Module: URI

Defined in:
lib/standard/facets/uri.rb

Defined Under Namespace

Modules: Hash, Kernel

Constant Summary collapse

KEY_VALUE_SEPARATOR =

“&”

";"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.cgi_escape(string) ⇒ Object

CGI escape

TODO: How does this compare to URI.escape?



83
84
85
86
87
# File 'lib/standard/facets/uri.rb', line 83

def cgi_escape(string)
  string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do
    '%' + $1.unpack('H2' * $1.size).join('%').upcase
  end.tr(' ', '+')
end

.cgi_parse(query) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/standard/facets/uri.rb', line 97

def cgi_parse(query)
  params = Hash.new([].freeze)

  query.split(/[&;]/n).each do |pairs|
    key, value = pairs.split('=',2).collect{|v| cgi_unescape(v) }
    if params.has_key?(key)
      params[key].push(value)
    else
      params[key] = [value]
    end
  end

  params
end

.cgi_unescape(string) ⇒ Object



90
91
92
93
94
# File 'lib/standard/facets/uri.rb', line 90

def cgi_unescape(string)
  string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) do
    [$1.delete('%')].pack('H*')
  end
end

.chomp_query_string(uri) ⇒ Object

Removes the query string from a uri.

Returns the chomped uri.



135
136
137
138
139
# File 'lib/standard/facets/uri.rb', line 135

def chomp_query_string(uri)
  return nil unless uri
  query_string = self.get_query_string(uri)
  return uri.dup.chomp("?#{query_string}")
end

.decode(uri) ⇒ Object

Decode the uri components.

Raises:

  • (ArgumentError)


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/standard/facets/uri.rb', line 11

def decode(uri)
  ## gmosx: hmm is this needed?
  ## guard against invalid filenames for example pictures with
  ## spaces uploaded by users
  escaped_uri = uri.gsub(/ /, "+")

  if md = URI::REGEXP::REL_URI.match(escaped_uri)
    path = "#{md[5]}#{md[6]}"
    type = File.extname(path)
    query_string = md[7]

    ## real_path = "#{$root_dir}/#{path}"

    parameters = URI.query_to_hash(query_string)
    path.gsub!(/\+/, " ")

    return [path, type, parameters, query_string]
  end

  ## this is usefull for uncovering bugs!
  raise ArgumentError.new("the parameter '#{uri}' is not a valid uri")
end

.get_query_string(uri) ⇒ Object

This method returns the query string of a uri

Input: the uri

Output: the query string. returns nil if no query string



120
121
122
123
124
125
126
127
128
129
130
# File 'lib/standard/facets/uri.rb', line 120

def get_query_string(uri)
  return nil unless uri
  # gmosx: INVESTIGATE ruby's URI seems to differently handle
  # abs and rel uris.
  if md = URI::REGEXP::ABS_URI.match(uri)
    return md[8]
  elsif md = URI::REGEXP::REL_URI.match(uri)
    return md[7]
  end
  return nil
end

.hash_to_query(parameters) ⇒ Object Also known as: hash_to_query_string

Given a hash with parameter/value pairs construct a standard query string.

URI.hash_to_query(:a => 1, :b => 2)
#=> "a=1;b=2"


69
70
71
72
73
74
75
76
# File 'lib/standard/facets/uri.rb', line 69

def hash_to_query(parameters)
  return '' unless parameters
  pairs = []
  parameters.each do |param, value|
    pairs << "#{param}=#{cgi_escape(value.to_s)}"
  end
  return pairs.join(KEY_VALUE_SEPARATOR)
end

.query_to_hash(query_string) ⇒ Object Also known as: query_string_to_hash

Extend the basic query string parser provided by the cgi module. converts single valued params (the most common case) to objects instead of arrays

Returns hash of parameters, contains arrays for multivalued parameters (multiselect, checkboxes , etc).

If no query string is provided (nil or “”) returns an empty hash.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/standard/facets/uri.rb', line 42

def query_to_hash(query_string)
  return {} unless query_string

  query_parameters = cgi_parse(query_string)

  query_parameters.each { |key, val|
    ## replace the array with an object
    query_parameters[key] = val[0] if 1 == val.length
  }

  ## set default value to nil! cgi sets this to []
  query_parameters.default = nil

  return query_parameters
end

.update_query_string(uri, parameters) ⇒ Object

Get a uri and a hash of parameters. Inject the hash values as parameters in the query sting path. Returns the full uri.

uri - the uri to filter (String) parameter - hash of parameters to update

Returns the full updated query string.

TODO: optimize



150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/standard/facets/uri.rb', line 150

def update_query_string(uri, parameters)
  query_string = self.get_query_string(uri)
  rest = uri.dup.gsub(/\?#{query_string}/, "")

  hash = self.query_string_to_hash(query_string)
  hash.update(parameters)
  query_string = self.hash_to_query_string(hash)

  unless query_string.blank?
    return "#{rest}?#{query_string}"
  else
    return rest
  end
end

.update_request_uri(request, parameters) ⇒ Object

Gets the request uri, injects extra parameters in the query string and returns a new uri. The request object is not modified. There is always a qs string so an extra test is skipped.

TODO: find a better name?



170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/standard/facets/uri.rb', line 170

def update_request_uri(request, parameters)
  hash = request.parameters.dup()
  hash.update(parameters)

  ## use this in hash_to_querystring.
  query_string = hash.collect { |k, v|
    "#{k}=#{v}"
  }.join(";")

  ## return "#{request.translated_uri}?#{query_string}"
  return "#{request.path}?#{query_string}"
end

Instance Method Details

#cgi_escape(string) ⇒ Object (private)

CGI escape

TODO: How does this compare to URI.escape?



83
84
85
86
87
# File 'lib/standard/facets/uri.rb', line 83

def cgi_escape(string)
  string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do
    '%' + $1.unpack('H2' * $1.size).join('%').upcase
  end.tr(' ', '+')
end

#cgi_parse(query) ⇒ Object (private)



97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/standard/facets/uri.rb', line 97

def cgi_parse(query)
  params = Hash.new([].freeze)

  query.split(/[&;]/n).each do |pairs|
    key, value = pairs.split('=',2).collect{|v| cgi_unescape(v) }
    if params.has_key?(key)
      params[key].push(value)
    else
      params[key] = [value]
    end
  end

  params
end

#cgi_unescape(string) ⇒ Object (private)



90
91
92
93
94
# File 'lib/standard/facets/uri.rb', line 90

def cgi_unescape(string)
  string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) do
    [$1.delete('%')].pack('H*')
  end
end

#chomp_query_string(uri) ⇒ Object (private)

Removes the query string from a uri.

Returns the chomped uri.



135
136
137
138
139
# File 'lib/standard/facets/uri.rb', line 135

def chomp_query_string(uri)
  return nil unless uri
  query_string = self.get_query_string(uri)
  return uri.dup.chomp("?#{query_string}")
end

#decode(uri) ⇒ Object (private)

Decode the uri components.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/standard/facets/uri.rb', line 11

def decode(uri)
  ## gmosx: hmm is this needed?
  ## guard against invalid filenames for example pictures with
  ## spaces uploaded by users
  escaped_uri = uri.gsub(/ /, "+")

  if md = URI::REGEXP::REL_URI.match(escaped_uri)
    path = "#{md[5]}#{md[6]}"
    type = File.extname(path)
    query_string = md[7]

    ## real_path = "#{$root_dir}/#{path}"

    parameters = URI.query_to_hash(query_string)
    path.gsub!(/\+/, " ")

    return [path, type, parameters, query_string]
  end

  ## this is usefull for uncovering bugs!
  raise ArgumentError.new("the parameter '#{uri}' is not a valid uri")
end

#get_query_string(uri) ⇒ Object (private)

This method returns the query string of a uri

Input: the uri

Output: the query string. returns nil if no query string



120
121
122
123
124
125
126
127
128
129
130
# File 'lib/standard/facets/uri.rb', line 120

def get_query_string(uri)
  return nil unless uri
  # gmosx: INVESTIGATE ruby's URI seems to differently handle
  # abs and rel uris.
  if md = URI::REGEXP::ABS_URI.match(uri)
    return md[8]
  elsif md = URI::REGEXP::REL_URI.match(uri)
    return md[7]
  end
  return nil
end

#hash_to_query(parameters) ⇒ Object (private)

Given a hash with parameter/value pairs construct a standard query string.

URI.hash_to_query(:a => 1, :b => 2)
#=> "a=1;b=2"


69
70
71
72
73
74
75
76
# File 'lib/standard/facets/uri.rb', line 69

def hash_to_query(parameters)
  return '' unless parameters
  pairs = []
  parameters.each do |param, value|
    pairs << "#{param}=#{cgi_escape(value.to_s)}"
  end
  return pairs.join(KEY_VALUE_SEPARATOR)
end

#hash_to_query_stringObject (private)



78
# File 'lib/standard/facets/uri.rb', line 78

alias_method :hash_to_query_string, :hash_to_query

#query_string_to_hashObject (private)



58
# File 'lib/standard/facets/uri.rb', line 58

alias_method :query_string_to_hash, :query_to_hash

#query_to_hash(query_string) ⇒ Object (private)

Extend the basic query string parser provided by the cgi module. converts single valued params (the most common case) to objects instead of arrays

Returns hash of parameters, contains arrays for multivalued parameters (multiselect, checkboxes , etc).

If no query string is provided (nil or “”) returns an empty hash.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/standard/facets/uri.rb', line 42

def query_to_hash(query_string)
  return {} unless query_string

  query_parameters = cgi_parse(query_string)

  query_parameters.each { |key, val|
    ## replace the array with an object
    query_parameters[key] = val[0] if 1 == val.length
  }

  ## set default value to nil! cgi sets this to []
  query_parameters.default = nil

  return query_parameters
end

#update_query_string(uri, parameters) ⇒ Object (private)

Get a uri and a hash of parameters. Inject the hash values as parameters in the query sting path. Returns the full uri.

uri - the uri to filter (String) parameter - hash of parameters to update

Returns the full updated query string.

TODO: optimize



150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/standard/facets/uri.rb', line 150

def update_query_string(uri, parameters)
  query_string = self.get_query_string(uri)
  rest = uri.dup.gsub(/\?#{query_string}/, "")

  hash = self.query_string_to_hash(query_string)
  hash.update(parameters)
  query_string = self.hash_to_query_string(hash)

  unless query_string.blank?
    return "#{rest}?#{query_string}"
  else
    return rest
  end
end

#update_request_uri(request, parameters) ⇒ Object (private)

Gets the request uri, injects extra parameters in the query string and returns a new uri. The request object is not modified. There is always a qs string so an extra test is skipped.

TODO: find a better name?



170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/standard/facets/uri.rb', line 170

def update_request_uri(request, parameters)
  hash = request.parameters.dup()
  hash.update(parameters)

  ## use this in hash_to_querystring.
  query_string = hash.collect { |k, v|
    "#{k}=#{v}"
  }.join(";")

  ## return "#{request.translated_uri}?#{query_string}"
  return "#{request.path}?#{query_string}"
end