Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

[CLASS] Base64 - Base64 encoder / decoder


  • Please log in to reply
9 replies to this topic
just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011

!!! Out of support for the time being !!!

 

 

Just a Class version of SKAN's Base64enc() / Base64dec() - Base64 encoder / decoder, tested with AHK U64 also.

Note: You may safely use the ANSI version of CryptBinaryToString with Unicode builds and save a lot of space.

Class_Base64.ahk:

; ======================================================================================================================
; Namespace:   Base64
; AHK version: AHK 1.1.+ (required)
; Function:    Methods for Base64 en/decoding.
; Language:    English
; Tested on:   Win XPSP3, Win VistaSP2 (U32) / Win 7 (U64)
; Version:     1.0.00.00/2012-08-12/just me
; URL:         http://msdn.microsoft.com/en-us/library/windows/desktop/aa380252(v=vs.85).aspx
; Remarks:     The ANSI functions are used by default to save space. ANSI needs about 133 % of the original size for
;              encoding, whereas Unicode needs about 266 %.
; ======================================================================================================================
; This software is provided 'as-is', without any express or implied warranty.
; In no event will the authors be held liable for any damages arising from the use of this software.
; ======================================================================================================================
Class Base64 {
   ; CRYPT_STRING_BASE64 = 0x01
   ; ===================================================================================================================
   ; Base64.Encode()
   ; Parameters:
   ;    VarIn  - Variable containing the input buffer
   ;    SizeIn - Size of the input buffer in bytes
   ;    VarOut - Variable to receive the encoded buffer
   ;    Use    - Use ANSI (A) or Unicode (W) function
   ;             Default: A
   ; Return values:
   ;    On success: Number of bytes copied to VarOut, not including the terminating null character
   ;    On failure: False
   ; Remarks:
   ;    VarIn may contain any binary contents including NUll bytes.
   ; ===================================================================================================================
   Encode(ByRef VarIn, SizeIn, ByRef VarOut, Use = "A") {
      Static Codec := 0x01 ; CRYPT_STRING_BASE64
      If (Use <> "W")
         Use := "A"
      Enc := "Crypt32.dll\CryptBinaryToString" . Use
      If !DllCall(Enc, "Ptr", &VarIn, "UInt", SizeIn, "UInt", Codec, "Ptr", 0, "UIntP", SizeOut)
         Return False
      VarSetCapacity(VarOut, SizeOut << (Use = "W"), 0)
      If !DllCall(Enc, "Ptr", &VarIn, "UInt", SizeIn, "UInt", Codec, "Ptr", &VarOut, "UIntP", SizeOut)
         Return False
      Return SizeOut << (Use = "W")
   }
   ; ===================================================================================================================
   ; Base64.Decode()
   ; Parameters:
   ;    VarIn  - Variable containing a null-terminated Base64 encoded string
   ;    VarOut - Variable to receive the decoded buffer
   ;    Use    - Use ANSI (A) or Unicode (W) function
   ;          Default: A
   ; Return values:
   ;    On success: Number of bytes copied to VarOut
   ;    On failure: False
   ; Remarks:
   ;    VarOut may contain any binary contents including NUll bytes.
   ; ===================================================================================================================
   Decode(ByRef VarIn, ByRef VarOut, Use = "A") {
      Static Codec := 0x01 ; CRYPT_STRING_BASE64
      If (Use <> "W")
         Use := "A"
      Dec := "Crypt32.dll\CryptStringToBinary" . Use
      If !DllCall(Dec, "Ptr", &VarIn, "UInt", 0, "UInt", Codec, "Ptr", 0, "UIntP", SizeOut, "Ptr", 0, "Ptr", 0)
         Return False
      VarSetCapacity(VarOut, SizeOut, 0)
      If !DllCall(Dec, "Ptr", &VarIn, "UInt", 0, "UInt", Codec, "Ptr", &VarOut, "UIntP", SizeOut, "Ptr", 0, "Ptr", 0)
         Return False
      Return SizeOut
   }
}

Sample.ahk:

#NoEnv
#Include Class_Base64.ahk
String := "Lorem ipsum dolor sit amet consectetuer pede eros tortor Vestibulum Aliquam. Id eget orci sed lobortis "
        . "felis urna Donec suscipit nibh id. Tellus semper Nulla pretium et nibh diam venenatis wisi cursus "
        . "adipiscing. Hendrerit lacinia ut laoreet quis a cursus Sed justo Nunc In. Tincidunt accumsan hac hac id "
        . "non eleifend Vivamus Fusce risus ac. Elit nec nec."
Bytes := StrLen(String) << !!A_IsUnicode
Encoded := Decoded := ""
If !(SizeE := Base64.Encode(String, Bytes, Encoded, "A"))
   Encoded := "Base64.Encode failed!"
Else If !(SizeD := Base64.Decode(Encoded, Decoded, "A"))
   Decoded := "Base64.Decode failed!"
Gui, Margin, 20, 20
Gui, Font, s9, Courier New
Gui, Add, Text, xm cNavy, Original (Size = %Bytes% bytes)
Gui, Add, Text, xm y+5 w800, %String%
Gui, Add, Text, xm cNavy, Encoded (Size = %SizeE% bytes)
Gui, Add, Text, xm y+5 w800, %Encoded%
Gui, Add, Text, xm cNavy, Decoded (Size = %SizeD% bytes)
Gui, Add, Text, xm y+5 w800, √ěcoded%
Gui, Show, , Class Base64 Sample
Return
GuiClose:
GuiEscape:
ExitApp

Prefer ahkscript.org for the time being.


iDrug
  • Members
  • 389 posts
  • Last active: Oct 11 2015 09:24 PM
  • Joined: 13 Oct 2009

did I get it right, that it works only with text strings, not files (especially graphics)?



just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011

Works with binary content, too.


Sorry, I've just edited the original post and lost all indentations, but got unwanted line numbers instead.

I'm getting somewhat frustrated. icon_cry.gif


Prefer ahkscript.org for the time being.


iDrug
  • Members
  • 389 posts
  • Last active: Oct 11 2015 09:24 PM
  • Joined: 13 Oct 2009

can I use an image file encoded using base64 to a text string as the InputImage argument for, say, the ImageSearch command?

do I have to decode a base64 string into a file first to be saved on the disk? or can I just set that base64 string as a value of a variable, so I could use that variable as the InputImage argument?



tmplinshi
  • Members
  • 245 posts
  • Last active: Mar 12 2015 02:29 PM
  • Joined: 06 Apr 2012

Strange result:

url := "Y2FjaGVmaWxlMTEucmF5ZmlsZS5jb20vemgtY24vZG93bmxvYWQvMjhkZWZjMzZiMDA3ZTA0NmQ3NDFjNDkwZDZiMjE0MjQvWFRNLkRWRC1IQUxGQ0QyLiVFNiVCMCVCNCVFNCVCOCVBRCVFNSVBNSVCMyVFNSVBNiU5Ni5MYWR5LkluLlRoZS5XYXRlci4yMDA2LiVFNyVCRSU4RSVFNSU5QiVCRC5DRDEubWt2fDIwNDYzNTIzMw=="
Base64.Decode(url, url_Decoded)
MsgBox, %url_Decoded%
MsgBox, "%url_Decoded%"			; <-------- This line has no result
MsgBox, % result := url_Decoded		; <-------- This line has no result, too.


just me
  • Members
  • 1496 posts
  • Last active: Nov 03 2015 04:32 PM
  • Joined: 28 May 2011

Base64.Decode() cannot know whether the decoded result will be a string or not. So you should use VarSetCapacity(Decoded, -1) to adjust the internally stored buffer length.

#NoEnv
#Include Class_Base64.ahk
url := "Y2FjaGVmaWxlMTEucmF5ZmlsZS5jb20vemgtY24vZG93bmxvYWQvMjhkZWZjMzZiMDA3ZTA0NmQ3NDFjNDkwZDZiMjE0MjQvWFRNLkRWRC1IQUxGQ0QyLiVFNiVCMCVCNCVFNCVCOCVBRCVFNSVBNSVCMyVFNSVBNiU5Ni5MYWR5LkluLlRoZS5XYXRlci4yMDA2LiVFNyVCRSU4RSVFNSU5QiVCRC5DRDEubWt2fDIwNDYzNTIzMw=="
Base64.Decode(url, url_Decoded)
VarSetCapacity(url_Decoded, -1)
MsgBox, %url_Decoded%
MsgBox, "%url_Decoded%"

Your encoded string is valid only for AHK ANSI.


Prefer ahkscript.org for the time being.


tmplinshi
  • Members
  • 245 posts
  • Last active: Mar 12 2015 02:29 PM
  • Joined: 06 Apr 2012

Thanks for help.



loadingx86
  • Members
  • 7 posts
  • Last active: May 04 2017 02:23 AM
  • Joined: 16 Jun 2014

shouldn't there be a different encoded string ? like this:  aGVsbG8gd29ybGQ=

SBLxwnH.png



jjohnston2
  • Members
  • 13 posts
  • Last active: Aug 23 2015 07:20 AM
  • Joined: 03 Aug 2012

For anyone who comes across this, there are a few issues with this class, not all of which I've figured out. 

  • If you want the readable text instead of Chinese characters, as requested in the previous post, use the Unicode string format (i.e., "W" option).  This doubles the reported string size which is now Unicode but yields what appears to be the proper text output.
  • There are also issues with reading the variables out of memory after the DLL modifies them
  • On the encode routine, one correction I found that helped was calling VarSetCapacity with a -1 option to update the encoded text with the proper string length
  • On the decode side, that doesn't seem to do the trick, although probably in both cases it's doing the same thing and for my particular application there's a binary null in the decoded binary that is causing the string to appear much shorter even though the contents are in memory (the help files specifically state this can happen, and it would be what I suspect is happening even if it weren't in the help files).  I haven't figured out how to work around this yet although a manual read of the memory locations using numget may be in order.
  • There is also a discrepancy between the VarSetCapacity calls in Encode (correct) vs. Decode (incomplete).  This was probably an oversight and was incorrectly re-coded since it is done properly in the original SKAN DLL calls
  • There are also other differences between the original DLL calls used, although I haven't determined if they're critical or not

Long story short, be warned if you expect this code to "just work".  The examples worked just fine for me but using it in my application to date has not.



space
  • Members
  • 520 posts
  • Last active:
  • Joined: 12 Aug 2014
There is a warning in the first post :-) You may check https://github.com/a...pt/libcrypt.ahkfor more recent implementations of base64