Module: Watobo::Utils

Defined in:
lib/watobo/utils.rb,
lib/watobo/utils/strings.rb,
lib/watobo/utils/hexprint.rb,
lib/watobo/utils/load_chat.rb,
lib/watobo/utils/load_icon.rb,
lib/watobo/utils/check_regex.rb,
lib/watobo/utils/copy_object.rb,
lib/watobo/utils/secure_eval.rb,
lib/watobo/utils/expand_range.rb,
lib/watobo/utils/text2request.rb,
lib/watobo/utils/response_hash.rb,
lib/watobo/utils/file_management.rb,
lib/watobo/utils/response_builder.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.camelcase(string) ⇒ Object



24
25
26
# File 'lib/watobo/utils/strings.rb', line 24

def self.camelcase(string)
  string.strip.gsub(/[^[a-zA-Z\-_]]/,"").gsub( "-" , "_").split("_").map{ |s| s.downcase.capitalize }.join
end

.checkRegex(pattern) ⇒ Object



24
25
26
27
28
29
30
31
32
33
# File 'lib/watobo/utils/check_regex.rb', line 24

def Utils.checkRegex(pattern)
  begin
    # use nice string to test pattern ;)
    "watobo rocks!!!" =~ /#{pattern}/i
    return true
  rescue => bang
   # puts bang
    return false, bang
  end
end

.copyObject(object) ⇒ Object



24
25
26
27
# File 'lib/watobo/utils/copy_object.rb', line 24

def Utils.copyObject(object)
   copy = secure_eval(YAML.load(YAML.dump(object.inspect)))
    return copy
end

.expand_range(pattern) ⇒ Object

expand range creates an array out of



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/watobo/utils/expand_range.rb', line 25

def self.expand_range(pattern)
  vals = pattern.split(",")

  result = []
  vals.each do |v|
    v.strip!
    if v =~ /^(\d+)$/ then
      result.push $1.to_i
    elsif v =~ /^(\d+)-(\d+)$/
      start = $1
      stop = $2
      dummy = (start..stop).to_a
      result.concat dummy
    end
  end
  result.uniq!
  return result
end

.hexprint(data) ⇒ Object



24
25
26
27
28
29
# File 'lib/watobo/utils/hexprint.rb', line 24

def self.hexprint(data)
  data.length.times do |i|
    print "%02X" % data[i].ord
    puts if data[i] == "\n"
  end
end

.load_settings(file) ⇒ Object



43
44
45
46
47
48
49
# File 'lib/watobo/utils/file_management.rb', line 43

def Utils.load_settings(file)
  settings = nil
  if File.exists?(file) then
    settings = YAML.load_file(file)
  end
  return settings
end

.loadChat(path, id, request_pattern, response_pattern) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/watobo/utils/load_chat.rb', line 122

def Utils.loadChat(path, id, request_pattern, response_pattern)
  chat = nil
  req_file = File.join(path, "#{id}#{request_pattern}")
  res_file = File.join(path, "#{id}#{response_pattern}")
  #   puts "* load chat (request): #{req_file}"
  #   puts "* load chat (response): #{res_file}"
  request = []
  if File.exists?(req_file) then
    fh = File.open(req_file,"rb")
    fh.each do |line|  
      request.push line
    end
  else
    # puts "!! File not found (#{req_file})"
    return nil,nil
  end
  
  response = []
  # print "."
  # first only read header as array
  content_length = 0
  response_is_gzipped = false
  content_is_chunked = false
  max_response_size = 50000
  
  if File.exists?(res_file) then
    begin
      
      resFH = open(res_file, "rb")
      
      loop do
        l = resFH.readline
        if l =~ /Content-Length.* (\d*)/ then
          content_length = $1.to_i
          #puts "Content-Length is #{content_length}"
        end
        if l =~ /Content-Encoding.*gzip/ then
          response_is_gzipped = true
        end
        if l=~ /Transfer-Encoding.*chunked/i then
          content_is_chunked = true
        end
        response.push(l)
        # break if l.length < 3 # end of header
        break if l =~ /^\r\n$/ # end of header
      end    
      
      if content_is_chunked then
        # read rest of file
        response.push "\r\n"
        response.push resFH.read
        #content_length = dummy.chomp.hex
        return request, response
      end
    rescue => bang
      puts "Could not read Header from file #{res_file}"
    end
    # now read response body
    begin
      if response_is_gzipped and content_length > 0 then            
        gziped = resFH.read(content_length)
        begin
          gz = Zlib::GzipReader.new( StringIO.new( gziped ) )
          data = gz.read
          if data.length > max_response_size then
            data = data[0..max_response_size]
            puts "!!! chat file (#{res_file}: Response too long"
            # puts data
          end
          response.push data
        rescue => bang
          puts "ERROR: GZIP with file #{res_file}"
          puts bang
          #resFH.each do |l|
          #  response.push(l) if response.join.length < @max_response_size
          #end
        end
        return request, response
      end
      
      #resFH.each do |l|
      #  response.push(l) if response.join.length < max_response_size
      #end
      rest = resFH.read
      response.push(rest)
      
      return request, response
    rescue EOFError => bang
      return request, response
    rescue => bang
      puts "!!! Error: Could not read response file #{res_file}"
      puts bang
    end
    
  end
end

.loadChatYAML(file) ⇒ Object

loadChat returns a chat object imported from a yaml file



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/watobo/utils/load_chat.rb', line 26

def Utils.loadChatYAML(file)
  begin
    if File.exists?(file) then
      puts "LoadChatYAML: #{file}" if $DEBUG 
      cdata  = YAML.load(File.open(file,"rb").read)
      return nil unless cdata
      # need to restore CRLF
      cdata[:request].map!{|l| 
        if l =~ /^\"/ then
          x = secure_eval(l)
        else
          x = l.strip + "\r\n"
          x = l if l == cdata[:request].last
        end
        
        x
      }
      
      cdata[:response].map!{|l| 
        if l =~ /^\"/ then
          x = secure_eval(l)
        else
          x = l.strip + "\r\n"
          x = l if l == cdata[:response].last
        end   
        
        x
      }
      # puts cdata
      # puts cdata.class
      
      settings = Hash.new
      settings.update cdata
      settings.delete(:response)
      settings.delete(:request)
      
      chat = Watobo::Chat.new(cdata[:request], cdata[:response], settings)
      chat.file = file
      
      return chat
      
    else
      puts "* file #{file} not found"
      return nil
    end
  rescue Psych::SyntaxError
    puts "!!! Malformed File #{file}"
  rescue => bang
    puts "! could not load chat from file #{file}"
    puts cdata
    #puts bang
    #puts bang.backtrace if $DEBUG
  end
end

.loadFindingYAML(file) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/watobo/utils/load_chat.rb', line 82

def Utils.loadFindingYAML(file)
  puts "LoadFindingYAML: #{file}" if $DEBUG 
  if File.exists?(file) then
    begin
    fdata  = YAML.load(File.open(file,"rb").read)
    # need to restore CRLF
    return nil unless fdata
    fdata[:request].map!{|l| 
      if l =~ /^\"/ then
        x = secure_eval(l)
      else
        x = l.strip + "\r\n"
        x = l if l == fdata[:request].last
      end
      x
    }
    
    fdata[:response].map!{|l|
      if l =~ /^\"/ then
        x = secure_eval(l)
      else
        x = l.strip + "\r\n"
        x = l if l == fdata[:response].last
      end
      x
    }
    finding = Watobo::Finding.new(fdata[:request], fdata[:response], fdata[:details])
    
    return finding
  rescue => bang
    puts bang
    puts "could not load finding #{file}"
    return nil
    end
  else
    #   puts "* file #{file} not found"
    return nil
  end
end

.responseHash(request, response) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/watobo/utils/response_hash.rb', line 26

def Utils.responseHash(request, response)
  begin
    if request.body and response.body then
      #     request.extend Watobo::Mixin::Parser::Web10
      #     request.extend Watobo::Mixin::Shaper::Web10

      #     response.extend Watobo::Mixin::Parser::Web10
      #     response.extend Watobo::Mixin::Shaper::Web10

      body = response.body

      # remove all parm/value pairs
      request.get_parm_names.each do |p|
        body.gsub!(/#{Regexp.quote(p)}/, '')
        val = request.get_parm_value(p)
        body.gsub!(/#{Regexp.quote(val)}/, '')
      end
      request.post_parm_names.each do |p|
        body.gsub!(/#{Regexp.quote(p)}/, '')
        val = request.post_parm_value(p)
        body.gsub!(/#{Regexp.quote(val)}/, '')
      end
    # remove date format 01.02.2009
    body.gsub!(/\d{1,2}\.\d{1,2}.\d{2,4}/, "")
    # remove date format 02/2009
    body.gsub!(/\d{1,2}(.\|\/)d{2,4}/, "")
    #remove time
    body.gsub!(/\d{1,2}:\d{1,2}(:\d{1,2})?/, '')

    return body, Digest::MD5.hexdigest(body)

    elsif response.body then
    return body, Digest::MD5.hexdigest(response.body)
    else
    return nil
    end
  rescue => bang
  puts bang
  puts bang.backtrace if $DEBUG
  end
  return nil

end

.save_settings(file, settings) ⇒ Object

e.g, save_settings(“test-settings.test”, 0, “@saved_settings”, @saved_settings)



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/watobo/utils/file_management.rb', line 26

def Utils.save_settings(file, settings)
  begin
    if settings.is_a? Hash
      File.open(file, "w") { |fh|
        YAML.dump(settings, fh)
      }
      return true
    else
      return false
    end
  rescue => bang
    puts bang
    puts bang.backtrace if $DEBUG
  end
  return false
end

.saveChat(chat, filename) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/watobo/utils/file_management.rb', line 51

def Utils.saveChat(chat, filename)
  chat_data = {
    :request => chat.request.map{|x| x.inspect},
    :response => chat.response.map{|x| x.inspect},
  }
  
  chat_data.update(chat.settings)                
  if File.exists?(filename) then
    puts "Updating #{filename}"
    File.open(filename, "w") { |fh| 
      YAML.dump(chat_data, fh)
    }
    chat.file = filename
  end
end

.secure_eval(exp) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/watobo/utils/secure_eval.rb', line 25

def Utils.secure_eval(exp)
  result = nil
  t = Thread.new(exp) { |e|
    e.untaint
 #   $SAFE = 3
    $SAFE = 4 # does not work here
    begin
      
     result = eval(e)
     
  
    rescue SyntaxError => bang
      puts bang
  puts bang.backtrace if $DEBUG
    rescue LocalJumpError => bang
      puts bang
  puts bang.backtrace if $DEBUG
    rescue SecurityError => bang
      puts "WARNING: Desired functionality forbidden. it may harm your system!"
      puts bang.backtrace if $DEBUG
    rescue => bang
      puts bang
      puts bang.backtrace if $DEBUG
      
    end
  }
  t.join
  return result
 
end

.smartHash(orig_request, request, response) ⇒ Object

smart hashes are necessary for blind sql injections tests SmartHash means that all dynamic information is removed from the response before creating the hash value. Dynamic information could be date&time as well as parameter names and theire valuse.



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/watobo/utils/response_hash.rb', line 73

def Utils.smartHash(orig_request, request, response)
  begin
    if request and response.body then

      body = response.body.dup
      # remove possible chunk values
      body.gsub!(/\r\n[0-9a-fA-F]+\r\n/,'')
      # remove date format 01.02.2009
      body.gsub!(/\d{1,2}\.\d{1,2}.\d{2,4}/, "")
      # remove date format 02/2009
      body.gsub!(/\d{1,2}(.\|\/)d{2,4}/, "")
      #remove time
      body.gsub!(/\d{1,2}:\d{1,2}(:\d{1,2})?/, '')
      # remove all non-printables
      body.gsub!(/[^[:print:]]/,'')

      request.get_parm_names.each do |p|
        body.gsub!(/#{Regexp.quote(p)}/, '')
        body.gsub!(/#{Regexp.quote(CGI::unescape(p))}/, '')

        val = request.get_parm_value(p)
        body.gsub!(/#{Regexp.quote(val)}/, '')
        body.gsub!(/#{Regexp.quote(CGI::unescape(val))}/, '')

      end

      request.post_parm_names.each do |p|
        body.gsub!(/#{Regexp.quote(p)}/, '')
        body.gsub!(/#{Regexp.quote(CGI::unescape(p))}/, '')

        val = request.post_parm_value(p)
        body.gsub!(/#{Regexp.quote(val)}/, '')
        body.gsub!(/#{Regexp.quote(CGI::unescape(val))}/, '')
      end

      # remove all parm/value pairs
      orig_request.get_parm_names.each do |p|
        body.gsub!(/#{Regexp.quote(p)}/, '')
        body.gsub!(/#{Regexp.quote(CGI::unescape(p))}/, '')

        val = orig_request.get_parm_value(p)
        body.gsub!(/#{Regexp.quote(val)}/, '')
        body.gsub!(/#{Regexp.quote(CGI::unescape(val))}/, '')
      end

      orig_request.post_parm_names.each do |p|
        body.gsub!(/#{Regexp.quote(p)}/, '')
        body.gsub!(/#{Regexp.quote(CGI::unescape(p))}/, '')

        val = orig_request.post_parm_value(p)
        body.gsub!(/#{Regexp.quote(val)}/, '')
        body.gsub!(/#{Regexp.quote(CGI::unescape(val))}/, '')
      end
    return body, Digest::MD5.hexdigest(body)
    else
    puts "!!! SMART-HASH is NIL !!!!"
    # puts request
    # puts "----------------------"
    # puts response.body
    return nil
    end
  rescue => bang
  puts bang
  puts bang.backtrace if $DEBUG
  return body, Digest::MD5.hexdigest(body||="")
  end

end

.snakecase(string) ⇒ Object



28
29
30
# File 'lib/watobo/utils/strings.rb', line 28

def self.snakecase(string)
  string.gsub(/([A-Z])([A-Z][a-z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1_\2').tr("-","_").downcase
end

.string2response(text, opts = {}) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/watobo/utils/response_builder.rb', line 24

def self.string2response( text, opts = {} )
    options = { :update_content_length => false }
    options.update opts
    begin
      hb_sep = "\r\n\r\n"
      eoh = text.index(hb_sep)
      if eoh.nil?
        hb_sep = "\n\n"
        eoh = text.index(hb_sep)
      end
      unless eoh.nil?
      raw_header = text[0..eoh-1]
      raw_body = text[eoh+hb_sep.length..-1]
      puts ">> RawBody: #{raw_body}"
      else
        raw_header = text
        raw_body = nil
      end

      response = raw_header.split("\n")
      response.map!{|r| "#{r.strip}\r\n" }
      Watobo::Response.create response
      unless raw_body.nil?
      response << "\r\n"
      response << raw_body unless raw_body.strip.empty?
      end
      return response

    rescue => bang
      puts bang
      puts bang.backtrace
    end
    return nil
end

.text2request(text) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
# File 'lib/watobo/utils/text2request.rb', line 24

def Utils.text2request(text)
    result = []
    if text =~ /\n\n/
      dummy = text.split(/\n\n/)
      header = dummy.shift.split(/\n/)
      body = dummy.join("\n\n")
    else
      header = text.split(/\n/)
      body = nil
    end
    
    header.each do |h|
      result.push "#{h}\r\n"
    end
    
    result.extend Watobo::Mixin::Parser::Url
    result.extend Watobo::Mixin::Parser::Web10
    result.extend Watobo::Mixin::Shaper::Web10
    
    ct = result.content_type
    # last line is without "\r\n" if text has a body
    if ct =~ /multipart\/form/ and body then
      #Content-Type: multipart/form-data; boundary=---------------------------3035221901842
      if ct =~ /boundary=([\-\w]+)/
        boundary = $1.strip
        chunks = body.split(boundary)
        e = chunks.pop # remove "--" 
        new_body = []
        chunks.each do |c|
          new_chunk = ''
          c.gsub!(/[\-]+$/,'')
          next if c.nil?
          next if c.strip.empty?
          c.strip!
          if c =~ /\n\n/
            ctmp = c.split(/\n\n/)
            cheader = ctmp.shift.split(/\n/)
            cbody = ctmp.join("\n\n")
          else
            cheader = c.split(/\n/)
            cbody = nil
          end
          new_chunk = cheader.join("\r\n")
          new_chunk +=  "\r\n\r\n"
          new_chunk += cbody.strip + "\r\n" if cbody
          
          # puts cbody
          new_body.push new_chunk
          
        end
        body = "--#{boundary}\r\n"
        body += new_body.join("--#{boundary}\r\n")
        body += "--#{boundary}--"
      end
      #  body.gsub!(/\n/, "\r\n") if body
      
    end
    
    if body then
      result.push "\r\n"
      result.push body.strip
    end
    
    
    return result
  
end

Instance Method Details

#loadIcon(app, filename) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/watobo/utils/load_icon.rb', line 24

def loadIcon(app, filename)
  begin
    icon = nil
    
    File.open(filename, "rb") do |f| 
      if filename.strip =~ /\.ico$/ then
        icon = FXICOIcon.new(app, f.read)
        #icon = FXICOIcon.new(getApp(), f.read)
      elsif filename.strip =~ /\.png$/ then
        icon = FXPNGIcon.new(app, f.read)
      elsif filename.strip =~ /\.gif$/ then
        icon = FXGIFIcon.new(app, f.read)
      end
      icon.create
    end
    
    icon
  rescue => bang
    puts "Couldn't load icon: #{filename}"
    puts bang
  end
end