Example #1
0
	def _unquote_host(self, host):
		# IPv6 / IPvFuture
		if host.startswith(b'[') and host.endswith(b']'):
			host = host[1:-1]
			try:
				return u'[%s]' % inet_ntop(AF_INET6, inet_pton(AF_INET6, host)).decode('ascii')
			except SocketError:
				# IPvFuture
				if host.startswith(b'v') and b'.' in host and host[1:].split(b'.', 1)[0].isdigit():
					try:
						return u'[%s]' % host.decode('ascii')
					except UnicodeDecodeError:
						raise InvalidURI(_('Invalid IPvFuture address: must be ASCII.'))
				raise InvalidURI(_('Invalid IP address in URI.'))
		# IPv4
		if all(x.isdigit() for x in host.split(b'.')):
			try:
				return inet_ntop(AF_INET, inet_pton(AF_INET, host)).decode('ascii')
			except SocketError:
				raise InvalidURI(_('Invalid IPv4 address in URI.'))

		if host.strip(Percent.UNRESERVED + Percent.SUB_DELIMS + b'%'):
			raise InvalidURI(_('Invalid URI host.'))

		# DNS hostname
		host = self.unquote(host)
		try:
			return host.encode('ascii').decode('idna').lower()
		except UnicodeError:
			raise InvalidURI(_('Invalid host.'))
Example #2
0
    def parse(self, line):
        """parses the request line and sets method, uri and protocol version
			:param line: the request line
			:type  line: bytes
		"""
        bits = line.strip().split(None, 2)
        try:
            method, uri, version = bits
        except ValueError:
            raise InvalidLine(_(u'Invalid request line: %r'),
                              line.decode('ISO8859-1'))

        # protocol version
        super(Request, self).parse(version)

        # method
        self.method.parse(method)

        # URI
        if uri.startswith(b'//'):
            raise InvalidURI(
                _(u'The request URI must be an absolute path or contain a scheme.'
                  ))
        if self.method == u'CONNECT':
            uri = b'//%s' % (uri, )
        self.uri.parse(uri)
        self.validate_request_uri()
Example #3
0
 def validate_request_uri(self):
     uri = self.uri
     if not isinstance(uri, (uri.SCHEMES['http'], uri.SCHEMES['https'])):
         raise InvalidURI(_(u'The request URI scheme must be HTTP based.'))
     if uri.fragment or uri.username or uri.password:
         raise InvalidURI(
             _(u'The request URI must not contain fragments or user information.'
               ))
     if uri.path.startswith(b'//'):
         raise InvalidURI(
             _(u'The request URI path must not start with //.'))
     if uri.path and uri.path != u'*' and uri.path[0] != u'/':
         raise InvalidURI(_(u'The request URI path must start with /.'))
     if self.method == u'CONNECT' and (uri.scheme or uri.path
                                       or uri.query_string or not uri.host):
         raise InvalidURI(
             _(u'The request URI of an CONNECT request must be a authority.'
               ))
Example #4
0
 def validate_request_uri_scheme(self):
     if self.message.uri.scheme:
         if self.message.uri.scheme not in ('http', 'https'):
             exc = InvalidURI(_(u'Invalid URL: wrong scheme'))
             raise BAD_REQUEST(Unicode(exc))
     else:
         self.message.uri.scheme = self._default_scheme
         self.message.uri.host = self._default_host
         self.message.uri.port = self._default_port
Example #5
0
	def port(self, port):
		port = port or self.PORT
		if port:
			try:
				port = int(port)
				if not 0 < int(port) <= 65535:
					raise ValueError
			except ValueError:
				raise InvalidURI(_(u'Invalid port: %r'), port)  # TODO: TypeError
		self._port = port
Example #6
0
	def _compose_authority_iter(self):
		if not self.host:
			return
		username, password, host, port, quote = self.username, self.password, self.host, self.port, self.quote
		if username:
			yield quote(username, Percent.USERINFO)
			if password:
				yield b':'
				yield quote(password, Percent.USERINFO)
			yield b'@'
		try:
			yield host.encode('idna')
		except UnicodeError:  # u'..'.encode('idna')
			raise InvalidURI(_(u'Invalid URI: cannot encode host as IDNA.'))
		if port and int(port) != self.PORT:
			yield b':%d' % int(port)
Example #7
0
	def parse(self, uri):
		r"""Parses a well formed absolute or relative URI.

			  foo://example.com:8042/over/there?name=ferret#nose
			  \_/   \______________/\_________/ \_________/ \__/
			   |           |            |            |        |
			scheme     authority       path        query   fragment
			   |   _____________________|__
			  / \ /                        \
			  urn:example:animal:ferret:nose

			https://username:password@[::1]:8090/some/path?query#fragment
			<scheme>://<username>:<password>@<host>:<port>/<path>?<query>#<fragment>
			[<scheme>:][//[<username>[:<password>]@][<host>][:<port>]/]<path>[?<query>][#<fragment>]
		"""

		if isinstance(uri, Unicode):
			try:
				uri = uri.encode('ascii')
			except UnicodeEncodeError:
				raise TypeError('URI must be ASCII bytes.')

		if type(self) is URI and b':' in uri:
			self.scheme = uri.split(b':', 1)[0].lower()
			if type(self) is not URI:
				return self.parse(uri)

		if uri and uri.strip(b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'):
			raise InvalidURI(_(u'Invalid URI: must consist of printable ASCII characters without whitespace.'))

		uri, __, fragment = uri.partition(b'#')
		uri, __, query_string = uri.partition(b'?')
		scheme, authority_exists, uri = uri.rpartition(b'://')
		if not authority_exists and uri.startswith(b'//'):
			uri = uri[2:]
			authority_exists = True
		if not authority_exists and b':' in uri:
			scheme, __, uri = uri.partition(b':')
		authority, path = b'', uri
		if authority_exists:
			authority, __, path = uri.partition(b'/')
			path = b'%s%s' % (__, path)
		userinfo, __, hostport = authority.rpartition(b'@')
		username, __, password = userinfo.partition(b':')
		if b':' in hostport and not hostport.endswith(b']'):
			host, __, port = hostport.rpartition(b':')
		else:
			host, port = hostport, b''

		unquote = self.unquote
		path = u'/'.join([unquote(seq).replace(u'/', u'%2f') for seq in path.split(b'/')])

		try:
			scheme = scheme.decode('ascii').lower()
		except UnicodeDecodeError:
			raise InvalidURI(_(u'Invalid scheme: must be ASCII.'))

		if scheme and scheme.strip(u'abcdefghijklmnopqrstuvwxyz0123456789.-+'):
			raise InvalidURI(_(u'Invalid scheme: must only contain alphanumeric letters or plus, dash, dot.'))

		if query_string:
			query_string = QueryString.encode(QueryString.decode(query_string, self.encoding), self.encoding)

		self.tuple = (
			scheme,
			unquote(username),
			unquote(password),
			self._unquote_host(host),
			port,
			path,
			query_string.decode(self.encoding),
			unquote(fragment)
		)