/* * Copyright (c) 2003 Rozhuk Ivan <rozhuk.im@gmail.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #if !defined(AFX_BASE64__H__INCLUDED_) #define AFX_BASE64__H__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 //typedef unsigned char BYTE; // // BASE64 coding: // 214 46 138 // 11010100 00101110 10001010 // ! ! ! // ---------->>> convert 3 8bit to 4 6bit // 110101 000010 111010 001010 // 53 2 58 10 // this numbers is offset in array coding below... // //01234567890123456789012345 static BYTE *pbtCodingTableBASE64=(BYTE*)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; //52...63 static BYTE btDeCodingTableBASE64[256]={64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63,52,53,54,55,56,57,58,59,60,61,64,64,64,64,64,64,64,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64}; __inline void BASE64CopyUnSafe(LPCVOID lpcSource,LPCVOID lpcDestination,SIZE_T dwSize,SIZE_T *pdwCopyedSize) {// �������� ������ �64 ������� LPBYTE lpbSource,lpbDestination; lpbSource=(LPBYTE)lpcSource; lpbDestination=(LPBYTE)lpcDestination; while(dwSize--) { if ((*lpbSource)>32 && (*lpbSource)<128) (*lpbDestination++)=(*lpbSource); lpbSource++; } if (pdwCopyedSize) (*pdwCopyedSize)=((SIZE_T)lpbDestination-(SIZE_T)lpcDestination); } __inline DWORD BASE64EncodeUnSafe(LPCVOID lpcSource,SIZE_T dwSourceSize,LPCVOID lpcDestination,SIZE_T dwDestinationSize,SIZE_T *pdwEncodedSize) {// BASE64 ����������� DWORD dwRetErrorCode; SIZE_T dwEncodedSize=((dwSourceSize*4+11)/12*4+1);//(((dwSourceSize+2)/3)*4); if ((dwDestinationSize<dwEncodedSize)) {// �������� ������ ������� ��� dwRetErrorCode=ERROR_INSUFFICIENT_BUFFER; }else{// ������ ��������� ������� ���������� dwEncodedSize=0; if(lpcSource && lpcDestination && dwSourceSize) { #ifdef _WIN64 LPBYTE lpbtSource=(LPBYTE)lpcSource,lpbtDestination=(LPBYTE)lpcDestination; SIZE_T i; for (i=0;i<dwSourceSize;i+=3) { *(lpbtDestination++)=pbtCodingTableBASE64[(*lpbtSource)>>2]; // c1 *(lpbtDestination++)=pbtCodingTableBASE64[(((*lpbtSource)<<4)&060) | ((lpbtSource[1]>>4)&017)]; // c2 *(lpbtDestination++)=pbtCodingTableBASE64[((lpbtSource[1]<<2)&074) | ((lpbtSource[2]>>6)&03)]; // c3 *(lpbtDestination++)=pbtCodingTableBASE64[lpbtSource[2] & 077]; // c4 lpbtSource+=3; } // If dwSourceSize was not a multiple of 3, then we have encoded too many characters. Adjust appropriately. if(i==(dwSourceSize+1)) {// There were only 2 bytes in that last group lpbtDestination[-1]='='; }else if(i==(dwSourceSize+2)) {// There was only 1 byte in that last group lpbtDestination[-1]='='; lpbtDestination[-2]='='; } (*lpbtDestination)=0; dwEncodedSize=(lpbtDestination-((LPBYTE)lpcDestination)); #else __asm{ push ebx // ��������� ������� push edi // ��������� ������� push esi // ��������� ������� mov ebx,pbtCodingTableBASE64// ebx = ����� ������� ������������� mov ecx,dwSourceSize // ecx = ������ �������� ������� mov edi,lpcDestination // edi = ����� ��������� ������� mov esi,lpcSource // esi = ��������� �� ������� ������ cld jmp short read_loop_cmp //////////Code function/////////////////////////////////////////// // ������� ��������� // eax - �������� ������, ������������ ������ 3 ����� //in buff, 3 byte used // eax - ��������� ������, ������������ 4 ����� //out buff, 4 byte used code_func: // ������ ������ ������� ����������, // ������ ������� ��� ������� ����� bswap eax rol eax,6 shl al,2 ror eax,10 shr ax,2 shr al,2 xlat rol eax,8 xlat rol eax,8 xlat rol eax,8 xlat rol eax,8 bswap eax// 188-235 ret ////////////////////////////////////////////////////////////////// /////////////Read & converting cycle////////////////////////////// read_loop: lodsd // ������ 4 ����� dec esi // ���������� ������ 3 and eax,0x00FFFFFF //==================================================== // ������ ������ ������� ����������, // ������ ������� ��� ������� ����� bswap eax rol eax,6 shl al,2 ror eax,10 shr ax,2 shr al,2 xlat rol eax,8 xlat rol eax,8 xlat rol eax,8 xlat rol eax,8 bswap eax //==================================================== stosd sub ecx,3 read_loop_cmp: cmp ecx,3 // ���������, ����� ������ ���� ��� ������� 4 ����� jg short read_loop // ���� ������ 3 � ����� ����, �� ���������� ������ ///////////////////////////////////////////////////////////////// xor eax,eax // �������� ������� cmp ecx,3 // ���������� ������ � 3 je short tree_byte_tail// ���� ������ 3 �����, �� ��������� � ������� �������������� ������� ����� ������ cmp ecx,2 // ���������� ������ � 2 je short two_byte_tail // ���� ������ 2 �����, �� ��������� � ������� �������������� ������� ����� ������ // �����, ������ ������� ����� 1 //////////tail 1 byte//////////////////////////////////////////// mov al,byte ptr [esi] // ������ 1 ���� call code_func // ����������� and eax,0x0000FFFF // �������� ��������� ��� ����� or eax,0x3D3D0000 // ���������� � ��������� ��� ����� 61("=") jmp short end_tail_handler // //////////tail 2 byte//////////////////////////////////////////// two_byte_tail: mov ax,word ptr [esi] // ������ 2 ����� call code_func // ����������� and eax,0x00FFFFFF // �������� ��������� ���� or eax,0x3D000000 // ���������� � ��������� ���� 61("=") jmp short end_tail_handler // //////////tail 3 byte//////////////////////////////////////////// tree_byte_tail: lodsw ror eax,16 mov al,byte ptr [esi] // ������ 1 ���� rol eax,16 call code_func // ����������� end_tail_handler: stosd // ���������� 4 �����, ��� �������������� sub edi,lpcDestination // ��������� ����������� ����, ���������� � �������� ������ mov dwEncodedSize,edi // ���������� ����������� ���� � ������������ ���������� pop esi // ��������������� ���������� �������� pop edi // ��������������� ���������� �������� pop ebx // ��������������� ���������� �������� } #endif dwRetErrorCode=NO_ERROR; }else{ dwRetErrorCode=ERROR_INVALID_HANDLE; } } if (pdwEncodedSize) (*pdwEncodedSize)=dwEncodedSize; return(dwRetErrorCode); } __inline DWORD BASE64Encode(LPCVOID lpcSource,SIZE_T dwSourceSize,LPCVOID lpcDestination,SIZE_T dwDestinationSize,SIZE_T *pdwEncodedSize) {// BASE64 ����������� DWORD dwRetErrorCode; __try { dwRetErrorCode=BASE64EncodeUnSafe(lpcSource,dwSourceSize,lpcDestination,dwDestinationSize,pdwEncodedSize); }__except(EXCEPTION_EXECUTE_HANDLER){ dwRetErrorCode=ERROR_INVALID_ADDRESS; } return(dwRetErrorCode); } __inline DWORD BASE64DecodeUnSafe(LPCVOID lpcSource,SIZE_T dwSourceSize,LPCVOID lpcDestination,SIZE_T dwDestinationSize,SIZE_T *pdwDecodedSize) {// BASE64 ������������� DWORD dwRetErrorCode; SIZE_T dwDecodedSize=((dwSourceSize>>2)*3);// ((dwSourceSize/4)*3); if ((dwDestinationSize<dwDecodedSize)) {// �������� ������ ������� ��� dwRetErrorCode=ERROR_INSUFFICIENT_BUFFER; }else{// ������ ��������� ������� ���������� dwDecodedSize=0; if(lpcSource && lpcDestination) {// ������� � ������� if (dwSourceSize>3) { #ifdef _WIN64 LPBYTE lpbtSource=(LPBYTE)lpcSource,lpbtDestination=(LPBYTE)lpcDestination; for(SIZE_T i=0;i<dwSourceSize;i+=4) { *(lpbtDestination++)=(unsigned char) (btDeCodingTableBASE64[(*lpbtSource)] << 2 | btDeCodingTableBASE64[lpbtSource[1]] >> 4); *(lpbtDestination++)=(unsigned char) (btDeCodingTableBASE64[lpbtSource[1]] << 4 | btDeCodingTableBASE64[lpbtSource[2]] >> 2); *(lpbtDestination++)=(unsigned char) (btDeCodingTableBASE64[lpbtSource[2]] << 6 | btDeCodingTableBASE64[lpbtSource[3]]); lpbtSource+=4; } dwDecodedSize=(lpbtDestination-((LPBYTE)lpcDestination)); if ((*((BYTE*)lpcSource+(dwSourceSize-1)))=='=') dwDecodedSize--; if ((*((BYTE*)lpcSource+(dwSourceSize-2)))=='=') dwDecodedSize--; #else __asm{ push ebx // ��������� ������� push edi // ��������� ������� push esi // ��������� ������� mov ebx,offset btDeCodingTableBASE64// ebx = ����� ������� ������������� mov ecx,dwSourceSize // ecx = ������ �������� ������� mov edi,lpcDestination // edi = ����� ��������� ������� mov esi,lpcSource // esi = ��������� �� ������� ������ cld read_loop: lodsd // ������ 4 ����� //===============bit conversion==================================== // eax - �������� ������, ������������ ������ 4 ����� //in buff, 4 byte used // eax - ��������� ������, ������������ ������ 3 ����� //out buff, 3 byte used // ������ ������ ������� �������� ��� bswap eax ror eax,8 xlat ror eax,8 xlat ror eax,8 xlat ror eax,8 xlat shl al,2 shl ax,2 rol eax,10 shr al,2 ror eax,6 bswap eax mov edx,eax //234-250 //=============================================================== stosd dec edi sub ecx,4 cmp ecx,3 jg short read_loop sub edi,lpcDestination // ��������� ����������� ����, ���������� � �������� ������ mov dwDecodedSize,edi // ���������� ����������� ���� � ������������ ���������� pop esi // ��������������� ���������� �������� pop edi // ��������������� ���������� �������� pop ebx // ��������������� ���������� �������� } if ((*((BYTE*)lpcSource+(dwSourceSize-1)))=='=') dwDecodedSize--; if ((*((BYTE*)lpcSource+(dwSourceSize-2)))=='=') dwDecodedSize--; #endif dwRetErrorCode=NO_ERROR; }else{// �� ������� ������� ������� ���� ������ dwRetErrorCode=ERROR_INSUFFICIENT_BUFFER; } }else{ dwRetErrorCode=ERROR_INVALID_HANDLE; } } if (pdwDecodedSize) (*pdwDecodedSize)=dwDecodedSize; return(dwRetErrorCode); } __inline DWORD BASE64Decode(LPCVOID lpcSource,SIZE_T dwSourceSize,LPCVOID lpcDestination,SIZE_T dwDestinationSize,SIZE_T *pdwDecodedSize) {// BASE64 ������������� DWORD dwRetErrorCode; __try { dwRetErrorCode=BASE64DecodeUnSafe(lpcSource,dwSourceSize,lpcDestination,dwDestinationSize,pdwDecodedSize); }__except(EXCEPTION_EXECUTE_HANDLER){ dwRetErrorCode=ERROR_INVALID_ADDRESS; } return(dwRetErrorCode); } __inline DWORD BASE64DecodeFormated(LPCVOID lpcSource,SIZE_T dwSourceSize,LPCVOID lpcDestination,SIZE_T dwDestinationSize,SIZE_T *pdwDecodedSize) {// BASE64 ������������� � ������������� �������������� DWORD dwRetErrorCode; if (dwSourceSize<=dwDestinationSize) { BASE64CopyUnSafe(lpcSource,lpcDestination,dwSourceSize,&dwSourceSize); dwRetErrorCode=BASE64DecodeUnSafe(lpcDestination,dwSourceSize,lpcDestination,dwDestinationSize,pdwDecodedSize); }else{// �� ������� ������� ������� ���� ������ dwRetErrorCode=ERROR_INSUFFICIENT_BUFFER; } return(dwRetErrorCode); } #endif // !defined(AFX_BASE64__H__INCLUDED_)