def getInputValue(self):
     self._error = None
     action = self.action_widget.getInputValue()
     try:
         announcement_date = self.announcement_date_widget.getInputValue()
     except ConversionError:
         self._error = WidgetInputError(
             self.name, self.label,
             LaunchpadValidationError(
                 _('Please provide a valid date and time.')))
         raise self._error
     if action == 'immediately' and announcement_date is not None:
         self._error = WidgetInputError(
             self.name, self.label,
             LaunchpadValidationError(
                 _('Please do not provide a date if you want to publish '
                   'immediately.')))
         raise self._error
     if action == 'specific' and announcement_date is None:
         self._error = WidgetInputError(
             self.name, self.label,
             LaunchpadValidationError(
                 _('Please provide a publication date.')))
         raise self._error
     if action == 'immediately':
         return datetime.now(pytz.utc)
     elif action == "sometime":
         return None
     elif action == "specific":
         return announcement_date
     else:
         raise AssertionError('Unknown action in AnnouncementDateWidget')
Example #2
0
 def getInputValue(self):
     """See zope.formlib.interfaces.IInputWidget."""
     scope = self.request.form_ng.getOne(self.name)
     if scope == 'all':
         return None
     elif scope == 'project':
         if not self.request.form_ng.getOne(self.target_widget.name):
             self._error = WidgetInputError(
                 self.name, self.label,
                 LaunchpadValidationError('Please enter a project name'))
             raise self._error
         try:
             return self.target_widget.getInputValue()
         except ConversionError:
             entered_name = self.request.form_ng.getOne("%s.target" %
                                                        self.name)
             self._error = WidgetInputError(
                 self.name, self.label,
                 LaunchpadValidationError(
                     "There is no project named '%s' registered in"
                     " Launchpad" % entered_name))
             raise self._error
     elif self.required:
         raise UnexpectedFormData("No valid option was selected.")
     else:
         return None
Example #3
0
    def _validate(self, value):
        """Ensure the value is a valid URI."""

        uri = URI(self.normalize(value))

        if self.allowed_schemes and uri.scheme not in self.allowed_schemes:
            raise LaunchpadValidationError(
                'The URI scheme "%s" is not allowed.  Only URIs with '
                'the following schemes may be used: %s'
                % (uri.scheme, ', '.join(sorted(self.allowed_schemes))))

        if not self.allow_userinfo and uri.userinfo is not None:
            raise LaunchpadValidationError(
                'A username may not be specified in the URI.')

        if not self.allow_port and uri.port is not None:
            raise LaunchpadValidationError(
                'Non-default ports are not allowed.')

        if not self.allow_query and uri.query is not None:
            raise LaunchpadValidationError(
                'URIs with query strings are not allowed.')

        if not self.allow_fragment and uri.fragment is not None:
            raise LaunchpadValidationError(
                'URIs with fragment identifiers are not allowed.')

        super(URIField, self)._validate(value)
Example #4
0
def channels_validator(channels):
    """Return True if the channels in a list are valid, or raise a
    LaunchpadValidationError.
    """
    tracks = set()
    branches = set()
    for name in channels:
        try:
            track, risk, branch = split_channel_name(name)
        except ValueError:
            message = _(
                "Invalid channel name '${name}'. Channel names must be of the "
                "form 'track/risk/branch', 'track/risk', 'risk/branch', or "
                "'risk'.",
                mapping={'name': html_escape(name)})
            raise LaunchpadValidationError(structured(message))
        tracks.add(track)
        branches.add(branch)

    # XXX cjwatson 2018-05-08: These are slightly arbitrary restrictions,
    # but they make the UI much simpler.

    if len(tracks) != 1:
        message = _("Channels must belong to the same track.")
        raise LaunchpadValidationError(structured(message))

    if len(branches) != 1:
        message = _("Channels must belong to the same branch.")
        raise LaunchpadValidationError(structured(message))

    return True
Example #5
0
 def _valid_image(self, image):
     """Check that the given image is under the given constraints."""
     # No global import to avoid hard dependency on PIL being installed
     import PIL.Image
     if len(image) > self.max_size:
         raise LaunchpadValidationError(_(dedent("""
             This image exceeds the maximum allowed size in bytes.""")))
     try:
         pil_image = PIL.Image.open(StringIO(image))
     except (IOError, ValueError):
         raise LaunchpadValidationError(_(dedent("""
             The file uploaded was not recognized as an image; please
             check it and retry.""")))
     width, height = pil_image.size
     required_width, required_height = self.dimensions
     if self.exact_dimensions:
         if width != required_width or height != required_height:
             raise LaunchpadValidationError(_(dedent("""
                 This image is not exactly ${width}x${height}
                 pixels in size."""),
                 mapping={'width': required_width,
                          'height': required_height}))
     else:
         if width > required_width or height > required_height:
             raise LaunchpadValidationError(_(dedent("""
                 This image is larger than ${width}x${height}
                 pixels in size."""),
                 mapping={'width': required_width,
                          'height': required_height}))
     return True
 def getInputValue(self):
     """See zope.formlib.interfaces.IInputWidget."""
     self.setUpSubWidgets()
     form_value = self.request.form_ng.getOne(self.name)
     if form_value == 'product':
         try:
             return self.product_widget.getInputValue()
         except MissingInputError:
             self._error = WidgetInputError(
                 self.name, self.label,
                 LaunchpadValidationError('Please enter a project name'))
             raise self._error
         except ConversionError:
             entered_name = self.request.form_ng.getOne("%s.product" %
                                                        self.name)
             self._error = WidgetInputError(
                 self.name, self.label,
                 LaunchpadValidationError(
                     "There is no project named '%s' registered in"
                     " Launchpad" % entered_name))
             raise self._error
     elif form_value == 'package':
         try:
             distribution = self.distribution_widget.getInputValue()
         except ConversionError:
             entered_name = self.request.form_ng.getOne("%s.distribution" %
                                                        self.name)
             self._error = WidgetInputError(
                 self.name, self.label,
                 LaunchpadValidationError(
                     "There is no distribution named '%s' registered in"
                     " Launchpad" % entered_name))
             raise self._error
         if self.package_widget.hasInput():
             try:
                 package_name = self.package_widget.getInputValue()
                 if package_name is None:
                     return distribution
                 if IDistributionSourcePackage.providedBy(package_name):
                     dsp = package_name
                 else:
                     source_name = (
                         distribution.guessPublishedSourcePackageName(
                             package_name.name))
                     dsp = distribution.getSourcePackage(source_name)
             except (ConversionError, NotFoundError):
                 entered_name = self.request.form_ng.getOne('%s.package' %
                                                            self.name)
                 self._error = WidgetInputError(
                     self.name, self.label,
                     LaunchpadValidationError(
                         "There is no package named '%s' published in %s." %
                         (entered_name, distribution.displayname)))
                 raise self._error
             return dsp
         else:
             return distribution
     else:
         raise UnexpectedFormData("No valid option was selected.")
Example #7
0
def validate_cvs_module(cvsmodule):
    valid_module = re.compile('^[a-zA-Z][a-zA-Z0-9_/.+-]*$')
    if not valid_module.match(cvsmodule):
        raise LaunchpadValidationError(
            'The CVS module contains illegal characters.')
    if cvsmodule == 'CVS':
        raise LaunchpadValidationError('A CVS module can not be called "CVS".')
    return True
Example #8
0
def validate_cvs_root(cvsroot):
    try:
        root = CVSRoot(cvsroot)
    except CvsRootError as e:
        raise LaunchpadValidationError(e)
    if root.method == 'local':
        raise LaunchpadValidationError('Local CVS roots are not allowed.')
    if not root.hostname:
        raise LaunchpadValidationError('CVS root is invalid.')
    if root.hostname.count('.') == 0:
        raise LaunchpadValidationError(
            'Please use a fully qualified host name.')
    return True
Example #9
0
def file_size_constraint(value, max_size):
    """Check constraints.

    The file cannot be empty and must be <= max_size.
    """
    size = len(value)
    if size == 0:
        raise LaunchpadValidationError(u'Cannot upload empty file.')
    elif max_size > 0 and size > max_size:
        raise LaunchpadValidationError(
            u'Cannot upload files larger than %i bytes' % max_size)
    else:
        return True
Example #10
0
def attachment_size_constraint(value):
    """Constraint for an attachment's file size.

    The file is not allowed to be empty.
    """
    size = len(value)
    max_size = config.launchpad.max_attachment_size
    if size == 0:
        raise LaunchpadValidationError(u'Cannot upload empty file.')
    elif max_size > 0 and size > max_size:
        raise LaunchpadValidationError(
            u'Cannot upload files larger than %i bytes' % max_size)
    else:
        return True
Example #11
0
 def _validate(self, version):
     """See `UniqueField`."""
     super(DistroSeriesVersionField, self)._validate(version)
     if not sane_version(version):
         raise LaunchpadValidationError("%s is not a valid version" %
                                        version)
     # Avoid circular import hell.
     from lp.archivepublisher.debversion import Version, VersionError
     try:
         # XXX sinzui 2009-07-25 bug=404613: DistributionMirror and buildd
         # have stricter version rules than the schema. The version must
         # be a debversion.
         Version(version)
     except VersionError as error:
         raise LaunchpadValidationError("'%s': %s" % (version, error))
    def _validate(self, value):
        # import here to avoid circular import
        from lp.services.webapp import canonical_url
        from lazr.uri import URI

        super(DistroMirrorURIField, self)._validate(value)
        uri = URI(self.normalize(value))

        # This field is also used when creating new mirrors and in that case
        # self.context is not an IDistributionMirror so it doesn't make sense
        # to try to get the existing value of the attribute.
        if IDistributionMirror.providedBy(self.context):
            orig_value = self.get(self.context)
            if orig_value is not None and URI(orig_value) == uri:
                return  # url was not changed

        mirror = self.getMirrorByURI(str(uri))
        if mirror is not None:
            message = _(
                'The distribution mirror <a href="${url}">${mirror}</a> '
                'is already registered with this URL.',
                mapping={
                    'url': html_escape(canonical_url(mirror)),
                    'mirror': html_escape(mirror.title)
                })
            raise LaunchpadValidationError(structured(message))
Example #13
0
def valid_webref(web_ref):
    """Returns True if web_ref is a valid download URL, or raises a
    LaunchpadValidationError.

    >>> valid_webref('http://example.com')
    True
    >>> valid_webref('https://example.com/foo/bar')
    True
    >>> valid_webref('ftp://example.com/~ming')
    True
    >>> valid_webref('sftp://example.com//absolute/path/maybe')
    True
    >>> valid_webref('other://example.com/moo')
    Traceback (most recent call last):
    ...
    LaunchpadValidationError: ...
    """
    if validate_url(web_ref, ['http', 'https', 'ftp', 'sftp']):
        # Allow ftp so valid_webref can be used for download_url, and so
        # it doesn't lock out weird projects where the site or
        # screenshots are kept on ftp.
        return True
    else:
        raise LaunchpadValidationError(_(dedent("""
            Not a valid URL. Please enter the full URL, including the
            scheme (for instance, http:// for a web URL), and ensure the
            URL uses either http, https or ftp.""")))
Example #14
0
    def _validate(self, input):
        """Make sure all the aliases are valid for the field's pillar.

        An alias is valid if it can be used as the name of a pillar and is
        not identical to the pillar's existing name.
        """
        context = self.context
        from lp.registry.interfaces.product import IProduct
        from lp.registry.interfaces.projectgroup import IProjectGroup
        from lp.registry.interfaces.distribution import IDistribution
        if IProduct.providedBy(context):
            name_field = IProduct['name']
        elif IProjectGroup.providedBy(context):
            name_field = IProjectGroup['name']
        elif IDistribution.providedBy(context):
            name_field = IDistribution['name']
        else:
            raise AssertionError("Unexpected context type.")
        name_field.bind(context)
        existing_aliases = context.aliases
        for name in self._split_input(input):
            if name == context.name:
                raise LaunchpadValidationError('This is your name: %s' % name)
            elif name in existing_aliases:
                # This is already an alias to this pillar, so there's no need
                # to validate it.
                pass
            else:
                name_field._validate(name)
Example #15
0
 def _validate(self, input):
     """Check that the URL is not already in use by another bugtracker."""
     super(BugTrackerURL, self)._validate(input)
     bugtracker = getUtility(IBugTrackerSet).queryByBaseURL(input)
     if bugtracker is not None and bugtracker != self.context:
         raise LaunchpadValidationError(
             '%s is already registered in Launchpad as "%s" (%s).'
             % (input, bugtracker.title, bugtracker.name))
Example #16
0
def valid_cve_sequence(value):
    """Check if the given value is a valid CVE otherwise raise an exception.
    """
    if valid_cve(value):
        return True
    else:
        raise LaunchpadValidationError(
            _("${cve} is not a valid CVE number", mapping={'cve': value}))
Example #17
0
def builder_url_validator(url):
    """Return True if the url is valid, or raise a LaunchpadValidationError"""
    if not valid_builder_url(url):
        raise LaunchpadValidationError(_(dedent("""
            Invalid builder url '${url}'. Builder urls must be
            http://host/ or http://host:port/ only.
            """), mapping={'url': url}))
    return True
def validate_release_glob(value):
    """Validate that the URL is supported."""
    parts = urlparse(value)
    if (validate_url(value, ["http", "https", "ftp"]) and '*' in parts[2]):
        # The product release finder does support the url scheme and
        # can match more than one file to the url's path part.
        return True
    else:
        raise LaunchpadValidationError('Invalid release URL pattern.')
Example #19
0
    def getInputValue(self):
        self._error = None
        action = self.action_widget.getInputValue()
        form = self.request.form_ng
        if action == 'change' and not form.getOne(self.image_widget.name):
            self._error = WidgetInputError(
                self.name, self.label,
                LaunchpadValidationError(
                    _('Please specify the image you want to use.')))
            raise self._error
        if action == "keep":
            if self.style == self.ADD_STYLE:
                # It doesn't make any sense to return KEEP_SAME_IMAGE in this
                # case, since there's nothing to keep.
                return None
            elif self.style == self.EDIT_STYLE:
                return KEEP_SAME_IMAGE
            else:
                raise AssertionError(
                    "Style must be one of EDIT_STYLE or ADD_STYLE, got %s" %
                    self.style)
        elif action == "change":
            self._image = form.getOne(self.image_widget.name)
            try:
                self.context.validate(self._image)
            except ValidationError as v:
                self._error = WidgetInputError(self.name, self.label, v)
                raise self._error
            self._image.seek(0)
            content = self._image.read()
            filename = self._image.filename
            type, dummy = guess_content_type(name=filename, body=content)

            # This method may be called more than once in a single request. If
            # that's the case here we'll simply return the cached
            # LibraryFileAlias we already have.
            existing_alias = self._image_file_alias
            if existing_alias is not None:
                assert existing_alias.filename == filename, (
                    "The existing LibraryFileAlias' name doesn't match the "
                    "given image's name.")
                assert existing_alias.content.filesize == len(content), (
                    "The existing LibraryFileAlias' size doesn't match "
                    "the given image's size.")
                assert existing_alias.mimetype == type, (
                    "The existing LibraryFileAlias' type doesn't match "
                    "the given image's type.")
                return existing_alias

            self._image_file_alias = getUtility(ILibraryFileAliasSet).create(
                name=filename,
                size=len(content),
                file=StringIO(content),
                contentType=type)
            return self._image_file_alias
        elif action == "delete":
            return None
Example #20
0
 def test_getInputValue_person_missing(self):
     # An error is raised when the person field is missing.
     form = self.form
     form["field.grantee"] = "person"
     del form["field.grantee.person"]
     self.widget.request = LaunchpadTestRequest(form=form)
     message = "Please enter a person or team name"
     e = self.assertRaises(WidgetInputError, self.widget.getInputValue)
     self.assertEqual(LaunchpadValidationError(message), e.errors)
Example #21
0
    def parseLine(self, line):
        workitem_match = WORKITEM_RE.search(line)
        if workitem_match:
            assignee = workitem_match.group('assignee')
            title = workitem_match.group('title')
            status = workitem_match.group('status')
        else:
            raise LaunchpadValidationError(
                'Invalid work item format: "%s"' % line)
        if title == '':
            raise LaunchpadValidationError(
                'No work item title found on "%s"' % line)
        if title.startswith('['):
            raise LaunchpadValidationError(
                'Missing closing "]" for assignee on "%s".' % line)

        return {'title': title, 'status': status.strip().upper(),
                'assignee': assignee}
Example #22
0
 def getAssignee(self, assignee_name):
     if assignee_name is None:
         return None
     from lp.registry.interfaces.person import IPersonSet
     assignee = getUtility(IPersonSet).getByName(assignee_name)
     if assignee is None:
         raise LaunchpadValidationError(
             "Unknown person name: %s" % assignee_name)
     return assignee
Example #23
0
 def getInputValue(self):
     """See `IInputWidget`."""
     self.setUpSubWidgets()
     track = self.track_widget.getInputValue()
     risks = self.risks_widget.getInputValue()
     branch = self.branch_widget.getInputValue()
     if track and self._separator in track:
         error_msg = "Track name cannot include '%s'." % self._separator
         raise WidgetInputError(self.name, self.label,
                                LaunchpadValidationError(error_msg))
     if branch and self._separator in branch:
         error_msg = "Branch name cannot include '%s'." % self._separator
         raise WidgetInputError(self.name, self.label,
                                LaunchpadValidationError(error_msg))
     channels = [
         self.buildChannelName(track, risk, branch) for risk in risks
     ]
     return channels
Example #24
0
def valid_bug_number(value):
    from lp.bugs.interfaces.bug import IBugSet
    bugset = getUtility(IBugSet)
    try:
        bugset.get(value)
    except NotFoundError:
        raise LaunchpadValidationError(
            _("Bug ${bugid} doesn't exist.", mapping={'bugid': value}))
    return True
Example #25
0
 def getInputValue(self):
     """See `IInputWidget`."""
     self.setUpSubWidgets()
     try:
         repository = self.repository_widget.getInputValue()
     except MissingInputError:
         if self.context.required:
             raise WidgetInputError(
                 self.name, self.label,
                 LaunchpadValidationError(
                     "Please choose a Git repository."))
         else:
             return None
     except ConversionError:
         entered_name = self.request.form_ng.getOne("%s.repository" %
                                                    self.name)
         raise WidgetInputError(
             self.name, self.label,
             LaunchpadValidationError(
                 "There is no Git repository named '%s' registered in "
                 "Launchpad." % entered_name))
     if self.path_widget.hasInput():
         path = self.path_widget.getInputValue()
     else:
         path = None
     if not path:
         if self.context.required:
             raise WidgetInputError(
                 self.name, self.label,
                 LaunchpadValidationError(
                     "Please enter a Git branch path."))
         else:
             return
     if self.allow_external and not IGitRepository.providedBy(repository):
         ref = getUtility(IGitRefRemoteSet).new(repository, path)
     else:
         ref = repository.getRefByPath(path)
         if ref is None:
             raise WidgetInputError(
                 self.name, self.label,
                 LaunchpadValidationError(
                     "The repository at %s does not contain a branch named "
                     "'%s'." % (repository.display_name, path)))
     return ref
Example #26
0
def valid_remote_bug_url(value):
    """Verify that the URL is to a bug to a known bug tracker."""
    try:
        getUtility(IBugWatchSet).extractBugTrackerAndBug(value)
    except NoBugTrackerFound:
        pass
    except UnrecognizedBugTrackerURL:
        raise LaunchpadValidationError(
            "Launchpad does not recognize the bug tracker at this URL.")
    return True
Example #27
0
 def test_getInputValue_product_missing(self):
     # An error is raised when the product field is missing.
     form = self.form
     form['field.target'] = 'product'
     del form['field.target.product']
     self.widget.request = LaunchpadTestRequest(form=form)
     message = 'Please enter a project name'
     e = self.assertRaises(WidgetInputError, self.widget.getInputValue)
     self.assertEqual(LaunchpadValidationError(message), e.errors)
     self.assertEqual(message, self.widget.error())
Example #28
0
 def test_getInputValue_package_invalid(self):
     # An error is raised when the package is not published in the distro.
     form = self.form
     form['field.target.package'] = 'non-existent'
     self.widget.request = LaunchpadTestRequest(form=form)
     message = (
         "There is no package named 'non-existent' published in Fnord.")
     e = self.assertRaises(WidgetInputError, self.widget.getInputValue)
     self.assertEqual(LaunchpadValidationError(message), e.errors)
     self.assertEqual(html_escape(message), self.widget.error())
Example #29
0
 def test_getInputValue_project_invalid(self):
     # An error is raised when the project is not valid.
     form = self.form
     form["field.target"] = "project"
     form["field.target.project"] = "non-existent"
     self.widget.request = LaunchpadTestRequest(form=form)
     message = ("There is no project named 'non-existent' registered in "
                "Launchpad")
     e = self.assertRaises(WidgetInputError, self.widget.getInputValue)
     self.assertEqual(LaunchpadValidationError(message), e.errors)
     self.assertEqual(html_escape(message), self.widget.error())
Example #30
0
def git_repository_name_validator(name):
    """Return True if the name is valid, or raise a LaunchpadValidationError.
    """
    if not valid_git_repository_name(name):
        raise LaunchpadValidationError(
            _("Invalid Git repository name '${name}'. ${message}",
              mapping={
                  "name": name,
                  "message": GIT_REPOSITORY_NAME_VALIDATION_ERROR_MESSAGE,
              }))
    return True
Example #31
0
 def __init__(self, name):
     self.name = name
     LaunchpadValidationError.__init__(
         self, "Invalid name for product: %s." % (name, ))