Ejemplo n.º 1
0
def set_url_query_parameter(url, param_name, param_value):
    """Set or replace a query parameter, and return the modified URL.

    Args:
        url: str. URL string which contains the query parameter.
        param_name: str. Parameter name to be removed.
        param_value: str. Set the parameter value, if it exists.

    Returns:
        str. Formated URL that has query parameter set or replaced.

    Raises:
        Exception. If the query parameter sent is not of string type,
            them this exception is raised.
    """
    if not isinstance(param_name, python_utils.BASESTRING):
        raise Exception(
            'URL query parameter name must be a string, received %s'
            % param_name)

    scheme, netloc, path, query_string, fragment = python_utils.url_split(url)
    query_params = python_utils.parse_query_string(query_string)

    query_params[param_name] = [param_value]
    new_query_string = python_utils.url_encode(query_params, doseq=True)

    return python_utils.url_unsplit(
        (scheme, netloc, path, new_query_string, fragment))
Ejemplo n.º 2
0
    def sanitize_url(obj):
        """Takes a string representing a URL and sanitizes it.

        Args:
            obj: a string representing a URL.

        Returns:
            An empty string if the URL does not start with http:// or https://
            except when the string is empty. Otherwise, returns the original
            URL.

        Raises:
            AssertionError: The string is non-empty and does not start with
            http:// or https://
        """
        if obj == '':
            return obj
        url_components = python_utils.url_split(obj)
        quoted_url_components = (python_utils.url_quote(component)
                                 for component in url_components)
        raw = python_utils.url_unsplit(quoted_url_components)

        acceptable = html_cleaner.filter_a('a', 'href', obj)
        assert acceptable, ('Invalid URL: Sanitized URL should start with '
                            '\'http://\' or \'https://\'; received %s' % raw)
        return raw
Ejemplo n.º 3
0
def filter_a(tag, name, value):
    """Returns whether the described attribute of a tag should be
    whitelisted.

    Args:
        tag: str. The name of the tag passed.
        name: str. The name of the attribute.
        value: str. The value of the attribute.

    Returns:
        bool. Whether the given attribute should be whitelisted.
    """
    if tag != 'a':
        raise Exception('The filter_a method should only be used for a tags.')
    if name in ('title', 'target'):
        return True
    if name == 'href':
        url_components = python_utils.url_split(value)
        if url_components[0] in ['http', 'https']:
            return True
        logging.error('Found invalid URL href: %s' % value)

    return False
Ejemplo n.º 4
0
    def dispatch(self):
        """Overrides dispatch method in webapp2 superclass.

        Raises:
            Exception. The CSRF token is missing.
            UnauthorizedUserException. The CSRF token is invalid.
        """
        request_split = python_utils.url_split(self.request.uri)
        # If the request is to the old demo server, redirect it permanently to
        # the new demo server.
        if request_split.netloc == 'oppiaserver.appspot.com':
            self.redirect('https://oppiatestserver.appspot.com',
                          permanent=True)
            return

        if not self._is_requested_path_currently_accessible_to_user():
            self.handle_exception(self.TemporaryMaintenanceException(),
                                  self.app.debug)
            return

        if self.user_is_scheduled_for_deletion:
            self.redirect('/logout?redirect_url=%s' %
                          feconf.PENDING_ACCOUNT_DELETION_URL)
            return

        if self.partially_logged_in and request_split.path != '/logout':
            self.redirect('/logout?redirect_url=%s' % self.request.uri)
            return

        if self.payload is not None and self.REQUIRE_PAYLOAD_CSRF_CHECK:
            try:
                # If user opens a new tab during signup process, the user_id
                # parameter is set to None and this causes the signup session
                # to expire. The code here checks if user is on the signup
                # page and the user_id is None, if that is the case an exception
                # is raised which is handled by the frontend by showing a
                # continue to registration modal.
                if 'signup' in self.request.uri and not self.user_id:
                    raise self.UnauthorizedUserException(
                        'Registration session expired.')
                csrf_token = self.request.get('csrf_token')
                if not csrf_token:
                    raise self.UnauthorizedUserException(
                        'Missing CSRF token. Changes were not saved. '
                        'Please report this bug.')

                is_csrf_token_valid = CsrfTokenManager.is_csrf_token_valid(
                    self.user_id, csrf_token)

                if not is_csrf_token_valid:
                    raise self.UnauthorizedUserException(
                        'Your session has expired, and unfortunately your '
                        'changes cannot be saved. Please refresh the page.')
            except Exception as e:
                logging.exception('%s: payload %s', e, self.payload)

                self.handle_exception(e, self.app.debug)
                return

        schema_validation_succeeded = True
        try:
            self.validate_and_normalize_args()
        except self.InvalidInputException as e:
            self.handle_exception(e, self.app.debug)
            schema_validation_succeeded = False
        # TODO(#13155): Remove this clause once all the handlers have had
        # schema validation implemented.
        except NotImplementedError as e:
            self.handle_exception(e, self.app.debug)
            schema_validation_succeeded = False

        if not schema_validation_succeeded:
            return

        super(BaseHandler, self).dispatch()
Ejemplo n.º 5
0
    def render_template(self, filepath, iframe_restriction='DENY'):
        """Prepares an HTML response to be sent to the client.

        Args:
            filepath: str. The template filepath.
            iframe_restriction: str or None. Possible values are
                'DENY' and 'SAMEORIGIN':

                DENY: Strictly prevents the template to load in an iframe.
                SAMEORIGIN: The template can only be displayed in a frame
                    on the same origin as the page itself.
        """
        values = self.values

        scheme, netloc, path, _, _ = python_utils.url_split(self.request.uri)

        values.update({
            'DEV_MODE':
            constants.DEV_MODE,
            'DOMAIN_URL':
            '%s://%s' % (scheme, netloc),
            'ACTIVITY_STATUS_PRIVATE':
            (rights_manager.ACTIVITY_STATUS_PRIVATE),
            'ACTIVITY_STATUS_PUBLIC': (rights_manager.ACTIVITY_STATUS_PUBLIC),
            # The 'path' variable starts with a forward slash.
            'FULL_URL':
            '%s://%s%s' % (scheme, netloc, path),
        })

        if 'status_code' not in values:
            values['status_code'] = 200

        if 'meta_name' not in values:
            values['meta_name'] = 'Personalized Online Learning from Oppia'

        if 'meta_description' not in values:
            values['meta_description'] = (
                'Oppia is a free, open-source learning platform. Join the '
                'community to create or try an exploration today!')

        # Create a new csrf token for inclusion in HTML responses. This assumes
        # that tokens generated in one handler will be sent back to a handler
        # with the same page name.

        self.response.cache_control.no_cache = True
        self.response.cache_control.must_revalidate = True
        self.response.headers[b'Strict-Transport-Security'] = (
            b'max-age=31536000; includeSubDomains')
        self.response.headers[b'X-Content-Type-Options'] = b'nosniff'
        self.response.headers[b'X-Xss-Protection'] = b'1; mode=block'

        if iframe_restriction is not None:
            if iframe_restriction in ['SAMEORIGIN', 'DENY']:
                self.response.headers[
                    b'X-Frame-Options'] = python_utils.convert_to_bytes(
                        iframe_restriction)
            else:
                raise Exception('Invalid X-Frame-Options: %s' %
                                iframe_restriction)

        self.response.expires = 'Mon, 01 Jan 1990 00:00:00 GMT'
        self.response.pragma = 'no-cache'

        self.response.write(
            self.jinja2_env.get_template(filepath).render(**values))
Ejemplo n.º 6
0
 def test_url_unsplit(self):
     response = python_utils.url_split('http://www.google.com')
     self.assertEqual(python_utils.url_unsplit(response),
                      'http://www.google.com')