class PhotoGallery(CodeSource):
    """A photo gallery to show thumbnails and the original pictures
    within a Silva document.
    """
    silvaconf.zmi_addable(True)
    silvaconf.factory('manage_addPhotoGalleryForm')
    silvaconf.factory('manage_addPhotoGallery')
    meta_type = 'Silva Photo Gallery Source'
    security = ClassSecurityInfo()

    _is_initialized = True

    def __init__(self, id):
        super(PhotoGallery, self).__init__(id)
        self._script_id = 'view'
        self._data_encoding = 'UTF-8'
        self._description = self.__doc__
        self._is_initialized = False

    security.declareProtected(SilvaPermissions.ChangeSilvaAccess,
                                'refresh')
    def refresh(self):
        """reload the form and pt"""
        if 'view' in self.objectIds():
            self.manage_delObjects(['view'])
        self._set_form()
        self._set_views()
        return 'refreshed form and pagetemplate'

    def _set_form(self):
        self.parameters = ZMIForm('form', 'Properties Form')
        with open(os.path.join(_home, 'photo_gallery_form.form')) as form:
            XMLToForm(form.read(), self.parameters)

    def _set_views(self):
        with open(os.path.join(_home, 'photo_gallery_view.pt')) as template:
            self._setObject('view', ZopePageTemplate('view', template.read()))

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'includeResources')
    def includeResources(self):
        need(IPhotoGalleryResources)
        return u''

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'getPhotos')
    def getPhotos(self, model):
        """Returns a sorted list of photos found in the container.
        """
        return model.get_container().get_non_publishables(IImage)

    security.declarePublic('getCaption')
    def getCaption(self, caption):
        lenCaption = 42
        if len(caption) < lenCaption:
            return caption
        return caption[:lenCaption-3].rstrip() + '...'
Пример #2
0
class Article(VersionedContent):
    meta_type = 'My Article'

    silvaconf.versionClass(ArticleVersion)
    silvaconf.factory('manage_addMyArticle')

    customCreation = False  # For test only
Пример #3
0
class SimpleMember(Member, Security, ZMIObject):
    """Silva Simple Member"""

    grok.implements(interfaces.IEditableMember)
    security = ClassSecurityInfo()

    meta_type = 'Silva Simple Member'

    silvaconf.icon('icons/member.png')
    silvaconf.factory('manage_addSimpleMemberForm')
    silvaconf.factory('manage_addSimpleMember')

    # BBB
    _avatar = None

    def __init__(self, id):
        self.id = id
        self._title = id
        self._fullname = None
        self._email = None
        self._avatar = None
        self._creation_datetime = self._modification_datetime = DateTime()
        self._is_approved = 0

    security.declarePrivate('allowed_roles')
    def allowed_roles(self):
        return roleinfo.ASSIGNABLE_ROLES

    security.declareProtected(SilvaPermissions.ChangeSilvaAccess,
                              'set_fullname')
    def set_fullname(self, fullname):
        """set the full name"""
        self._fullname = fullname

    security.declareProtected(SilvaPermissions.ChangeSilvaAccess,
                              'set_email')
    def set_email(self, email):
        """ set the email address.
           (does not test, if email address is valid)
        """
        self._email = email

    security.declareProtected(SilvaPermissions.ChangeSilvaAccess,
                              'set_avatar')
    def set_avatar(self, avatar):
        """Set the email address to be used by gravatar"""
        self._avatar = avatar

    security.declareProtected(SilvaPermissions.ChangeSilvaAccess,
                              'approve')
    def approve(self):
        """Approve the member"""
        self._is_approved = 1

    # ACCESSORS
    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'userid')
    def userid(self):
        """userid
        """
        return self.id

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'fullname')
    def fullname(self):
        """fullname
        """
        if self._fullname is None:
            return self.id
        return self._fullname

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'email')
    def email(self):
        """email
        """
        return self._email

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'extra')
    def extra(self, name):
        """Return bit of extra information, keyed by name.
        """
        #For CachedMember accessing of the avatar tag
        #Should be 'avatar_tag:SIZE' -- ie, 'avatar_tag:32'
        if name.startswith("avatar_tag"):
            return self.avatar_tag(name.split(':')[1])

        return None

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'avatar')
    def avatar(self):
        """Return the email address to be used by gravatar. Return '' if
        no address has been specified.
        """
        return self._avatar if self._avatar is not None else self._email


    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'is_approved')
    def is_approved(self):
        """is_approved
        """
        return self._is_approved
Пример #4
0
class Root(Publication):
    """Root of Silva site.
    """
    security = ClassSecurityInfo()

    meta_type = "Silva Root"

    # We do not want to register Root automaticaly.
    grok.implements(IRoot)
    silvaconf.icon('icons/root.png')
    silvaconf.zmi_addable(True)
    silvaconf.factory('manage_addRootForm')
    silvaconf.factory('manage_addRoot')

    _smi_skin = 'silva.ui.interfaces.ISilvaUITheme'
    _properties = Publication._properties + ({
        'id': '_smi_skin',
        'label': 'Skin SMI',
        'type': 'string',
        'mode': 'w'
    }, )

    def __init__(self, id):
        super(Root, self).__init__(id)
        # if we add a new root, version starts out as the software version
        self._content_version = self.get_silva_software_version()

    # MANIPULATORS

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'validate_wanted_quota')

    def validate_wanted_quota(self, value, REQUEST=None):
        """Validate the wanted quota is correct the current
        publication.
        """
        if value < 0:
            # Quota can't be negative.
            return False
        if not value:
            # 0 or means no quota.
            return True
        # Quota can't be be bigger than the site quota.
        if self.service_extensions._site_quota:
            if self.service_extensions._site_quota < value:
                return False
        return True

    security.declareProtected(SilvaPermissions.ApproveSilvaContent,
                              'to_folder')

    def to_folder(self):
        """Don't do anything here. Can't do this with root.
        """
        raise ContentError(_("Root cannot be converted to folder."), self)

    security.declareProtected(SilvaPermissions.ApproveSilvaContent,
                              'to_publication')

    def to_publication(self):
        """Don't do anything here. Can't do this with root.
        """
        raise ContentError(_("Root cannot be converted to publication."), self)

    security.declareProtected(SilvaPermissions.ChangeSilvaAccess,
                              'add_silva_addable_forbidden')

    def add_silva_addable_forbidden(self, meta_type):
        """Add a meta_type that is forbidden from use in this site.
        """
        addables_forbidden = getattr(self.aq_base, '_addables_forbidden', {})
        addables_forbidden[meta_type] = 0
        self._addables_forbidden = addables_forbidden

    security.declareProtected(SilvaPermissions.ChangeSilvaAccess,
                              'clear_silva_addables_forbidden')

    def clear_silva_addables_forbidden(self):
        """Clear out all forbidden addables; everything allowed now.
        """
        self._addables_forbidden = {}

    # ACCESSORS
    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'get_root')

    def get_root(self):
        """Get root of site. Can be used with acquisition get the
        'nearest' Silva root.
        """
        return self.aq_inner

    security.declareProtected(SilvaPermissions.ReadSilvaContent,
                              'is_silva_addable_forbidden')

    def is_silva_addable_forbidden(self, meta_type):
        """Return true if addable is forbidden to be used in this
        site.
        """
        if not hasattr(self.aq_base, '_addables_forbidden'):
            return False
        return meta_type in self._addables_forbidden

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'get_current_quota')

    def get_current_quota(self):
        """Return the current quota value on the publication.
        """
        site = getUtility(IExtensionService).get_site_quota()
        binding = getUtility(IMetadataService).getMetadata(self)
        try:
            local = int(binding.get('silva-quota', element_id='quota') or 0)
            if local < 0:
                local = 0
        except KeyError:
            local = 0
        if site and local:
            return min(site, local)
        if site:
            return site
        return local

    security.declarePublic('get_silva_software_version')

    def get_silva_software_version(self):
        """The version of the Silva software.
        """
        return extensionRegistry.get_extension('Silva').version

    security.declareProtected(SilvaPermissions.ReadSilvaContent,
                              'get_silva_content_version')

    def get_silva_content_version(self):
        """Return the version of Silva content.

        This version is usually the same as the software version, but
        can be different in case the content was not yet updated.
        """
        return getattr(self, '_content_version', 'before 0.9.2')

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'get_real_container')

    def get_real_container(self):
        """Get the container, even if we're a container.

        If we're the root object, returns None.

        Can be used with acquisition to get the 'nearest' container.
        """
        return None
Пример #5
0
class Image(Asset):
    __doc__ = _("""Web graphics (gif, jpg, png) can be uploaded and inserted in
       documents, or used as viewable assets.
    """)
    security = ClassSecurityInfo()

    meta_type = "Silva Image"

    grok.implements(interfaces.IImage)

    re_WidthXHeight = re.compile(r'^([0-9]+|\*)[Xx]([0-9\*]+|\*)$')
    re_percentage = re.compile(r'^([0-9\.]+)\%$')
    re_box = re.compile(r'^([0-9]+)[Xx]([0-9]+)-([0-9]+)[Xx]([0-9]+)')

    thumbnail_size = Size(120, 120)

    image = None
    hires_image = None
    thumbnail_image = None
    web_scale = '100%'
    web_crop = ''
    web_format = Format.JPEG
    web_formats = (Format.JPEG, Format.GIF, Format.PNG)

    _web2ct = {
        Format.JPEG: 'image/jpeg',
        Format.GIF: 'image/gif',
        Format.PNG: 'image/png',
    }

    silvaconf.priority(-3)
    silvaconf.icon('icons/image.gif')
    silvaconf.factory('manage_addImage')

    security.declareProtected(SilvaPermissions.ChangeSilvaContent,
                              'set_web_presentation_properties')

    def set_web_presentation_properties(self, web_format, web_scale, web_crop):
        """Sets format and scaling for web presentation.

        web_format (str): either JPEG or PNG (or whatever other format
        makes sense, must be recognised by PIL).
        web_scale (str): WidthXHeight or nn.n%.
        web_crop (str): X1xY1-X2xY2, crop-box or empty for no cropping.


        Automaticaly updates cached web presentation image.
        """
        update = False
        if self.hires_image is None:
            update = True
            self.hires_image = self.image
            self.image = None

        # Set web format.
        if web_format not in ('unknown', '') and self.web_format != web_format:
            if web_format in self.web_formats:
                self.web_format = web_format
                update = True
            else:
                raise ValueError('Unknown image format %s' % web_format)
        # check if web_scale can be parsed:
        try:
            self.get_canonical_web_scale(web_scale)
        except ValueError:
            # if not, we set web_scale back to default value
            web_scale = '100%'

        if self.web_scale != web_scale:
            self.web_scale = web_scale
            update = True
        # check if web_crop can be parsed:
        self.get_crop_box(web_crop)
        if self.web_crop != web_crop:
            # if web_crop is None it should be replaced by an empty string
            self.web_crop = web_crop and web_crop or ''
            update = True
        if update and self.hires_image is not None:
            self._create_derived_images()

    security.declareProtected(SilvaPermissions.ChangeSilvaContent, 'set_image')

    def set_image(self, file):
        """Set the image object.
        """
        validate_image(file)
        self._image_factory('hires_image', file)
        # Image change, reset scale, crop box: they can be invalid for
        # this new image.
        format = self.get_format()
        if format in self.web_formats:
            self.web_format = format
        self.web_scale = '100%'
        self.web_crop = ''
        self._create_derived_images()
        # XXX Should be on event
        self.update_quota()

    security.declareProtected(SilvaPermissions.View, 'get_image')

    def get_image(self, hires=True, webformat=False):
        """Return image data.
        """
        if hires:
            if self.hires_image is not None:
                if webformat:
                    # Create web format of original image.
                    with ImageFile(self.hires_image) as working:
                        data = working.save(self.web_format)
                    if data is not None:
                        return data.getvalue()
                # Original format of the original image is the orginal.
                return self.hires_image.get_file()
            return None
        if self.image is not None:
            if webformat:
                # Webformat of the cropped/resized image is already computed.
                return self.image.get_file()
            # Original format of the cropped/resize image is not possible.
            raise ValueError(
                _(u"Low resolution image in original format is "
                  u"not supported"))
        return None

    security.declareProtected(SilvaPermissions.View, 'get_canonical_web_scale')

    def get_canonical_web_scale(self, scale=None):
        """returns (width, height) of web image"""
        if scale is None:
            scale = self.web_scale
        m = self.re_WidthXHeight.match(scale)
        if m is None:
            m = self.re_percentage.match(scale)
            if m is None:
                msg = _(
                    "'${scale}' is not a valid scale identifier. "
                    "Probably a percent symbol is missing.",
                    mapping={'scale': scale})
                raise ValueError(msg)
            cropbox = Rect.parse(self.web_crop)
            if cropbox:
                width, height = cropbox.size
            else:
                width, height = self.get_dimensions()
            percentage = float(m.group(1)) / 100.0
            width = int(width * percentage)
            height = int(height * percentage)
        else:
            img_w, img_h = self.get_dimensions()
            width = m.group(1)
            height = m.group(2)
            if width == height == '*':
                msg = _(
                    "'${scale} is not a valid scale identifier. "
                    "At least one number is required.",
                    mapping={'scale': scale})
                raise ValueError(msg)
            if width == '*':
                height = int(height)
                width = img_w * height / img_h
            elif height == '*':
                width = int(width)
                height = img_h * width / img_w
            else:
                width = int(width)
        return width, height

    security.declareProtected(SilvaPermissions.View, 'get_crop_box')

    def get_crop_box(self, crop=None):
        """return crop box"""
        crop = crop or self.web_crop
        if crop is None or crop.strip() == '':
            return None
        rect = Rect.parse(crop)
        if rect is None:
            msg = _("'${crop} is not a valid crop identifier",
                    mapping={'crop': crop})
            raise ValueError(msg)
        with ImageFile(self.hires_image) as image:
            Crop(rect).validate(image)
        return (rect.lower_edge.x, rect.lower_edge.y, rect.higher_edge.x,
                rect.higher_edge.y)

    security.declareProtected(SilvaPermissions.View, 'get_dimensions')

    def get_dimensions(self, thumbnail=False, hires=False):
        """Returns width, heigt of (hi res) image.

        Raises ValueError if there is no way of determining the dimenstions,
        Return 0, 0 if there is no image,
        Returns width, height otherwise.
        """
        data = None
        if thumbnail:
            data = self.thumbnail_image
        elif hires:
            data = self.hires_image
        else:
            data = self.image

        if data is None:
            return Size(0, 0)
        try:
            with ImageFile(data) as image:
                return image.get_size()
        except (ValueError, TypeError):
            return Size(0, 0)

    security.declareProtected(SilvaPermissions.View, 'tag')

    def tag(self,
            hires=False,
            thumbnail=False,
            request=None,
            preview=False,
            **extra_attributes):
        warnings.warn(
            'tag have been replaced with get_html_tag. '
            'It will be removed, please update your code.',
            DeprecationWarning,
            stacklevel=2)
        return self.get_html_tag(hires=hires,
                                 thumbnail=thumbnail,
                                 request=request,
                                 preview=preview,
                                 **extra_attributes)

    security.declareProtected(SilvaPermissions.View, 'get_html_tag')

    def get_html_tag(self,
                     preview=False,
                     request=None,
                     hires=False,
                     thumbnail=False,
                     **extra_attributes):
        """ return xhtml tag

        Since 'class' is a Python reserved word, it cannot be passed in
        directly in keyword arguments which is a problem if you are
        trying to use 'tag()' to include a CSS class. The tag() method
        will accept a 'css_class' argument that will be converted to
        'class' in the output tag to work around this.
        """
        url = self.get_download_url(request=request,
                                    preview=preview,
                                    hires=hires,
                                    thumbnail=thumbnail)

        title = self.get_title_or_id()
        width, height = self.get_dimensions(thumbnail=thumbnail, hires=hires)
        if extra_attributes.has_key('css_class'):
            extra_attributes['class'] = extra_attributes['css_class']
            del extra_attributes['css_class']

        extra_html_attributes = [
            u'{name}="{value}"'.format(name=escape(name, 1),
                                       value=escape(value, 1))
            for name, value in extra_attributes.iteritems()
        ]

        return u'<img src="{src}" width="{width}" height="{height}" ' \
               u'alt="{alt}" {extra_attributes} />'.format(
                    src=url,
                    width=str(width),
                    height=str(height),
                    alt=escape(title, 1),
                    extra_attributes=u" ".join(extra_html_attributes))

    security.declareProtected(SilvaPermissions.View, 'url')

    def url(self, hires=False, thumbnail=False, request=None, preview=False):
        warnings.warn(
            'url have been replaced with get_download_url. '
            'It will be removed, please update your code.',
            DeprecationWarning,
            stacklevel=2)
        return self.get_download_url(hires=hires,
                                     thumbnail=thumbnail,
                                     request=request,
                                     preview=preview)

    security.declareProtected(SilvaPermissions.View, 'get_download_url')

    def get_download_url(self,
                         preview=False,
                         request=None,
                         hires=False,
                         thumbnail=False):
        "return url of image"
        if request is None:
            request = self.REQUEST
        url = getMultiAdapter((self, request),
                              IContentURL).url(preview=preview)
        more = '?'
        if hires:
            url += '?hires'
            more = '&'
        elif thumbnail:
            url += '?thumbnail'
            more = '&'
        if preview:
            # In case of preview we add something that change at the
            # end of the url to prevent caching from the browser.
            url += more + str(int(time.time()))
        return url

    security.declareProtected(SilvaPermissions.View, 'get_web_format')

    def get_web_format(self):
        """Return file format of web presentation image
        """
        try:
            with ImageFile(self.image) as image:
                return image.get_format()
        except (ValueError, TypeError):
            return 'unknown'

    security.declareProtected(SilvaPermissions.View, 'get_web_scale')

    def get_web_scale(self):
        """Return scale percentage / WxH of web presentation image
        """
        return str(self.web_scale)

    security.declareProtected(SilvaPermissions.View, 'get_web_crop')

    def get_web_crop(self):
        """Return crop identifier
        """
        return str(self.web_crop)

    security.declareProtected(SilvaPermissions.View, 'get_orientation')

    def get_orientation(self):
        """Returns translated Image orientation (string).
        """
        width, height = self.get_dimensions()
        if width == height:
            return _("square")
        elif width > height:
            return _("landscape")
        return _("portrait")

    security.declareProtected(SilvaPermissions.ChangeSilvaContent,
                              'get_file_system_path')

    def get_file_system_path(self):
        """return path on filesystem for containing image"""
        if self.hires_image is not None:
            return self.hires_image.get_file_system_path()
        return None

    security.declareProtected(SilvaPermissions.View, 'get_format')

    def get_format(self):
        """Returns image format.
        """
        try:
            with ImageFile(self.hires_image) as image:
                return image.get_format()
        except (ValueError, TypeError):
            return 'unknown'

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'get_filename')

    def get_filename(self):
        if self.hires_image is None:
            return self.getId()
        return self.hires_image.get_filename()

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'get_mime_type')

    def get_mime_type(self):
        if self.hires_image is None:
            return 'application/octet-stream'
        return self.hires_image.get_mime_type()

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'get_content_type')

    def get_content_type(self):
        if self.hires_image is None:
            return 'application/octet-stream'
        return self.hires_image.get_content_type()

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'get_file_size')

    def get_file_size(self):
        if self.hires_image is None:
            return 0
        return self.hires_image.get_file_size()

    ##########
    ## private

    def _create_derived_images(self):
        self._create_web_presentation()
        self._create_thumbnail()

    def _create_web_presentation(self):
        try:
            transformer = Transformer()
            cropbox = self.get_crop_box()
            if cropbox is not None:
                crop_rect = Rect.from_points(Point(cropbox[0], cropbox[1]),
                                             Point(cropbox[2], cropbox[3]))
                transformer.append(Crop(crop_rect))

            if self.web_scale != '100%':
                spec = WHResizeSpec.parse(self.web_scale)
                if spec is None:
                    spec = PercentResizeSpec.parse(self.web_scale)
                if spec is not None:
                    transformer.append(Resize(spec))

            image_io = transformer.transform(self.hires_image, self.web_format)
            if image_io:
                content_type = self._web2ct[self.web_format]
                self._image_factory('image', image_io, content_type)
            else:
                self.image = self.hires_image
        except IOError as error:
            logger.error("Web presentation creation failed for %s with %s" %
                         ('/'.join(self.getPhysicalPath()), str(error)))
            if str(error.args[0]) == "cannot read interlaced PNG files":
                self.image = self.hires_image
                return
            raise ValueError(str(error))
        except ValueError as error:
            logger.error("Web presentation creation failed for %s with %s" %
                         ('/'.join(self.getPhysicalPath()), str(error)))
            self.image = self.hires_image
            return

    def _create_thumbnail(self):
        try:
            transformer = Transformer(ThumbnailResize(self.thumbnail_size))
            thumb = transformer.transform(self.image or self.hires_image,
                                          self.web_format)
            if thumb:
                content_type = self._web2ct[self.web_format]
                self._image_factory('thumbnail_image', thumb, content_type)
        except IOError as error:
            logger.info("Thumbnail creation failed for %s with %s" %
                        ('/'.join(self.getPhysicalPath()), str(error)))
            if str(error.args[0]) == "cannot read interlaced PNG files":
                self.thumbnail_image = None
                return
            else:
                raise ValueError(str(error))
        except ValueError, e:
            logger.info("Thumbnail creation failed for %s with %s" %
                        ('/'.join(self.getPhysicalPath()), str(e)))
            # no thumbnail
            self.thumbnail_image = None
            return
Пример #6
0
class CodeSource(EditableExternalSource, Folder, ZMIObject):
    grok.implements(ICodeSource)
    # register icon and factories
    silvaconf.icon('www/codesource.png')
    silvaconf.factory('manage_addCodeSourceForm')
    silvaconf.factory('manage_addCodeSource')
    silvaconf.zmi_addable(True)

    meta_type = "Silva Code Source"
    security = ClassSecurityInfo()

    _data_encoding = 'UTF-8'
    _fs_location = None
    _script_layers = []

    # ZMI Tabs
    manage_options = (
        {
            'label': 'Edit',
            'action': 'editCodeSource'
        },
        {
            'label': 'Parameters',
            'action': 'parameters/manage_main'
        },
    ) + Folder.manage_options
    management_page_charset = 'utf-8'

    security.declareProtected(SilvaPermissions.ViewManagementScreens,
                              'editCodeSource')
    editCodeSource = PageTemplateFile('www/codeSourceEdit',
                                      globals(),
                                      __name__='editCodeSource')

    def __init__(self, id, script_id=None, fs_location=None):
        super(CodeSource, self).__init__(id)
        self._script_id = script_id
        self._fs_location = fs_location

    security.declareProtected(SilvaPermissions.ViewManagementScreens,
                              'test_source')

    def test_source(self):
        # return a list of problems or None
        errors = []
        # in real life the parent of the form is the document. We try
        # to do the same here.
        root = self.get_root()
        if root.get_default():
            root = root.get_default()
        if self.parameters is not None:
            try:
                self.parameters.test_form(
                    context=root,
                    bad_fields=['context', 'content', 'model', 'script'])
            except ValueError as error:
                errors.extend(error.args)
        if not self.title:
            errors.append(u'Missing required source title.')
        if not self._script_id:
            errors.append(u'Missing required renderer id.')
        else:
            ids = self.objectIds()
            scripts = [self._script_id] + map(itemgetter(0),
                                              self._script_layers)
            for script_id in scripts:
                if script_id not in ids:
                    errors.append(
                        u'Missing renderer %s. Please a script or template with this id.'
                        % (script_id))
        if errors:
            return errors
        return None

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'get_icon')

    def get_icon(self):
        return self._getOb('icon.png', None)

    # ACCESSORS
    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'get_script_id')

    def get_script_id(self):
        return self._script_id

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'get_script_layers')

    def get_script_layers(self):
        result = []
        skin = grok.skin.bind(default=lambda l: l.__identifier__)
        for script_id, layer in self._script_layers:
            result.append(":".join((script_id, skin.get(layer))))
        return '\n'.join(result)

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'get_fs_location')

    def get_fs_location(self):
        return self._fs_location

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'to_html')

    def to_html(self, content, request, **parameters):
        """Render HTML for code source
        """
        script = None
        if self._script_layers:
            # If there are script_layer, check them first.
            for script_id, layer in self._script_layers:
                if layer.providedBy(request):
                    break
            else:
                # No matching layer, default.
                script_id = self._script_id
        else:
            # No script_layer, default one.
            script_id = self._script_id
        if script_id is not None:
            script = self._getOb(script_id, None)
        if script_id is None or script is None:
            # Missing script
            return None
        parameters['REQUEST'] = request
        if IVersion.providedBy(content):
            parameters['version'] = content
            parameters['model'] = content.get_silva_object()
        else:
            parameters['version'] = None
            parameters['model'] = content
        __traceback_supplement__ = (CodeSourceErrorSupplement, self,
                                    parameters)
        result = script(**parameters)
        if isinstance(result, unicode):
            return result
        return unicode(result, self.get_data_encoding(), 'replace')

    # MANAGERS

    security.declareProtected(SilvaPermissions.ViewManagementScreens,
                              'set_script_id')

    def set_script_id(self, script_id):
        self._script_id = script_id

    security.declareProtected(SilvaPermissions.ViewManagementScreens,
                              'set_script_layers')

    def set_script_layers(self, script_layers):
        found = []
        for lineno, line in enumerate(script_layers.strip().splitlines()):
            entries = line.strip().split(':', 1)
            if len(entries) != 2:
                raise ValueError(
                    u'Invalid script layers: invalid form on line %d' %
                    (lineno))
            script_id, layer_identifier = entries
            layer = queryUtility(IBrowserSkinType, name=layer_identifier)
            if layer is None:
                raise ValueError(
                    u'Invalid script layer: layer %s not found on line %d' %
                    (layer_identifier, lineno))
            found.append((script_id, layer))
        self._script_layers = found

    def _get_installable(self, location=None):
        """Return the installable source associated with this code
        source.
        """
        if location is None:
            location = self.get_fs_location()
            if location is None:
                return None
        service = queryUtility(ICodeSourceService)
        if service is None:
            # XXX pre-migration Silva 3.0
            service = self.service_codesources
        candidates = list(service.get_installable_source(location=location))
        if len(candidates) == 1:
            return candidates[0]
        return None

    security.declareProtected(SilvaPermissions.ViewManagementScreens,
                              'manage_getFileSystemLocations')

    def manage_getFileSystemLocations(self):
        service = queryUtility(ICodeSourceService)
        if service is None:
            # XXX pre-migration Silva 3.0
            service = self.service_codesources
        return map(lambda source: source.location,
                   service.get_installable_source(identifier=self.id))

    security.declareProtected(SilvaPermissions.ViewManagementScreens,
                              'manage_updateCodeSource')

    def manage_updateCodeSource(self, purge=False, REQUEST=None):
        """Update a code source from the filesystem.
        """
        installable = self._get_installable()
        if (installable is None or not os.path.isdir(installable._directory)):
            if REQUEST is not None:
                return self.editCodeSource(
                    manage_tabs_message=\
                        'Couldn\'t find the code source on the filesystem.')
            return False
        installable.update(self, bool(purge))
        if REQUEST is not None:
            return self.editCodeSource(
                manage_tabs_message='Source updated from the filesystem.')
        return True

    security.declareProtected(SilvaPermissions.ViewManagementScreens,
                              'manage_exportCodeSource')

    def manage_exportCodeSource(self, aszip=False, dump=False, REQUEST=None):
        """Export a code source to the filesystem.
        """
        if dump:
            installable = self._get_installable()
            if (installable is None
                    or not os.path.isdir(installable._directory)):
                message = "Couldn't find the code source on the filesystem."
            else:
                installable.export(self)
                message = "Source dumped to the filesystem."
            if REQUEST is not None:
                return self.editCodeSource(manage_tabs_message=message)
            return None

        directory = tempfile.mkdtemp('-codesource-export')
        try:
            CodeSourceExportable().export(self, directory)
            result = io.BytesIO()
            archive = zipfile.ZipFile(result, 'w')
            for path, directories, filenames in os.walk(directory):
                root = path[len(directory):]
                if root:
                    root = os.path.join(self.getId(), root)
                else:
                    root = self.getId()
                for filename in filenames:
                    archive.write(os.path.join(path, filename),
                                  os.path.join(root, filename))
            archive.close()
        finally:
            shutil.rmtree(directory)
        if REQUEST is not None:
            REQUEST.RESPONSE.setHeader('Content-Type', 'application/zip')
            REQUEST.RESPONSE.setHeader(
                'Content-Disposition',
                'attachment;filename=%s.zip' % self.getId())
        return result.getvalue()

    security.declareProtected(SilvaPermissions.ViewManagementScreens,
                              'manage_editCodeSource')

    def manage_editCodeSource(self,
                              title,
                              script_id,
                              data_encoding,
                              description=None,
                              location=None,
                              cacheable=None,
                              previewable=None,
                              usable=None,
                              script_layers=None):
        """ Edit a code source settings.
        """
        msg = u''

        if location is not None and location != self._fs_location:
            if location:
                installable = self._get_installable(location)
                if installable is None:
                    msg += "Invalid location for the code source " + \
                        "definition, not changed! "
                    return self.editCodeSource(manage_tabs_message=msg)
            self._fs_location = location
            msg += "Code source location changed. "

        if data_encoding != self._data_encoding:
            try:
                unicode('abcd', data_encoding, 'replace')
            except LookupError:
                # unknown encoding, return error message
                msg += "Unknown encoding %s, not changed! " % data_encoding
                return self.editCodeSource(manage_tabs_message=msg)
            self.set_data_encoding(data_encoding)
            msg += u'Data encoding changed. '

        if script_layers is not None:
            try:
                self.set_script_layers(script_layers)
            except ValueError as error:
                msg += "Error while setting script layers: %s" % error.args[0]
                return self.editCodeSource(manage_tabs_message=msg)

        title = unicode(title, self.management_page_charset)
        if title and title != self.title:
            self.title = title
            msg += "Title changed. "

        if script_id and script_id != self._script_id:
            self._script_id = script_id
            msg += "Script id changed. "

        # Assume description is in the encoding as specified
        # by "management_page_charset". Store it in unicode.
        if description is not None:
            description = unicode(description, self.management_page_charset)
            if description != self._description:
                self.set_description(description)
                msg += "Description changed. "

        if not bool(cacheable) is self.is_cacheable():
            self.set_cacheable(bool(cacheable))
            msg += "Cacheability setting changed. "

        if not bool(usable) is self.is_usable():
            self.set_usable(bool(usable))
            msg += "Usability setting changed. "

        if not bool(previewable) is self.is_previewable():
            self.set_previewable(bool(previewable))
            msg += "Previewable setting changed. "

        return self.editCodeSource(manage_tabs_message=msg)
Пример #7
0
class File(Asset):
    __doc__ = """Any digital file can be uploaded as Silva content.
       For instance large files such as pdf docs or mpegs can be placed in a
       site. File objects have metadata as well."""
    security = ClassSecurityInfo()

    meta_type = "Silva File"

    grok.implements(interfaces.IFile)
    silvaconf.icon('icons/file.png')
    silvaconf.factory('manage_addFile')

    # Default values
    _filename = None
    _content_encoding = None

    # ACCESSORS

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'get_filename')

    def get_filename(self):
        """Object's id is filename if not set.
        """
        if self._filename is not None:
            return self._filename
        return self.id

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'get_file_size')

    def get_file_size(self):
        """Get the size of the file as it will be downloaded.
        """
        return self._file.get_size()

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'get_mime_type')

    def get_mime_type(self):
        """Return the content mimetype.
        """
        # possibly strip out charset encoding
        return self.get_content_type().split(';')[0].strip()

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'fulltext')

    def fulltext(self):
        """Return the content of this object without any markup
        """
        converter = get_converter_for_mimetype(self.get_mime_type())
        fulltext = [self.get_title()]
        if converter is None:
            return fulltext

        text = None
        filename = self.get_file_system_path()
        if filename is not None:
            text = converter.convert_file(filename)
        else:
            file_data = self.get_file()
            if file_data:
                text = converter.convert_string(file_data)
        if text:
            fulltext.append(text)
        return fulltext

    security.declareProtected(SilvaPermissions.View, 'get_download_url')

    def get_download_url(self, preview=False, request=None):
        if request is None:
            request = self.REQUEST
        url = getMultiAdapter((self, request),
                              IContentURL).url(preview=preview)
        if preview:
            # In case of preview we add something that change at the
            # end of the url to prevent caching from the browser.
            url += '?' + str(int(time.time()))
        return url

    security.declareProtected(SilvaPermissions.View, 'tag')

    def tag(self, **kw):
        warnings.warn(
            'tag have been replaced with get_html_tag. '
            'It will be removed, please update your code.',
            DeprecationWarning,
            stacklevel=2)
        return self.get_html_tag(**kw)

    security.declareProtected(SilvaPermissions.View, 'get_html_tag')

    def get_html_tag(self, preview=False, request=None, **extra_attributes):
        """ return xhtml tag

        Since 'class' is a Python reserved word, it cannot be passed in
        directly in keyword arguments which is a problem if you are
        trying to use 'tag()' to include a CSS class. The tag() method
        will accept a 'css_class' argument that will be converted to
        'class' in the output tag to work around this.
        """
        src = self.get_download_url(preview, request)
        title = self.get_title_or_id()

        if 'css_class' in extra_attributes:
            extra_attributes['class'] = extra_attributes['css_class']
            del extra_attributes['css_class']

        extra_html_attributes = [
            '{name}="{value}"'.format(name=escape(name, 1),
                                      value=escape(value, 1))
            for name, value in extra_attributes.items()
        ]

        return '<a href="%s" title="Download %s" %s>%s</a>' % (
            src, self.get_filename(), extra_html_attributes, title)

    # checks where the mime type is text/* or javascript
    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'is_text')

    def is_text(self):
        mimetype = self.get_mime_type()
        if ((mimetype.startswith('text/') and mimetype != 'text/rtf')
                or mimetype in ('application/x-javascript', 'application/xml',
                                'application/xhtml+xml')):
            return self.get_content_encoding() is None
        return False

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'is_text_editable')

    def is_text_editable(self):
        #size is editable if it is less than 150 KB
        return self.is_text() and (not self.get_file_size() > 153600)

    security.declareProtected(SilvaPermissions.View, 'get_text')

    def get_text(self):
        if not self.is_text():
            raise TypeError("Content of Silva File is not text")
        return self.get_file()

    security.declareProtected(SilvaPermissions.View, 'get_file')

    def get_file(self):
        fd = self.get_file_fd()
        data = fd.read()
        fd.close()
        return data

    security.declareProtected(SilvaPermissions.View, 'get_file_fd')

    def get_file_fd(self):
        raise NotImplementedError

    security.declareProtected(SilvaPermissions.View, 'get_content_type')

    def get_content_type(self):
        return self._file.content_type

    security.declareProtected(SilvaPermissions.View, 'get_content_encoding')

    def get_content_encoding(self):
        return self._content_encoding

    # MODIFIERS

    security.declareProtected(SilvaPermissions.ChangeSilvaContent, 'set_file')

    def set_file(self, stream, content_type=None, content_encoding=None):
        """Set data in _file object
        """
        raise NotImplementedError

    security.declareProtected(SilvaPermissions.ChangeSilvaContent,
                              'set_filename')

    def set_filename(self, filename):
        """Set filename
        """
        self._filename = filename

    security.declareProtected(SilvaPermissions.ChangeSilvaContent,
                              'get_file_system_path')

    def get_file_system_path(self):
        """Return path on filesystem for containing File.
        """
        return None

    security.declareProtected(SilvaPermissions.ChangeSilvaContent,
                              'set_content_type')

    def set_content_type(self, content_type):
        self._file.content_type = content_type

    security.declareProtected(SilvaPermissions.ChangeSilvaContent,
                              'set_content_encoding')

    def set_content_encoding(self, content_encoding):
        self._content_encoding = content_encoding

    security.declareProtected(SilvaPermissions.ChangeSilvaContent, 'set_text')

    def set_text(self, text):
        raise NotImplementedError
class SQLSource(EditableExternalSource, Folder, ZMIObject):
    grok.implements(IExternalSource)
    # register icon and factories
    silvaconf.icon('www/sqlsource.png')
    silvaconf.factory('manage_addSQLSourceForm')
    silvaconf.factory('manage_addSQLSource')
    silvaconf.zmi_addable(True)

    meta_type = "Silva SQL Source"
    security = ClassSecurityInfo()

    _sql_method_id = 'sql_method'
    _layout_id = 'layout'
    _default_batch_size = 10
    _v_cached_parameters = None

    # ZMI Tabs
    manage_options = (
        {'label':'Edit', 'action':'editSQLSource'},
        {'label':'Parameters', 'action':'parameters/manage_main'},
        ) + Folder.manage_options
    management_page_charset = 'utf-8'

    security.declareProtected(ViewManagementScreens, 'editSQLSource')
    editSQLSource = PageTemplateFile(
        'www/sqlSourceEdit', globals(),  __name__='sqlCodeSource')

    def __init__(self, id):
        self.id = id
        self._sql_method = None
        self._statement = None
        self._connection_id = None

    # ACCESSORS

    def layout_id(self):
        return self._layout_id

    def connection_id(self):
        return self._connection_id

    def statement(self):
        return self._statement

    def available_connection_ids(self):
        return SQLConnectionIDs(self)

    security.declareProtected(AccessContentsInformation, 'to_html')
    def to_html(self, content, request, **parameters):
        """ render HTML for SQL source
        """
        values = self._get_data(parameters)
        names = values.names()
        batch_size = self._default_batch_size
        if parameters.get('sqlbatchsize'):
            batch_size = int(parameters.get('sqlbatchsize'))
        data = Batch(
            values.dictionaries(),
            factory=self._decode_dict_helper,
            count=batch_size,
            name=self.getId(),
            request=request)
        model = content
        if IVersion.providedBy(content):
            model = content.get_content()
        layout = self._getOb(self._layout_id)
        batch = getMultiAdapter((model, data, request), IBatching)()
        return layout(
            table=data, batch=batch, names=names, parameters=parameters)

    def _get_data(self, args):
        if not self._sql_method:
            self._set_sql_method()
        elif self._v_cached_parameters != self.get_parameters_form().get_field_ids():
            self._set_sql_method()
        args = self._encode_dict_helper(args)
        return self._sql_method(REQUEST=args)

    def _decode_dict_helper(self, dictionary):
        for key, value in dictionary.items():
            if type(value) is type(''):
                dictionary[key] = unicode(
                    value, self._data_encoding, 'replace')
        return dictionary

    def _encode_dict_helper(self, dictionary):
        for key, value in dictionary.items():
            if type(value) is type(u''):
                dictionary[key] =  value.encode(
                    self._data_encoding, 'replace')
        return dictionary

    # MODIFIERS

    def _set_statement(self, statement):
        self._statement = statement
        #invalidate sql method
        self._sql_method = None
        self._p_changed = 1

    def _set_connection_id(self, id):
        self._connection_id = id
        #invalidate sql method
        self._sql_method = None
        self._p_changed = 1

    def _set_sql_method(self):
        self._v_cached_parameters = parameters = self.get_parameters_form().get_field_ids()
        arguments = '\n'.join(parameters)
        self._sql_method = SQL(
            self._sql_method_id, '', self._connection_id,
            arguments.encode('ascii'), self._statement.encode('UTF-8'))
        self._p_changed = 1

    # MANAGERS

    security.declareProtected(ViewManagementScreens, 'manage_editSQLSource')
    def manage_editSQLSource(
        self, title, data_encoding, statement, connection_id=None,
        description=None, cacheable=None, layout_id=None, reset_layout=None,
        reset_params=None, previewable=None, usable=None,
        ):
        """ Edit SQLSource object
        """
        msg = u''

        if reset_layout:
            reset_table_layout(self)
            return self.editSQLSource(
                manage_tabs_message="Table rendering pagetemplate reset " \
                    "to default layout.")

        if reset_params:
            reset_parameter_form(self)
            return self.editSQLSource(
                manage_tabs_message="Parameters form reset to default.")

        if data_encoding and data_encoding != self._data_encoding:
            try:
                unicode('abcd', data_encoding, 'replace')
            except LookupError:
                # unknown encoding, return error message
                msg  += "Unknown encoding %s, not changed!" % data_encoding
                return self.editSQLSource(manage_tabs_message=msg)
            self.set_data_encoding(data_encoding)
            msg += "Data encoding changed. "

        if connection_id and connection_id != self._connection_id:
            self._set_connection_id(connection_id)
            msg += "Connection id changed. "

        if statement:
            statement = unicode(statement, 'UTF-8')
            self._set_statement(statement)
            msg += "SQL statement changed. "

        title = unicode(title, self.management_page_charset)
        if title and title != self.title:
            self.set_title(title)
            msg += "Title changed. "

        description = unicode(description, self.management_page_charset)
        if description != self._description:
            self.set_description(description)
            msg += "Description changed. "

        if not bool(cacheable) is self.is_cacheable():
            self.set_cacheable(bool(cacheable))
            msg += "Cacheability setting changed. "

        if not bool(previewable) is self.is_previewable():
            self.set_previewable(bool(previewable))
            msg += "Previewable setting changed. "

        if not bool(usable) is self.is_usable():
            self.set_usable(bool(usable))
            msg += "Usability setting changed. "

        if layout_id and layout_id != self._layout_id:
            self._layout_id = layout_id
            msg += "Layout object id changed. "

        return self.editSQLSource(manage_tabs_message=msg)
Пример #9
0
class MyFolder(Folder):

    meta_type = 'My Folder'
    silvaconf.factory('manage_addMyFolder')