-- NAME: Base64 -- TYPE: Movie Script - Not fully openLingo compliant -- VERSION: 1.11 -- -- DESCRIPTION -- -- Functions for base64 encoding and decoding -- -- USAGE -- -- encodedString = base64encode( aBinaryString [, aNoWrap, aUrlSafe] ) -- -- binaryString = base64decode( aEncodedString [, aUrlSafe ] ) -- -- AUTHORS -- -- Robert Tweed -- -- HISTORY -- -- 2003-11-27: v1.11 - Robert Tweed: -- Bug in URL safe version fixed -- -- 2003-11-16: v1.1 - Robert Tweed: -- Massive overhaul of code and comments -- Added "omit line-wrap" option for encoding -- Added "URL safe" options for both -- -- 202-05-14: v1.0 - Robert Tweed --------------------------------------------------------------------------------- -- NAME -- -- base64encode -- -- DESCRIPTION -- -- Encode data using base-64 -- Capable of operating in RFC 2045 compliant mode, or "URL safe" mode -- "URL safe" mode is a nonstandard mode designed for use in URL querystrings. -- -- PARAMETERS -- -- aBinaryString - Any string data -- -- aNoWrap (optional) - If set to anything other than false then line wrapping will not occur -- Default is false in compliance with RFC 2045. -- -- aUrlSafe (optional) - If set to anything other than false then "URL safe" mode is used. -- This is a nonstandard mode that can be used in URLs without additional -- URL encoding. Default is false for compliance with RFC 2045. -- -- RETURNS -- -- Base-64 encoded string. -- -- USAGE -- -- Encode some data using RFC 2045 compliant base-64 -- -- encodedString = base64encode( aBinaryString ) -- -- Encode some data using semi-compliant base-64, no line wrapping. -- Note that this encoding is perfectly compliant for the purposes of decoding, but may -- not be compatible with some transports and is therefore forbidden by RFC 2045 -- This mode is most useful for saving files with fileio. -- -- encodedString = base64encode( aBinaryString, true ) -- -- Encode some data using fully "URL safe" mode. -- "URL safe" data can be used in URLs without additional URL encoding. -- -- encodedString = base64encode( aBinaryString, true, true ) -- on base64encode aBinaryString, aNoWrap, aUrlSafe -- Define the lookup table according to whether we are using -- "URL safe" mode or RFC 2045-compliant mode: if( aUrlSafe = 0 ) then vBase64Lookup = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" vTrail = "=" else vBase64Lookup = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" vTrail = "." end if -- Initialise everything else... vOutput = "" vIndex = 1 vTrailingBytes = aBinaryString.length mod 3 vLengthWhole = aBinaryString.length - (vTrailingBytes) -- Store all the complete quanta... repeat while vIndex < vLengthWhole vByte1 = charToNum( aBinaryString.char[ vIndex ] ) vByte2 = charToNum( aBinaryString.char[ vIndex + 1 ] ) vByte3 = charToNum( aBinaryString.char[ vIndex + 2 ] ) vChar1 = vBase64Lookup.char[ ( bitAnd( vByte1, 252 ) / 4 ) + 1 ] vChar2 = vBase64Lookup.char[ ( bitAnd( (vByte1*256)+vByte2, 1008 ) / 16 ) + 1 ] vChar3 = vBase64Lookup.char[ ( bitAnd( (vByte2*256)+vByte3, 4032 ) / 64 ) + 1 ] vChar4 = vBase64Lookup.char[ ( bitAnd( vByte3, 63 ) ) + 1] put vChar1 & vChar2 & vChar3 & vChar4 after vOutput vIndex = vIndex + 3 -- Wrap at 76 characters if( aNoWrap = 0 ) then if( ((vIndex-1) mod 57) = 0 ) then put RETURN after vOutput end if end repeat -- Store any partial quanta at the end.... if( vTrailingBytes = 1 ) then -- Partial quanta containing a single byte... vByte1 = charToNum( aBinaryString.char[ vIndex ] ) vChar1 = vBase64Lookup.char[ ( bitAnd( vByte1, 252 ) / 4 ) + 1 ] vChar2 = vBase64Lookup.char[ ( bitAnd( vByte1*256, 1008 ) / 16 ) + 1 ] vChar3 = vTrail vChar4 = vTrail put vChar1 & vChar2 & vChar3 & vChar4 after vOutput else if ( vTrailingBytes = 2 ) then -- Partial quanta containing two bytes... vByte1 = charToNum( aBinaryString.char[ vIndex ] ) vByte2 = charToNum( aBinaryString.char[ vIndex + 1 ] ) vChar1 = vBase64Lookup.char[ ( bitAnd( vByte1, 252 ) / 4 ) + 1 ] vChar2 = vBase64Lookup.char[ ( bitAnd( (vByte1*256)+vByte2, 1008 ) / 16 ) + 1 ] vChar3 = vBase64Lookup.char[ ( bitAnd( vByte2*256, 4032 ) / 64 ) + 1 ] vChar4 = vTrail put vChar1 & vChar2 & vChar3 & vChar4 after vOutput end if -- All done! return vOutput end --------------------------------------------------------------------------------- -- NAME -- -- base64decode -- -- DESCRIPTION -- -- Decode base-64 encoded data to a binary string -- Capable of operating in RFC 2045 compliant mode, or "URL safe" mode -- "URL safe" mode is a nonstandard mode designed for use in URL querystrings. -- -- PARAMETERS -- -- aEncodedString - The encoded data -- -- aUrlSafe (optional) - Any nonzero value specifies that the data is encoded -- in "URL safe" form. Otherwise RFC 2045 standard encoding -- is assumed. Neither is backwards comptible with the other. -- -- RETURNS -- -- Decoded binary string - may contain NULs -- -- USAGE -- -- Decode a standard base-64 encoded string: -- -- binaryString = base64decode( aEncodedString ) -- -- Decode a standard URL safe base-64 encoded string: -- -- binaryString = base64decode( aEncodedString, true ) -- on base64decode aEncodedString, aUrlSafe -- Define the majority of the reverse lookup table: vBase64Lookup = [ "A":0, "B":1, "C":2, "D":3, "E":4, "F":5, "G":6, "H":7, "I":8, \ "J":9, "K":10, "L":11, "M":12, "N":13, "O":14, "P":15, "Q":16, "R":17, "S":18, \ "T":19, "U":20, "V":21, "W":22, "X":23, "Y":24, "Z":25, "a":26, "b":27, "c":28, \ "d":29, "e":30, "f":31, "g":32, "h":33, "i":34, "j":35, "k":36, "l":37, "m":38, \ "n":39, "o":40, "p":41, "q":42, "r":43, "s":44, "t":45, "u":46, "v":47, "w":48, \ "x":49, "y":50, "z":51, "0":52, "1":53, "2":54, "3":55, "4":56, "5":57, "6":58, \ "7":59, "8":60, "9":61 ] -- Set the unsafe characters according to whether we are using -- "URL safe" mode or RFC 2045-compliant mode: if( aUrlSafe = 0 ) then vBase64Lookup[ "+" ] = 62 vBase64Lookup[ "/" ] = 63 else vBase64Lookup[ "-" ] = 62 vBase64Lookup[ "_" ] = 63 end if -- Initialise everything else... vOutput = "" vQuanta = [] -- Read all the input bytes and reconstruct any complete quanta... repeat with vIndex = 1 to aEncodedString.length ch = vBase64Lookup.getaProp( aEncodedString.char[ vIndex ] ) if not VoidP( ch ) then vQuanta.add( ch ) if( vQuanta.count = 4 ) then vByte1 = numToChar( bitAnd( (vQuanta[1]*64)+vQuanta[2], 4080 ) / 16 ) vByte2 = numToChar( bitAnd( (vQuanta[2]*64)+vQuanta[3], 1020 ) / 4 ) vByte3 = numToChar( bitAnd( (vQuanta[3]*64)+vQuanta[4], 255 ) ) put vByte1 & vByte2 & vByte3 after vOutput vQuanta = [] end if end repeat -- Get partial quanta from end of stream, if any... if( vQuanta.count = 3 ) then vByte1 = numToChar( bitAnd( (vQuanta[1]*64)+vQuanta[2], 4080 ) / 16 ) vByte2 = numToChar( bitAnd( (vQuanta[2]*64)+vQuanta[3], 1020 ) / 4 ) put vByte1 & vByte2 after vOutput else if( vQuanta.count = 2 ) then vByte1 = numToChar( bitAnd( (vQuanta[1]*64)+vQuanta[2], 4080 ) / 16 ) put vByte1 after vOutput end if -- All done! return vOutput end