def parse_ticket(secret, ticket, ip): """ Parse the ticket, returning (timestamp, userid, tokens, user_data). If the ticket cannot be parsed, a ``BadTicket`` exception will be raised with an explanation. """ ticket = ticket.strip('"') digest = ticket[:32] try: timestamp = int(ticket[32:40], 16) except ValueError as e: raise BadTicket('Timestamp is not a hex integer: %s' % e) try: userid, data = ticket[40:].split('!', 1) except ValueError: raise BadTicket('userid is not followed by !') userid = url_unquote(userid) if '!' in data: tokens, user_data = data.split('!', 1) else: # pragma: no cover (never generated) # @@: Is this the right order? tokens = '' user_data = data expected = calculate_digest(ip, timestamp, secret, userid, tokens, user_data) if expected != digest: raise BadTicket('Digest signature is not correct', expected=(expected, digest)) tokens = tokens.split(',') return (timestamp, userid, tokens, user_data)
def resource_to_url(self, resource, quote=False): """ Returns the URL for the given resource. :param resource: Resource to create a URL for. :param bool quote: If set, the URL returned will be quoted. :raises ValueError: If the given resource is floating (i.e., has the parent attribute set to `None`) """ ifc = provided_by(resource) if not IResource in ifc: raise TypeError('Can not generate URL for non-resource "%s".' % resource) elif resource.__parent__ is None: raise ValueError('Can not generate URL for floating resource ' '"%s".' % resource) if ICollectionResource in ifc: query = {} if not resource.filter is None: query['q'] = \ UrlPartsConverter.make_filter_string(resource.filter) if not resource.order is None: query['sort'] = \ UrlPartsConverter.make_order_string(resource.order) if not resource.slice is None: query['start'], query['size'] = \ UrlPartsConverter.make_slice_strings(resource.slice) if query != {}: options = dict(query=query) else: options = dict() if not resource.is_root_collection: # For nested collections, we check if the referenced root # collection is exposed (i.e., has the service as parent). # If yes, we return an absolute URL, else a nested URL. root_coll = get_root_collection(resource) if not root_coll.has_parent: url = self.__request.resource_url(resource) else: url = self.__request.resource_url(root_coll, **options) else: url = self.__request.resource_url(resource, **options) else: if not resource.is_root_member: # For nested members, we check if the referenced root # collection is exposed (i.e., has the service as parent). # If yes, we return an absolute URL, else a nested URL. root_coll = get_root_collection(resource) if not root_coll.has_parent: url = self.__request.resource_url(resource) else: par_url = self.__request.resource_url(root_coll) url = "%s%s/" % (par_url, resource.__name__) else: url = self.__request.resource_url(resource) if not quote: url = url_unquote(url) return url
def resource_to_url(self, resource, quote=False): """ Returns the URL for the given resource. :param resource: Resource to create a URL for. :param bool quote: If set, the URL returned will be quoted. :raises ValueError: If the given resource is floating (i.e., has the parent attribute set to `None`) """ ifc = provided_by(resource) if not IResource in ifc: raise TypeError('Can not generate URL for non-resource "%s".' % resource) elif resource.__parent__ is None: raise ValueError('Can not generate URL for floating resource ' '"%s".' % resource) if ICollectionResource in ifc: query = {} if not resource.filter is None: query['q'] = \ UrlPartsConverter.make_filter_string(resource.filter) if not resource.order is None: query['sort'] = \ UrlPartsConverter.make_order_string(resource.order) if not resource.slice is None: query['start'], query['size'] = \ UrlPartsConverter.make_slice_strings(resource.slice) if query != {}: options = dict(query=query) else: options = dict() if not resource.is_root_collection: # For nested collections, we check if the referenced root # collection is exposed (i.e., has the service as parent). # If yes, we return an absolute URL, else a nested URL. root_coll = get_root_collection(resource) if not root_coll.has_parent: url = self.__request.resource_url(resource, **options) else: url = self.__request.resource_url(root_coll, **options) else: url = self.__request.resource_url(resource, **options) else: if not resource.is_root_member: # For nested members, we check if the referenced root # collection is exposed (i.e., has the service as parent). # If yes, we return an absolute URL, else a nested URL. root_coll = get_root_collection(resource) if not root_coll.has_parent: par_url = self.__request.resource_url(resource) else: par_url = self.__request.resource_url(root_coll) url = "%s%s/" % (par_url, resource.__name__) else: url = self.__request.resource_url(resource) if not quote: url = url_unquote(url) return url
def parse_ticket(secret, ticket, ip, hashalg='md5'): """ Parse the ticket, returning (timestamp, userid, tokens, user_data). If the ticket cannot be parsed, a ``BadTicket`` exception will be raised with an explanation. """ ticket = native_(ticket).strip('"') digest_size = hashlib.new(hashalg).digest_size * 2 digest = ticket[:digest_size] try: timestamp = int(ticket[digest_size:digest_size + 8], 16) except ValueError as e: raise BadTicket('Timestamp is not a hex integer: %s' % e) try: userid, data = ticket[digest_size + 8:].split('!', 1) except ValueError: raise BadTicket('userid is not followed by !') userid = url_unquote(userid) if '!' in data: tokens, user_data = data.split('!', 1) else: # pragma: no cover (never generated) # @@: Is this the right order? tokens = '' user_data = data expected = calculate_digest(ip, timestamp, secret, userid, tokens, user_data, hashalg) # Avoid timing attacks (see # http://seb.dbzteam.org/crypto/python-oauth-timing-hmac.pdf) if strings_differ(expected, digest): raise BadTicket('Digest signature is not correct', expected=(expected, digest)) tokens = tokens.split(',') return (timestamp, userid, tokens, user_data)
def run(self): if not len(self.args) >= 2: self.out('You must provide at least two arguments') return 2 app_spec = self.args[0] path = self.args[1] if not path.startswith('/'): path = '/' + path try: path, qs = path.split('?', 1) except ValueError: qs = '' path = url_unquote(path) headers = {} if self.options.headers: for item in self.options.headers: if ':' not in item: self.out( "Bad --header=%s option, value must be in the form " "'name:value'" % item) return 2 name, value = item.split(':', 1) headers[name] = value.strip() app = self.get_app(app_spec, self.options.app_name, options=parse_vars(self.args[2:])) request_method = (self.options.method or 'GET').upper() environ = { 'REQUEST_METHOD': request_method, 'SCRIPT_NAME': '', # may be empty if app is at the root 'PATH_INFO': path, 'SERVER_NAME': 'localhost', # always mandatory 'SERVER_PORT': '80', # always mandatory 'SERVER_PROTOCOL': 'HTTP/1.0', 'CONTENT_TYPE': 'text/plain', 'REMOTE_ADDR': '127.0.0.1', 'wsgi.run_once': True, 'wsgi.multithread': False, 'wsgi.multiprocess': False, 'wsgi.errors': sys.stderr, 'wsgi.url_scheme': 'http', 'wsgi.version': (1, 0), 'QUERY_STRING': qs, 'HTTP_ACCEPT': 'text/plain;q=1.0, */*;q=0.1', 'paste.command_request': True, } if request_method == 'POST': environ['wsgi.input'] = self.stdin environ['CONTENT_LENGTH'] = '-1' for name, value in headers.items(): if name.lower() == 'content-type': name = 'CONTENT_TYPE' else: name = 'HTTP_' + name.upper().replace('-', '_') environ[name] = value request = Request.blank(path, environ=environ) response = request.get_response(app) if self.options.display_headers: self.out(response.status) for name, value in response.headerlist: self.out('%s: %s' % (name, value)) if response.charset: self.out(response.ubody) else: self.out(response.body) return 0
def run(self): if not self.args.config_uri or not self.args.path_info: self.out('You must provide at least two arguments') return 2 app_spec = self.args.config_uri path = self.args.path_info self.configure_logging(app_spec) if not path.startswith('/'): path = '/' + path try: path, qs = path.split('?', 1) except ValueError: qs = '' path = url_unquote(path) headers = {} if self.args.login: enc = base64.b64encode(self.args.login.encode('ascii')) headers['Authorization'] = 'Basic ' + enc.decode('ascii') if self.args.headers: for item in self.args.headers: if ':' not in item: self.out( "Bad --header=%s option, value must be in the form " "'name:value'" % item) return 2 name, value = item.split(':', 1) headers[name] = value.strip() app = self.get_app(app_spec, self.args.app_name, options=parse_vars(self.args.config_vars)) request_method = (self.args.method or 'GET').upper() environ = { 'REQUEST_METHOD': request_method, 'SCRIPT_NAME': '', # may be empty if app is at the root 'PATH_INFO': path, 'SERVER_NAME': 'localhost', # always mandatory 'SERVER_PORT': '80', # always mandatory 'SERVER_PROTOCOL': 'HTTP/1.0', 'CONTENT_TYPE': 'text/plain', 'REMOTE_ADDR':'127.0.0.1', 'wsgi.run_once': True, 'wsgi.multithread': False, 'wsgi.multiprocess': False, 'wsgi.errors': sys.stderr, 'wsgi.url_scheme': 'http', 'wsgi.version': (1, 0), 'QUERY_STRING': qs, 'HTTP_ACCEPT': 'text/plain;q=1.0, */*;q=0.1', 'paste.command_request': True, } if request_method in ('POST', 'PUT', 'PATCH'): environ['wsgi.input'] = self.stdin environ['CONTENT_LENGTH'] = '-1' for name, value in headers.items(): if name.lower() == 'content-type': name = 'CONTENT_TYPE' else: name = 'HTTP_' + name.upper().replace('-', '_') environ[name] = value request = Request.blank(path, environ=environ) response = request.get_response(app) if self.args.display_headers: self.out(response.status) for name, value in response.headerlist: self.out('%s: %s' % (name, value)) if response.charset: self.out(response.ubody) else: self.out(response.body) return 0
def __getitem__(self, key): key = url_unquote(key) if key in self.request.registry.introspector.categories(): return Introspector(key, self, self.request) raise KeyError(key)
def run(self): if not len(self.args) >= 2: self.out("You must provide at least two arguments") return 2 app_spec = self.args[0] path = self.args[1] if not path.startswith("/"): path = "/" + path try: path, qs = path.split("?", 1) except ValueError: qs = "" path = url_unquote(path) headers = {} if self.options.headers: for item in self.options.headers: if ":" not in item: self.out("Bad --header=%s option, value must be in the form " "'name:value'" % item) return 2 name, value = item.split(":", 1) headers[name] = value.strip() app = self.get_app(app_spec, self.options.app_name) request_method = (self.options.method or "GET").upper() environ = { "REQUEST_METHOD": request_method, "SCRIPT_NAME": "", # may be empty if app is at the root "PATH_INFO": path, "SERVER_NAME": "localhost", # always mandatory "SERVER_PORT": "80", # always mandatory "SERVER_PROTOCOL": "HTTP/1.0", "CONTENT_TYPE": "text/plain", "REMOTE_ADDR": "127.0.0.1", "wsgi.run_once": True, "wsgi.multithread": False, "wsgi.multiprocess": False, "wsgi.errors": sys.stderr, "wsgi.url_scheme": "http", "wsgi.version": (1, 0), "QUERY_STRING": qs, "HTTP_ACCEPT": "text/plain;q=1.0, */*;q=0.1", "paste.command_request": True, } if request_method == "POST": environ["wsgi.input"] = self.stdin environ["CONTENT_LENGTH"] = "-1" for name, value in headers.items(): if name.lower() == "content-type": name = "CONTENT_TYPE" else: name = "HTTP_" + name.upper().replace("-", "_") environ[name] = value request = Request.blank(path, environ=environ) response = request.get_response(app) if self.options.display_headers: self.out(response.status) for name, value in response.headerlist: self.out("%s: %s" % (name, value)) if response.charset: self.out(response.ubody) else: self.out(response.body) return 0