-- License: Same as Nmap--See http://nmap.org/book/man-legal.html
-- Author: Thomas Buchanan <tbuchanan@thecompassgrp.net>
module(...,package.seeall)

require 'stdnse'
require 'bit'

--
-- b64.encode(string)
--

-- returns a base64 encoded version of the input string
encode = function(str)
 -- create the translation table
 local e = {"B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
  "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",
  "0","1","2","3","4","5","6","7","8","9","+","/"}
 e[0]="A"

 local a,b,c,d,w,x,y,z
 local r
 local output = ""
 while true do
  -- attempt to read 3 bytes
  local s = string.sub(str,1,3)
  -- if we didn't get anything, return
  if s == nil or string.len(s) == 0 then
   return output
  elseif string.len(s) == 3 then
   -- if all three bytes are present, convert to 4 6-bit numbers
   a,b,c = string.byte(s,1,3)
   d = bit.lshift(a,16) + bit.lshift(b,8) + c
   w = bit.arshift(d,18)
   x = bit.arshift(d,12) % (2^6)
   y = bit.arshift(d,6) % (2^6)
   z = d % (2^6)
   -- covert the 6-bit numbers to ASCII output, based on our translation table
   output = output .. e[w] .. e[x] .. e[y] .. e[z]
   -- remove the 3 bytes we've encoded, and move on
   str = string.sub(str, 4, -1)
  elseif string.len(s) == 2 then
   -- if only 2 bytes are present, we covert to 3 6-bit numbers, with 2 bits of padding on the right
   -- our output will be padded with one byte
   a,b = string.byte(s,1,2)
   d = bit.lshift(a,10) + bit.lshift(b,2)
   w = bit.arshift(d,12)
   x = bit.arshift(d,6) % (2^6)
   y = d % (2^6)
   z = "=" -- padding
   output = output .. e[w] .. e[x] .. e[y] .. z
   return output
  elseif string.len(s) == 1 then
   -- if only 1 byte is present, we covert to 2 6-bit numbers, with 4 bits of padding on the right
   -- our output will be padded with two bytes
   a = string.byte(s)
   d = bit.lshift(a,4)
   w = bit.arshift(d,6)
   x = d % (2^6)
   y = "=" -- padding
   z = "=" -- padding
   output = output .. e[w] .. e[x] .. y .. z
   return output
  end
 end -- while loop
end -- encode function
