kernelsmith
9/24/2013 - 8:48 PM

Ruby tricks, tips, and one-liners Convert hex data to hex string, convert file contents to base64, machine sortable, but still human-readabl

Ruby tricks, tips, and one-liners Convert hex data to hex string, convert file contents to base64, machine sortable, but still human-readable time stamps, mash two arrays into a hash where one array is hash keys (esp CSV parsing), timeouts, zip files

#
# One-liners (or one'ish-liners)
#

# remove all gem documentation (from shell):
rm -rf "$(gem env gemdir)"/doc/*

### CONVERT a hex file to hex string
# for_testing$ echo -n "DEADBEEFDEADBEEF" > tmp 
File.open("tmp", "rb") {|f| [f.read].pack("H*")} 
# => "\xDE\xAD\xBE\xEF\xDE\xAD\xBE\xEF"

### CONVERT to base64 (note .encode and .strict_encode can have different results)
require 'base64' && File.open("tmp", "rb") {|f| Base64.strict_encode64(f.read)}
# => "REVBREJFRUZERUFEQkVFRg==\n"

### sweet TIMESTAMP, nicely formatted & machine sortable, good for file names esp the 2nd one.
require 'time' # yes this is required.  To access the .utc method iirc
Time.now.utc.iso8601  # => "2013-03-27T21:40:19Z"
Time.now.utc.iso8601.gsub(':','-')  # => "2013-03-27T21-40-19Z"

### one line WEBSERVER, like python -m SimpleHTTPServer port
ruby -run -e httpd -- [-p port] DocumentRoot

### CONVERT 2 ARRAYS TO A HASH
a1 = [1,2,3]
a2 = ["one", "two", "three"]
h = Hash[a1.zip(a2)]

# => {1=>"one", 2=>"two", 3=>"three"}
# or as a true one-liner, tho more confusing:
Hash[ [1,2,3].zip(["one", "two", "three"]) ]
# this is especially useful when you are reading lines from a file, like a CSV file and want to map items to the column title:
rows_as_hashes = []
columns = [:last, :first, :age]
CSV.read_lines do |line|
  rows_as_hashes << Hash[ columns.zip(line) ] # <= {:age=>69, :first=>"James", :last=>"Smith"}  etc.
end

#
# Tips & Tricks
#

### basic usage of timeouts
require 'timeout'
timeout = 10 # in seconds
buffer = ''
io = SomeFakeIo.new
begin
  Timeout.timeout(timeout) do
    ret = nil
    # do stuff that might timeout
    io.read
  end
  return ret
rescue ::Timeout::Error #, Rex::TimeoutError as well if Metasploit (lib/rex/exceptions.rb)
  puts "Timeout Error message"
  return nil
rescue ::OtherException => e
  raise e
ensure
  io.close if io
end

### create zip files in memory
# credit: http://www.devinterface.com/blog/en/2010/02/create-zip-files-on-the-fly/
def create_zip(file_list, filename = nil, &block)
  if !file_list.blank?
    # require 'time' is assumed from above
    stamp = Time.now.utc.iso8601.gsub(':','-') || "tmp"
    filename ||= "#{stamp}.zip"
    Tempfile.open(stamp) do |t|
      Zip::ZipOutputStream.open(t.path) do |z|
        file_list.each do |f|
          z.put_next_entry(f)
            z.print IO.read(f) # this could use some error handling
          end
        end
        # Do something with t now.  If you're emailing this from Rails you can:
        # send_file t.path, :type => 'application/zip',:disposition => 'attachment',:filename => file_name
        
        # But I want to save it to disk, we can use a block form
        if block_given?
          yield t
        else
          blah
        end
      end
    end
  end
end

# convert ascii string into 4-byte hex string groupings like "0x41424345"
# highest nibble first
s = "string";s.unpack('H*').first.scan(/[0-9A-Fa-f]{1,8}/).map {|i| "0x#{i}"}.join(" ")
# this could be improved in many ways.