# encoding: UTF-8 module Plezi # includes general helper methods for HTTP protocol and related (url encoding etc') module HTTP module_function # decode html form data stream # def decode_form_data encoded # scanner = StringScanner.new encoded.gsub('+', '%20') # decoded = '' # until scanner.eos? do # decoded << scanner.scan(/[^%]+/) # if scanner.scan(/\%[0-9a-fA-F][0-9a-fA-F]/) # decoded << scanner.matched[1,2].to_i(16).chr # elsif !scanner.eos? # decoded << scanner.scan(/./) # end # end # decoded # end # # encode html form data stream # def encode_form_data exposed # scanner = StringScanner.new exposed # encoded = '' # # HTML form encoding # until scanner.eos? do # encoded << scanner.scan(/[a-zA-Z0-9\*\.\_\-]+/) # encoded << "%#{scanner.matched.ord <= 16 ? "0" : ""} #{ scanner.matched.ord.to_s(16) }" if scanner.scan(/./) # end # # HTTP encoding # # until scanner.eos? do # # encoded << scanner.scan(/[^\:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=]+/) # # encoded << "%#{scanner.matched.ord <= 16 ? "0" : ""} #{ scanner.matched.ord.to_s(16) }" if scanner.scan(/./) # # end # encoded # end # # decode HTTP URI data stream # def decode_uri encoded # scanner = StringScanner.new encoded.gsub('+', '%20') #? is this true here? # decoded = '' # until scanner.eos? do # decoded << scanner.scan(/[^%]+/) # if scanner.scan(/\%[0-9a-fA-F][0-9a-fA-F]/) # decoded << scanner.matched[1,2].to_i(16).chr # elsif !scanner.eos? # decoded << scanner.scan(/./) # end # end # decoded # end # # encode HTTP URI data stream # def encode_uri_data exposed # scanner = StringScanner.new exposed # encoded = '' # until scanner.eos? do # encoded << scanner.scan(/[^\:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=]+/) # encoded << "%#{scanner.matched.ord <= 16 ? "0" : ""} #{ scanner.matched.ord.to_s(16) }" if scanner.scan(/.|[\s]/) # end # encoded # end # Based on the WEBRick source code, escapes &, ", > and < in a String object def escape(string) string.gsub(/&/n, '&') .gsub(/\"/n, '"') .gsub(/>/n, '>') .gsub(/ e Plezi.error e Plezi.error "(Silent): parameters parse error for #{param_name} ... maybe conflicts with a different set?" target_hash[param_name] = rubyfy! param_value end end def decode object, decode_method = :form if object.is_a?(Hash) object.values.each {|v| decode v, decode_method} elsif object.is_a?(Array) object.each {|v| decode v, decode_method} elsif object.is_a?(String) case decode_method when :form object.gsub!('+', '%20') object.gsub!(/\%[0-9a-fA-F][0-9a-fA-F]/) {|m| m[1..2].to_i(16).chr} when :uri, :url object.gsub!(/\%[0-9a-fA-F][0-9a-fA-F]/) {|m| m[1..2].to_i(16).chr} when :html object.gsub!(/&/i, '&') object.gsub!(/"/i, '"') object.gsub!(/>/i, ">") object.gsub!(/</i, "<") when :utf8 else end object.gsub!(/&#([0-9a-fA-F]{2});/) {|m| m.match(/[0-9a-fA-F]{2}/)[0].hex.chr} object.gsub!(/&#([0-9]{4});/) {|m| [m.match(/[0-9]+/)[0].to_i].pack 'U'} make_utf8! object return object elsif object.is_a?(Symbol) str = object.to_str decode str, decode_method return str.to_sym else raise "Plezi Raising Hell (don't misuse us)!" end end def encode object, decode_method = :form if object.is_a?(Hash) object.values.each {|v| encode v, decode_method} elsif object.is_a?(Array) object.each {|v| encode v, decode_method} elsif object.is_a?(String) case decode_method when :uri, :url, :form object.force_encoding "binary" object.gsub!(/[^a-zA-Z0-9\*\.\_\-]/) {|m| m.ord <= 16 ? "%0#{m.ord.to_s(16)}" : "%#{m.ord.to_s(16)}"} when :html object.gsub!('&', "&") object.gsub!('"', """) object.gsub!(">", ">") object.gsub!("<", "<") object.gsub!(/[^\sa-zA-Z\d\&\;]/) {|m| "&#%04d;" % m.unpack('U')[0] } # object.gsub!(/[^\s]/) {|m| "&#%04d;" % m.unpack('U')[0] } object.force_encoding "binary" when :utf8 object.gsub!(/[^\sa-zA-Z\d]/) {|m| "&#%04d;" % m.unpack('U')[0] } object.force_encoding "binary" else end return object elsif object.is_a?(Symbol) str = object.to_str encode str, decode_method return str.to_sym else raise "Plezi Raising Hell (don't misuse us)!" end end # extracts parameters from the query def extract_data data, target_hash, decode = :form data.each do |set| list = set.split('=') list.each {|s| HTTP.decode s, decode if s} add_param_to_hash list.shift, list.join('='), target_hash end end # re-encodes a string into UTF-8 def make_utf8!(string, encoding= 'utf-8') return false unless string string.force_encoding("binary").encode!(encoding, "binary", invalid: :replace, undef: :replace, replace: '') unless string.force_encoding(encoding).valid_encoding? string end # Changes String to a Ruby Object, if it's a special string def rubyfy!(string) return false unless string make_utf8! string if string == 'true' string = true elsif string == 'false' string = false elsif string.match(/[0-9]/) && !string.match(/[^0-9]/) string = string.to_i end string end end end