lib/ronin/url.rb in ronin-1.0.0.pre3 vs lib/ronin/url.rb in ronin-1.0.0.pre4
- old
+ new
@@ -1,23 +1,22 @@
#
-# Ronin - A Ruby platform for exploit development and security research.
+# Copyright (c) 2006-2011 Hal Brodigan (postmodern.mod3 at gmail.com)
#
-# Copyright (c) 2009-2010 Hal Brodigan (postmodern.mod3 at gmail.com)
+# This file is part of Ronin.
#
-# This program is free software; you can redistribute it and/or modify
+# Ronin is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
+# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
-# This program is distributed in the hope that it will be useful,
+# Ronin is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# along with Ronin. If not, see <http://www.gnu.org/licenses/>.
#
require 'ronin/url_scheme'
require 'ronin/url_query_param'
require 'ronin/host_name'
@@ -51,14 +50,14 @@
# The host name of the URL
belongs_to :host_name
# Port of the URL
- belongs_to :port, :model => 'TCPPort'
+ belongs_to :port, :model => 'TCPPort', :required => false
# Path of the URL
- property :path, String, :default => ''
+ property :path, String
# The fragment of the URL
property :fragment, String
# The query params of the URL
@@ -83,11 +82,11 @@
# The matching URLs.
#
# @since 1.0.0
#
def self.http
- all('scheme.name' => 'http')
+ all(:scheme => {:name => 'http'})
end
#
# Searches for all URLs using HTTPS.
#
@@ -95,11 +94,11 @@
# The matching URLs.
#
# @since 1.0.0
#
def self.https
- all('scheme.name' => 'https')
+ all(:scheme => {:name => 'https'})
end
#
# Searches for URLs with specific host name(s).
#
@@ -110,11 +109,11 @@
# The matching URLs.
#
# @since 1.0.0
#
def self.hosts(names)
- all('host.address' => names)
+ all(:host => {:address => names})
end
#
# Searches for URLs with the specific port number(s).
#
@@ -125,11 +124,11 @@
# The matching URLs.
#
# @since 1.0.0
#
def self.ports(numbers)
- all('port.number' => numbers)
+ all(:port => {:number => numbers})
end
#
# Searches for all URLs sharing a common sub-directory.
#
@@ -170,11 +169,11 @@
# The URLs with the given query-param.
#
# @since 1.0.0
#
def self.query_param(name)
- all('query_params.name' => name)
+ all(:query_params => {:name => name})
end
#
# Search for all URLs with a given query-param value.
#
@@ -185,40 +184,101 @@
# The URLs with the given query-param value.
#
# @since 1.0.0
#
def self.query_value(value)
- all('query_params.value' => value)
+ all(:query_params => {:value => value})
end
#
+ # Searches for a URL.
+ #
+ # @param [URI::HTTP, String] url
+ # The URL to search for.
+ #
+ # @return [URL, nil]
+ # The matching URL.
+ #
+ # @since 1.0.0
+ #
+ def self.[](url)
+ return super(url) if url.kind_of?(Integer)
+
+ # optionally parse the URL
+ url = ::URI.parse(url) unless url.kind_of?(::URI)
+
+ port = if url.port
+ {:number => url.port}
+ end
+
+ path = normalized_path(url)
+ fragment = url.fragment
+
+ # create the initial query
+ query = all(
+ :scheme => {:name => url.scheme},
+ :host_name => {:address => url.host},
+ :port => port,
+ :path => path,
+ :fragment => fragment
+ )
+
+ if url.query
+ # add the query params to the query
+ URI::QueryParams.parse(url.query).each do |name,value|
+ query = query.all(
+ :query_params => {:name => name, :value => value}
+ )
+ end
+ end
+
+ return query.first
+ end
+
+ #
# Creates a new URL.
#
# @param [URI::HTTP] uri
# The URI to create the URL from.
#
# @return [URL]
# The new URL.
#
# @since 1.0.0
#
- def URL.from(uri)
- new_url = URL.new(
- :scheme => URLScheme.first_or_new(:name => uri.scheme),
- :host_name => HostName.first_or_new(:address => uri.host),
- :port => TCPPort.first_or_new(:number => uri.port),
- :path => uri.path,
- :fragment => uri.fragment
- )
+ def self.from(uri)
+ # find or create the URL scheme, host_name and port
+ scheme = self.scheme.model.first_or_new(:name => uri.scheme)
+ host_name = self.host_name.model.first_or_new(:address => uri.host)
+ port = if uri.port
+ self.port.model.first_or_new(:number => uri.port)
+ end
+ path = normalized_path(uri)
+ fragment = uri.fragment
+
+ query_params = []
+
if uri.respond_to?(:query_params)
+ # find or create the URL query params
uri.query_params.each do |name,value|
- new_url.query_params.new(:name => name, :value => value)
+ query_params << self.query_params.model.first_or_new(
+ :name => name,
+ :value => value
+ )
end
end
- return new_url
+ # find or create the URL
+ return first_or_new(
+ :scheme => scheme,
+ :host_name => host_name,
+ :port => port,
+ :path => path,
+ :fragment => fragment,
+ :query_params => query_params
+ )
end
#
# Parses the URL.
#
@@ -230,12 +290,12 @@
#
# @see URL.from
#
# @since 1.0.0
#
- def URL.parse(url)
- URL.from(::URI.parse(url))
+ def self.parse(url)
+ from(::URI.parse(url))
end
#
# The host name of the url.
#
@@ -249,17 +309,17 @@
end
#
# The port number used by the URL.
#
- # @return [Integer]
+ # @return [Integer, nil]
# The port number.
#
# @since 1.0.0
#
def port_number
- self.port.number
+ self.port.number if self.port
end
#
# Dumps the URL query params into a URI query string.
#
@@ -306,25 +366,31 @@
# The URI object created from the url attributes.
#
# @since 1.0.0
#
def to_uri
+ # map the URL scheme to a URI class
url_class = (SCHEMES[self.scheme.name] || ::URI::Generic)
host = if self.host_name
self.host_name.address
end
port = if self.port
self.port.number
end
+ query = unless self.query_params.empty?
+ self.query_string
+ end
+
+ # build the URI
return url_class.build(
:scheme => self.scheme.name,
:host => host,
:port => port,
:path => self.path,
- :query => self.query_string,
+ :query => query,
:fragment => self.fragment
)
end
#
@@ -335,9 +401,36 @@
#
# @since 1.0.0
#
def to_s
self.to_uri.to_s
+ end
+
+ protected
+
+ #
+ # Normalizes the path of a URI.
+ #
+ # @param [URI] uri
+ # The URI containing the path.
+ #
+ # @return [String, nil]
+ # The normalized path.
+ #
+ # @since 1.0.0
+ #
+ def self.normalized_path(uri)
+ case uri
+ when URI::HTTP
+ # map empty HTTP paths to '/'
+ unless uri.path.empty?
+ uri.path
+ else
+ '/'
+ end
+ else
+ uri.path
+ end
end
end
end