'Author: Scott Slater 'Source: http://www.powerbasic.com/support/forums/Forum7/HTML/001291.html ' ' --------------------------------------------------------- ' Local Function Called by Base64Dec ' --------------------------------------------------------- Function CvtNvtByte(ByVal x As Long) As Long Local rtn As Long ! push eax ; save eax since we alter it ! push ebx ; save ebx since we alter it ! mov eax, x ; get byte into eax ! and eax, 255 ; clear other bytes ! cmp eax, 64 ; see if its an upper case letter ! jle CvtNvtCheck47 ; if not check to see if its = 43 ! cmp eax, 91 ; can't be bigger than 90 ! jge CvtNvtCheck96 ; otherwize not what we thought ! sub eax, 65 ; subtract 65 from the original ! mov rtn, eax ; return that value to caller ! jmp CvtNvtDone ; leave the function CvtNvtCheck96: ! cmp eax, 96 ; looking for lower case letters ! jle CvtNvtRtn63 ; return 63 ! cmp eax, 123 ; see if we're less then 123 ! jge CvtNvtRtn63 ; return 63 ! sub eax, 71 ; subtract 71 and ! mov rtn, eax ; return it to the caller ! jmp CvtNvtDone ; leave the function CvtNvtCheck47: ! cmp eax, 47 ; see if its a /, 0-9 ! jle CvtNvtCheck43 ; see if its a + next ! cmp eax, 58 ; no more than 57 acceptable ! jge CvtNvtRtn63 ; return 63 ! add eax, 4 ; add 4 to eax ! mov rtn, eax ; return it to the caller ! jmp CvtNvtDone ; leave the function CvtNvtCheck43: ! cmp eax, 43 ; see if its a + sign ! jne CvtNvtRtn63 ; if not do next check ! mov ebx, 62 ; return value 62 ! mov rtn, ebx ; to the caller ! jmp CvtNvtDone ; exit function CvtNvtRtn63: ! mov ebx, 63 ; return 63 for any other bytes ! mov rtn, ebx ; not specified CvtNvtDone: ! pop ebx ; restore original ebx ! pop eax ; restore original eax Function = rtn ' Pass Return Value to caller End Function ' --------------------------------------------------------- ' BASE64 Decoding Routine: Returns 1 on Error ' 0 for Success ' --------------------------------------------------------- Function Base64Dec Alias "Base64Dec"(StringIn As Asciiz, StringOut As Asciiz , _ ByVal OutStrLen As Long) Export As Long Local rtn As Long ! push ebx ; save ebx ! push esi ; save esi ! push edi ; save edi ! mov esi, StringIn ; input buffer address ! and esi, esi ; null ptr check ! jz Base64DecDone ; exit function ! mov edi, StringOut ; output buffer address ! and edi, edi ; null ptr check ! jz Base64DecDone ; exit function ! xor ebx, ebx ; zero ebx ! xor ecx, ecx ; zero ecx ! xor edx, edx ; zero edx Base64DecLoop: ! xor eax, eax ; zero eax register ! mov bl, [esi] ; get character from input ! cmp bl, 0 ; see if it's a null terminator ! je Base64DecDone ; if so then exit function ! push ebx ; parameter for next call ! call CvtNvtByte ; call the function ! shl al, 2 ; shift bits in result left by 2 ! mov ecx, eax ; save it to ecx ! mov bl, [esi+1] ; get next char from input ! push ebx ; parameter for call ! call CvtNvtByte ; call function ! shr al, 4 ; shift result bits right by 4 ! or ecx, eax ; or result 1 with result 2 ! mov edx, ecx ; save ecx to edx ! mov bl, [esi+2] ; get third letter ! cmp bl, 61 ; see if its an = sign ! je Base64DecBC1 ; append it to the output buffer ! mov bl, [esi+1] ; get second letter ! push ebx ; paramter for call ! call CvtNvtByte ; call function ! shl al, 4 ; shift result left by 4 ! mov ecx, eax ; save the result in ecx ! mov bl, [esi+2] ; get the 3rd char from input ! push ebx ; set it as parameter for call ! call CvtNvtByte ; call the function ! shr al, 2 ; shift the result right by 2 ! or ecx, eax ; or reslult 2 with result 3 ! mov dh, cl ; save it in dh ! mov bl, [esi+3] ; get 4th char from input ! cmp bl, 61 ; see if its an = sign ! je Base64DecBC2 ; append it to the output buffer ! mov bl, [esi+2] ; get 3rd char ! push ebx ; set it as param for call ! call CvtNvtByte ; call the function ! shl al, 6 ; shift result left 6 ! mov ecx, eax ; save it to ecx ! mov bl, [esi+3] ; get the 4th char ! push ebx ; set it as parameter for call ! call CvtNvtByte ; call the function ! or ecx, eax ; or it with the modified third ! jmp Base64DecBC3 ; process the output Base64DecBC1: ! mov [edi], dl ; write byte to output ! inc edi ; update the pointer ! mov eax, 1 ; set an error code ! cmp edi, OutStrLen ; see if we're out of buffer space ! je Base64DecDone ; if so exit ! add esi, 4 ; prepare for next block ! jmp Base64DecLoop ; go back for more Base64DecBC2: ! mov [edi], dl ; write byte to output ! inc edi ; update the pointer ! mov eax, 1 ; set an error code ! cmp edi, OutStrLen ; see if we're out of buffer space ! je Base64DecDone ; if so exit ! shr edx, 8 ; move dh to dl ! jmp Base64DecBC1 ; process the last char Base64DecBC3: ! mov eax, edx ; copy edx to eax ! shr edx, 8 ; move dh to dl ! mov dh, cl ; copy cl to dh ! mov [edi], al ; write byte to output ! inc edi ; move pointer up 1 ! mov eax, 1 ; set an error code ! cmp edi, OutStrLen ; see if we're out of buffer space ! je Base64DecDone ; if so exit ! jmp Base64DecBC2 ; process remaining 2 bytes Base64DecDone: ! pop edi ; restore edi ! pop esi ; restore esi ! pop ebx ; restore ebx ! cmp eax, 1 ; see if we have an error ! je Base64DecError ! jmp Base64DecExit Base64DecError: ! mov rtn, eax ; save our return value in rtn Function = rtn ' and return it to caller. Base64DecExit: End Function ' --------------------------------------------------------- ' BASE64 Encoding Routine: Returns 0 for success, ' Non-Zero for Error Code ' ' Err Codes: 1 = OutPut Buffer Null Ptr Error ' 2 = InPut Buffer Null Ptr Error ' 4 = OutPut Buffer Too Short! ' --------------------------------------------------------- Function Base64Enc Alias "Base64Enc"(StringIn As Asciiz, StringOut As Asciiz, _ ByVal OutStrLen As Long) Export As Long Local rtn As Long ! push ebx ; save ebx ! push esi ; save esi ! push edi ; save edi ! mov ecx, StringOut ; pointer to output buffer ! push ecx ; save the address in case of err ! mov eax, 1 ; Null pointer error code ! and ecx, ecx ; check for null pointer ! jz Base64EncDone ; if so get out ! mov edi, StringIn ; pointer to input buffer ! mov eax, 2 ; Null pointer error code ! and edi, edi ; see if its a null pointer ! jz Base64EncDone ; if so get out ! xor esi, esi ; zero esi Base64GetLen: ! mov al, [edi+esi] ; get a character into al ! inc esi ; increment the len counter ! cmp al, 0 ; see if it is a zero terminator ! jne Base64GetLen ; get another character ! dec esi ; adjust the len counter ! mov edx, esi ; update the edx ! lea ebx, Base64_Nvt ; load translation table to ebx Base64EncTop: ! xor eax, eax ; error code 0 ! cmp edx, 0 ; see if we're at the end ! je Base64EncDone ; if so then exit function ! mov al, [edi] ; get character into al ! shr al, 2 ; Shift Right 2 bits ! xlatb ; translate the character ! mov [ecx], al ; save it ! inc ecx ; move pointer up 1 ! pop eax ; get original address of output ! push eax ; save it again ! mov esi, ecx ; get current Output pos ! sub esi, eax ; get current output len ! mov eax, 4 ; error code into eax ! add esi, 4 ; translate it to len ! cmp esi, OutStrLen ; see if we've reached the limit ! jge Base64EncDone ; if so exit with an error ! mov al, [edi+1] ; read char2 into al ! mov ah, [edi] ; read char1 into ah ! shr ax, 4 ; shift it all r by 4 ! and al, &H3F ; and the low byte w/0x3F ! xlatb ; translate the low bit ! mov [ecx], al ; save it ! inc ecx ; move pointer up 1 ! cmp edx, 1 ; see which position we are in ! jne Base64EncSec2 ; jump to section 2 ! mov al, 61 ; append the == to end ! mov [ecx], al ; save it once ! inc ecx ; move the pointer up ! mov [ecx], al ; save it once more ! mov al, 61 ; 2nd = sign ! inc ecx ; up the pointer again ! xor eax, eax ; return error code 0 ! jmp Base64EncDone ; exit the function Base64EncSec2: ! mov al, [edi+2] ; read the 3rd char into al ! mov ah, [edi+1] ; read the 2nd char into ah ! shr ax, 6 ; shift it all right 6 bits ! and al, &H3F ; and the low byte w/0x3F ! xlatb ; translate the char ! mov [ecx], al ; save it to output buffer ! inc ecx ; move output buff ptr up ! cmp edx, 2 ; see if were at pos 2 ! jne Base64EncSec3 ; if not jump to section 3 ! mov al, 61 ; otherwise add an = to end ! mov [ecx], al ; save it ! inc ecx ; update the pointer ! xor eax, eax ; return error code 0 ! jmp Base64EncDone ; exit the function Base64EncSec3: ! mov al, [edi+2] ; read 3rd char into al ! and al, &H3F ; and it with 0x3F ! xlatb ; translate it ! mov [ecx], al ; save it ! inc ecx ; update output pointer ! add edi, 3 ; prepare for next block of chars ! sub edx, 3 ; move input string pointer down ! jmp Base64EncTop ; go back to the top for next block Base64_Nvt: ! db 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90 ! db 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122 ! db 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47 Base64EncDone: ! pop esi ; recall original output addr (ecx) ! cmp eax, 0 ; see if an error got us here ! jne Base64Error ; yep so handle it ! mov [ecx], al ; save null terminator ! mov rtn, eax ; return error code ! jmp Base64ExitProc ; exit the proceedure Base64Error: ! mov rtn, eax ; return error code ! and eax, 3 ; see if it was a null ptr error ! jnz Base64ExitProc ; exit directly ! xor eax, eax ; zero eax ! mov [esi], al ; write a null terminator Base64ExitProc: ! pop edi ; restore edi ! pop esi ; restore esi ! pop ebx ; restore ebx Function = rtn ' return code to caller End Function