Beispiel #1
0
def validate_og_fallback_image(value):
    """Check if fallback image follows best practices on MIME type,
    size, dimensions and aspect ratio.
    """
    if value is None:
        return True

    filename, data = b64decode_file(value)
    image = NamedBlobImage(data=data, filename=filename)

    if image.contentType not in OG_LEAD_IMAGE_MIME_TYPES:
        raise Invalid(MSG_INVALID_OG_LEAD_IMAGE_MIME_TYPE)

    if image.getSize() > OG_LEAD_IMAGE_MAX_SIZE:
        raise Invalid(MSG_INVALID_OG_LEAD_IMAGE_SIZE)

    width, height = image.getImageSize()
    if width < OG_LEAD_IMAGE_MIN_WIDTH or height < OG_LEAD_IMAGE_MIN_HEIGHT:
        raise Invalid(MSG_INVALID_OG_LEAD_IMAGE_DIMENSIONS)

    aspect_ratio = width / height
    if aspect_ratio < OG_LEAD_IMAGE_MIN_ASPECT_RATIO:
        raise Invalid(MSG_INVALID_OG_LEAD_IMAGE_ASPECT_RATIO)

    return True
 def testPublishUpdatesLogo(self):
     # Test for http://code.simplon.biz/tracker/tno-euphorie/ticket/136
     white_gif = (
         b"GIF89a\x01\x00\x01\x00\x80\x00\x00\xff\xff\xff\xff\xff\xff,"
         b"\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;"
     )
     black_gif = (
         b"GIF89a\x01\x00\x01\x00\x80\x01\x00\x00\x00\x00\xff\xff\xff,"
         b"\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;"
     )
     self.createSurvey()
     self.sector.logo = NamedBlobImage(
         data=white_gif, contentType="image/gif", filename="white.gif"
     )
     view = self.survey.restrictedTraverse("@@publish")
     view.publish()
     client_sector = self.client.nl["dining"]
     self.assertEqual(client_sector.logo.data, white_gif)
     images = client_sector.restrictedTraverse("@@images")
     white_scale = images.scale("logo", height=100, direction="up").data.data
     self.sector.logo = NamedBlobImage(
         data=black_gif, contentType="image/gif", filename="black.gif"
     )
     view.publish()
     self.assertEqual(client_sector.logo.data, black_gif)
     images = client_sector.restrictedTraverse("@@images")
     black_scale = images.scale("logo", height=100, direction="up").data.data
     self.assertNotEqual(white_scale, black_scale)
 def testImage(self):
     self.folder.invokeFactory('Image', id='image')
     portal_repository = self.portal_repository
     img1 = open(os.path.join(PACKAGE_HOME, 'tests/images/img1.png'),
                 'rb').read()
     img2 = open(os.path.join(PACKAGE_HOME, 'tests/images/img2.png'),
                 'rb').read()
     content = self.folder.image
     content.image = NamedBlobImage(img1, u'img1.png', u'image/png')
     content.title = u'content'
     content.subject = [u'content']
     content.description = u'content'
     content.contributors = [u'content']
     content.language = 'content'
     content.rights = u'content'
     portal_repository.applyVersionControl(content, comment='save no 1')
     content.image = NamedBlobImage(img2, u'img2.png', u'image/png')
     content.title = u'contentOK'
     content.subject = [u'contentOK']
     content.description = u'contentOK'
     content.contributors = [u'contentOK']
     content.language = 'contentOK'
     content.rights = u'contentOK'
     portal_repository.save(content, comment='save no 2')
     obj = portal_repository.retrieve(content, 0).object
     self.assertEqual(obj.image.data, img1)
     self.metadata_test_one(obj)
     obj = portal_repository.retrieve(content, 1).object
     self.assertEqual(obj.image.data, img2)
     self.metadata_test_two(obj)
     portal_repository.revert(content, 0)
     self.assertEqual(content.image.data, img1)
     self.metadata_test_one(content)
Beispiel #4
0
def validate_og_fallback_image(value):
    """Check if fallback image follows best practices on MIME type,
    size, dimensions and aspect ratio.
    """
    if value is None:
        return True

    filename, data = b64decode_file(value)
    image = NamedBlobImage(data=data, filename=filename)

    if image.contentType not in OG_LEAD_IMAGE_MIME_TYPES:
        raise Invalid(MSG_INVALID_OG_LEAD_IMAGE_MIME_TYPE)

    if image.getSize() > OG_LEAD_IMAGE_MAX_SIZE:
        raise Invalid(MSG_INVALID_OG_LEAD_IMAGE_SIZE)

    width, height = image.getImageSize()
    if width < OG_LEAD_IMAGE_MIN_WIDTH or height < OG_LEAD_IMAGE_MIN_HEIGHT:
        raise Invalid(MSG_INVALID_OG_LEAD_IMAGE_DIMENSIONS)

    aspect_ratio = width / height
    if aspect_ratio < OG_LEAD_IMAGE_MIN_ASPECT_RATIO:
        raise Invalid(MSG_INVALID_OG_LEAD_IMAGE_ASPECT_RATIO)

    return True
Beispiel #5
0
    def setUp(self):
        self.app = self.layer["app"]
        self.portal = self.layer["portal"]
        self.portal_url = self.portal.absolute_url()
        setRoles(self.portal, TEST_USER_ID, ["Manager"])

        self.api_session = RelativeSession(self.portal_url)
        self.api_session.headers.update({"Accept": "application/json"})
        self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD)

        image_file = os.path.join(os.path.dirname(__file__), u"image.png")
        with open(image_file, "rb") as f:
            image_data = f.read()

        self.folder = api.content.create(container=self.portal,
                                         type="Folder",
                                         title="Normal folder")
        self.subsite = api.content.create(
            container=self.portal,
            type="Subsite",
            title="Subsite",
            subsite_header=RichTextValue(
                raw="<p>header</p>",
                mimeType="text/html",
                outputMimeType="text/html",
                encoding="utf-8",
            ),
            subsite_footer=RichTextValue(
                raw="<p>footer</p>",
                mimeType="text/html",
                outputMimeType="text/html",
                encoding="utf-8",
            ),
            subsite_css_class="red",
            image=NamedBlobImage(data=image_data,
                                 contentType="image/png",
                                 filename=u"image.png"),
            subsite_logo=NamedBlobImage(data=image_data,
                                        contentType="image/png",
                                        filename=u"image.png"),
        )
        self.document_in_subsite = api.content.create(
            container=self.subsite,
            type="Document",
            title="Document in subsite",
        )
        self.document_outside_subsite = api.content.create(
            container=self.folder,
            type="Document",
            title="Document outside subsite",
        )

        commit()
Beispiel #6
0
    def create_object(self, folder, type_, info):
        filename = info['name']
        name = filename.decode("utf8")
        chooser = INameChooser(folder)
        chooser_name = name.lower().replace('aq_', '')
        newid = chooser.chooseName(chooser_name, folder.aq_parent)

        # strip metadata from file
        if (type_ in ('Image', 'File', 'Video', 'Audio')
                and exiftool is not None and 'tmp_file' in info):
            try:
                exiftool(info['tmp_file'])
            except Exception:
                logger.warn('Could not strip metadata from file: %s' %
                            info['tmp_file'])

        fi = open(info['tmp_file'], 'r')
        try:
            # Try to determine which kind of NamedBlob we need
            # This will suffice for standard p.a.contenttypes File/Image
            # and any other custom type that would have 'File' or 'Image' in
            # its type name
            filename = ploneutils.safe_unicode(filename)
            create_opts = dict(type=type_, id=newid, container=folder)
            if 'Image' in type_:
                image = NamedBlobImage(data=fi, filename=filename)
                try:
                    image.focal_point = [
                        float(self.request.form.get('focalX')),
                        float(self.request.form.get('focalY'))
                    ]
                except Exception:
                    pass
                create_opts['image'] = image
            else:
                create_opts['file'] = NamedBlobFile(data=fi, filename=filename)

            for field in get_upload_fields():
                if not field.get('name'):
                    continue
                name = field['name']
                if not self.request.form.get(name):
                    continue
                if name in ('tags', 'subject'):
                    # tags needs to be converted
                    create_opts['subject'] = self.request.form.get(name).split(
                        ';')
                else:
                    create_opts[name] = self.request.form.get(name, '')
            return api.content.create(**create_opts)
        finally:
            fi.close()
Beispiel #7
0
    def testCopyBlobs(self):
        from zope.copy import copy
        file = NamedBlobFile()
        file.data = u'hello, world'
        image = NamedBlobImage()
        image.data = 'some image bytes'
        transaction.commit()

        file_copy = copy(file)
        self.assertEqual(file_copy.data, file.data)

        image_copy = copy(image)
        self.assertEqual(image_copy.data, image.data)
Beispiel #8
0
    def testCopyBlobs(self):
        from zope.copy import copy
        file = NamedBlobFile()
        file.data = u'hello, world'
        image = NamedBlobImage()
        image.data = 'some image bytes'
        transaction.commit()

        file_copy = copy(file)
        self.assertEqual(file_copy.data, file.data)

        image_copy = copy(image)
        self.assertEqual(image_copy.data, image.data)
 def test_opened_file_storable(self):
     data = getFile('image.gif')
     f = tempfile.NamedTemporaryFile(delete=False)
     try:
         path = f.name
         f.write(data)
         f.close()
         with open(path, 'rb') as f:
             fi = NamedBlobImage(f, filename=u'image.gif')
     finally:
         if os.path.exists(path):
             os.remove(path)
     self.assertEqual(303, fi.getSize())
def update_featuredimage(context, event):
    """Update Fetured Image after save content"""
    if not context.featuredimage_enabled:
        return
    page = u'{0}/@@featuredimage'.format(context.absolute_url())
    # integration tests don't work with phantomjs
    if page.startswith('http://nohost/'):
        return
    # without this phantomjs look the old page
    transaction.commit()
    # get screenshot
    data = _get_screenshot(page)
    # save image
    image = NamedBlobImage()
    image._setData(data)
    context.featured_image = image
    def test_namedblobimage_field_serialization_doesnt_choke_on_corrupt_image(
            self):
        """ Original image url will be None because the original image is corrupted
            and the created url should be an image scale """
        image_data = b"INVALID IMAGE DATA"
        fn = "test_namedblobimage_field"
        with patch.object(storage, "uuid4", return_value="uuid_1"):
            value = self.serialize(
                fn,
                NamedBlobImage(data=image_data,
                               contentType=u"image/gif",
                               filename=u"1024x768.gif"),
            )

        self.assertEqual(
            {
                u"content-type": u"image/gif",
                u"download": None,
                u"filename": u"1024x768.gif",
                u"height": -1,
                u"scales": {},
                u"size": 18,
                u"width": -1,
            },
            value,
        )
Beispiel #12
0
 def update_file_content(self, info):
     type_, location = self.get_type_and_location(info)
     obj = uuidToObject(info['existing_id'])
     success = False
     msg = None
     if obj:
         if self.sm.checkPermission(ModifyPortalContent, obj):
             try:
                 if info['field_name'].startswith('tmp_'):
                     self.add_tmp_upload(obj, info)
                 else:
                     fi = open(info['tmp_file'], 'r')
                     filename = ploneutils.safe_unicode(info['name'])
                     if 'Image' in type_:
                         blob = NamedBlobImage(data=fi, filename=filename)
                     else:
                         blob = NamedBlobFile(data=fi, filename=filename)
                     setattr(obj, info['field_name'], blob)
                 success = True
             except Exception:
                 # could not update content
                 logger.warning('Error updating content', exc_info=True)
                 msg = 'Unknown error'
         else:
             msg = 'Invalid permissions'
     else:
         success = False
         msg = 'Object not found'
     return obj, success, msg
Beispiel #13
0
 def migrate_schema_fields(self):
     old_image = self.old.getField('image').get(self.old)
     if old_image == '':
         return
     filename = safe_unicode(old_image.filename)
     namedblobimage = NamedBlobImage(data=old_image.data, filename=filename)
     self.new.image = namedblobimage
Beispiel #14
0
def migrate_imagefield(src_obj, dst_obj, src_fieldname, dst_fieldname):
    """
    migrate an image field.
    This field needs to be migrated with an NamedBlobImage instance.
    """
    # get old image data and filename
    old_image = src_obj.getField(src_fieldname).get(src_obj)
    if old_image == '':
        return
    filename = safe_unicode(old_image.filename)
    old_image_data = old_image.data
    if safe_hasattr(old_image_data, 'data'):
        old_image_data = old_image_data.data

    # create the new image field
    namedblobimage = NamedBlobImage(data=old_image_data, filename=filename)

    # set new field on destination object
    setattr(dst_obj, dst_fieldname, namedblobimage)

    # handle a possible image caption field
    # postulate is the old caption field name is ending by 'Caption'
    # and the new field name is ending by '_caption'
    # is this postulate correct ?
    # should this field not be handle by itself because it will appear in the
    # old field list ?
    caption_field = src_obj.getField('%sCaption' % src_fieldname, None)
    if caption_field:
        setattr(dst_obj, ('%s_caption' % dst_fieldname),
                safe_unicode(caption_field.get(src_obj)))

    logger.info("Migrating image %s" % filename)
Beispiel #15
0
def updateOGG(context, normalizedTitle, pt):
    """
    :param context: an object with a ``ogg`` field
    :type context: usualy a ABC object
    :param normalizedTitle: used for the blob filename
    :type normalizedTitle: string
    :param pt: tool
    :type pt: portal_tranform tool
    :returns: nothing, update the ``ogg`` field of the object
    """
    try:
        oggData = pt.convertTo(
            'audio/ogg',
            context.abc,
            context=context,
            annotate=True,
            )
        oggFilename = normalizedTitle + u'.ogg'
        oggContenType = 'audio/ogg'
        context.ogg = NamedBlobImage()
        context.ogg.data = oggData.getData()
        context.ogg.filename = oggFilename
        context.ogg.contentType = oggContenType
    except Exception:
        msg = u'Failed to create OGG sound'
        logger.info(msg)
        annotateObject(context, msg=msg, key='ABC_ERRORS')
Beispiel #16
0
def dummy_file():
    from plone.namedfile.file import NamedBlobImage
    path = os.path.join(os.path.dirname(__file__), FILENAME)
    return NamedBlobImage(
        data=open(path, 'r').read(),
        filename=FILENAME
    )
Beispiel #17
0
def dummy_image():
    from plone.namedfile.file import NamedBlobImage
    filename = os.path.join(os.path.dirname(__file__), u'image.jpg')
    return NamedBlobImage(
        data=open(filename, 'r').read(),
        filename=filename
    )
Beispiel #18
0
    def test_get_news_item(self):
        self.portal.invokeFactory('News Item', id='news1', title='News Item 1')
        image_file = os.path.join(os.path.dirname(__file__), u'image.png')
        self.portal.news1.image = NamedBlobImage(data=open(image_file,
                                                           'r').read(),
                                                 contentType='image/png',
                                                 filename=u'image.png')
        self.portal.news1.image_caption = u'This is an image caption.'
        transaction.commit()

        with patch.object(storage, 'uuid4', return_value='uuid1'):
            response = self.api_session.get(self.portal.news1.absolute_url())

            self.assertEqual(response.status_code, 200)
            self.assertEqual(
                response.headers.get('Content-Type'),
                'application/json',
                'When sending a GET request with Content-Type: application/json '
                +  # noqa
                'the server should respond with sending back application/json.'
            )
            self.assertEqual(
                'News Item',
                response.json().get('@type'),
                "Response should be @type 'News Item', not '{}'".format(
                    response.json().get('@type')))
            self.assertEqual(response.json().get('@id'),
                             self.portal.news1.absolute_url())
            self.assertEqual('News Item 1', response.json().get('title'))
            self.assertEqual(u'This is an image caption.',
                             response.json()['image_caption'])
            self.assertDictContainsSubset(
                {'download': self.portal_url + u'/news1/@@images/uuid1.png'
                 },  # noqa
                response.json()['image'])
Beispiel #19
0
    def create_entry(self, folder, dictNews):
        ''' Cria news item, realiza transição '''
        oId = str(dictNews.get('id'))
        if not oId in folder.objectIds():
            api.content.create(folder,
                               'News Item',
                               oId,
                               title=dictNews.get('title'),
                               description=dictNews.get('description'))
        else:
            return folder[oId]
        log.info('     - Cria item %s' % (oId))
        o = folder[oId]
        if not o:
            return
        for k, v in dictNews.items():
            if k in ['title', 'id', 'anexos']:
                continue
            if k in ['text']:
                v = RichTextValue(v, 'text/html', 'text/html')
                o.text = v
            if k in ['image']:
                data = v[0]
                content_type = v[1]
                filename = u'image.%s' % (content_type.split('/')[1])
                v = NamedBlobImage(data, content_type, filename)
                o.image = v
            if v and hasattr(o, k):
                setattr(o, k, v)
        o.exclude_from_nav = True

        api.content.transition(o, 'publish')
        o.reindexObject()
        return o
Beispiel #20
0
    def test_get_content_related_items_without_workflow(self):
        intids = getUtility(IIntIds)

        self.portal.invokeFactory("Image", id="imagewf")
        self.portal.imagewf.title = "Image without workflow"
        self.portal.imagewf.description = "This is an image"
        image_file = os.path.join(os.path.dirname(__file__), "image.png")
        with open(image_file, "rb") as f:
            image_data = f.read()
        self.portal.imagewf.image = NamedBlobImage(data=image_data,
                                                   contentType="image/png",
                                                   filename="image.png")
        transaction.commit()

        self.portal.folder1.doc1.relatedItems = [
            RelationValue(intids.getId(self.portal.imagewf))
        ]
        transaction.commit()
        response = requests.get(
            self.portal.folder1.doc1.absolute_url(),
            headers={"Accept": "application/json"},
            auth=(SITE_OWNER_NAME, SITE_OWNER_PASSWORD),
        )
        self.assertEqual(response.status_code, 200)
        self.assertEqual(1, len(response.json()["relatedItems"]))
        self.assertEqual(
            [{
                "@id": self.portal_url + "/imagewf",
                "@type": "Image",
                "description": "This is an image",
                "review_state": None,
                "title": "Image without workflow",
            }],
            response.json()["relatedItems"],
        )
Beispiel #21
0
    def _create_file(self, item, files, title, description, rights):
        namechooser = INameChooser(self.context)
        content_type = item.headers.get('Content-Type')
        filename = safe_unicode(item.filename)
        data = item.read()
        id_name = ''
        title = title and title[0] or filename
        id_name = namechooser.chooseName(title, self.context)

        if content_type in IMAGE_MIMETYPES:
            portal_type = 'Image'
            wrapped_data = NamedBlobImage(data=data, filename=filename)
        else:
            portal_type = 'File'
            wrapped_data = NamedBlobFile(data=data, filename=filename)

        self.context.invokeFactory(portal_type,
                                   id=id_name,
                                   title=title,
                                   description=description[0],
                                   rights=rights[0])
        newfile = self.context[id_name]
        if portal_type == 'File':
            if IATFile.providedBy(newfile):
                newfile.setFile(data, filename=filename)
            else:
                newfile.file = wrapped_data
        elif portal_type == 'Image':
            if IATImage.providedBy(newfile):
                newfile.setImage(data, filename=filename)
            else:
                newfile.image = wrapped_data
        newfile.reindexObject()
        notify(ObjectModifiedEvent(newfile))
        return newfile
def migrate_blobimagefield(src_obj, dst_obj, src_fieldname, dst_fieldname):
    """
    migrate an image field.
    Actually this field needs only to copy the existing NamedBlobImage instance
    to the new dst_obj, but we do some more in detail and create new fields.
    """
    old_image = getattr(src_obj, src_fieldname)
    if old_image == '':
        return
    filename = safe_unicode(old_image.filename)
    old_image_data = old_image.data
    if safe_hasattr(old_image_data, 'data'):
        old_image_data = old_image_data.data
    namedblobimage = NamedBlobImage(data=old_image_data, filename=filename)

    # set new field on destination object
    setattr(dst_obj, dst_fieldname, namedblobimage)

    # handle a possible image caption field
    field = '{0}_caption'.format(src_fieldname)
    old_image_caption = getattr(src_obj, field, None)
    if old_image_caption:
        setattr(dst_obj, ('{0}_caption'.format(dst_fieldname)),
                safe_unicode(old_image_caption))

    logger.info(u'Migrating image {0}'.format(filename))
Beispiel #23
0
    def test_dexterity_news_item_get(self):
        self.portal.invokeFactory("News Item", id="newsitem")
        self.portal.newsitem.title = "My News Item"
        self.portal.newsitem.description = u"This is a news item"
        self.portal.newsitem.text = RichTextValue(
            u"Lorem ipsum", "text/plain", "text/html"
        )
        image_file = os.path.join(os.path.dirname(__file__), u"image.png")
        fd = open(image_file, "rb")
        self.portal.newsitem.image = NamedBlobImage(
            data=fd.read(), contentType="image/png", filename=u"image.png"
        )
        fd.close()
        self.portal.newsitem.image_caption = u"This is an image caption."
        import transaction

        transaction.commit()
        response = requests.get(
            self.portal.newsitem.absolute_url(),
            headers={"Accept": "application/json"},
            auth=(SITE_OWNER_NAME, SITE_OWNER_PASSWORD),
        )

        self.assertEqual(200, response.status_code)
        self.assertEqual(u"newsitem", response.json().get("id"))
        self.assertEqual(u"GET", response.json().get("method"))
    def test_namedblobimage_field_serialization_doesnt_choke_on_corrupt_image(
            self):
        """ In Plone >= 5.2 the original image file is not a "scale", so its url
            is returned as is and we need to check it, but the scales should be empty"""
        image_data = b"INVALID IMAGE DATA"
        fn = "test_namedblobimage_field"
        with patch.object(storage, "uuid4", return_value="uuid_1"):
            value = self.serialize(
                fn,
                NamedBlobImage(data=image_data,
                               contentType=u"image/gif",
                               filename=u"1024x768.gif"),
            )

        obj_url = self.doc1.absolute_url()
        scale_url_uuid = "uuid_1"
        self.assertEqual(
            {
                u"content-type":
                u"image/gif",
                u"download":
                u"{}/@@images/{}.{}".format(obj_url, scale_url_uuid, "gif"),
                u"filename":
                u"1024x768.gif",
                u"height":
                -1,
                u"scales": {},
                u"size":
                18,
                u"width":
                -1,
            },
            value,
        )
Beispiel #25
0
def prefill_image_types_dexterity(kwargs):
    import random
    import string
    image = random_image()
    filename = u'{}.png'.format(''.join(
        random.choice(string.ascii_lowercase) for _ in range(6)))
    kwargs['image'] = NamedBlobImage(data=image, filename=filename)
Beispiel #26
0
    def test_namedblobimage_field_serialization_returns_dict(self):
        image_file = os.path.join(os.path.dirname(__file__), u'1024x768.gif')
        with open(image_file, 'rb') as f:
            image_data = f.read()
        fn = 'test_namedblobimage_field'
        with patch.object(storage, 'uuid4', return_value='uuid_1'):
            value = self.serialize(
                fn,
                NamedBlobImage(
                    data=image_data,
                    contentType=u'image/gif',
                    filename=u'1024x768.gif'
                )
            )
            self.assertTrue(isinstance(value, dict), 'Not a <dict>')

            scale_url_uuid = 'uuid_1'
            obj_url = self.doc1.absolute_url()
            download_url = u'{}/@@images/{}.{}'.format(
                obj_url, scale_url_uuid, GIF_SCALE_FORMAT
            )
            scales = {
                u'listing': {
                    u'download': download_url,
                    u'width': 16,
                    u'height': 12},
                u'icon': {
                    u'download': download_url,
                    u'width': 32,
                    u'height': 24},
                u'tile': {
                    u'download': download_url,
                    u'width': 64,
                    u'height': 48},
                u'thumb': {
                    u'download': download_url,
                    u'width': 128,
                    u'height': 96},
                u'mini': {
                    u'download': download_url,
                    u'width': 200,
                    u'height': 150},
                u'preview': {
                    u'download': download_url,
                    u'width': 400,
                    u'height': 300},
                u'large': {
                    u'download': download_url,
                    u'width': 768,
                    u'height': 576},
            }
            self.assertEqual({
                u'filename': u'1024x768.gif',
                u'content-type': u'image/gif',
                u'size': 1514,
                u'download': download_url,
                u'width': 1024,
                u'height': 768,
                u'scales': scales},
                value)
Beispiel #27
0
    def populate_with_object(self, obj):
        # check permissions
        super(ImageTile, self).populate_with_object(obj)

        data_mgr = ITileDataManager(self)

        data_mgr.set({'image': NamedBlobImage(obj.getImage().data)})
Beispiel #28
0
    def handle_storage(self):
        gsettings = self.gsettings
        storage_dir = self.storage_dir
        settings = self.settings
        context = self.context

        # save lead image if available
        if ILeadImage.providedBy(self.context):
            path = os.path.join(storage_dir, 'large')
            filename = None
            for dump_filename in os.listdir(path):
                if dump_filename.startswith('dump_1.'):
                    filename = dump_filename
                    break
            filepath = os.path.join(path, filename)
            tmppath = '%s.tmp' % (filepath)

            # NamedBlobImage eventually calls blob.consume,
            # destroying the image, so we need to make a temporary copy.
            shutil.copyfile(filepath, tmppath)
            fi = open(tmppath)
            self.context.image = NamedBlobImage(
                fi, filename=filename.decode('utf8'))
            fi.close()

        if self.gsettings.storage_type == 'Blob':
            logger.info('setting blob data for %s' % repr(context))
            # go through temp folder and move items into blob storage
            files = OOBTree()
            for size in ('large', 'normal', 'small'):
                path = os.path.join(storage_dir, size)
                for filename in os.listdir(path):
                    filepath = os.path.join(path, filename)
                    filename = '%s/%s' % (size, filename)
                    files[filename] = saveFileToBlob(filepath)

            if self.settings.enable_indexation:
                textfilespath = os.path.join(storage_dir, TEXT_REL_PATHNAME)
                for filename in os.listdir(textfilespath):
                    filepath = os.path.join(textfilespath, filename)
                    filename = '%s/%s' % (TEXT_REL_PATHNAME, filename)
                    files[filename] = saveFileToBlob(filepath)

            # Store converted PDF
            dump_pdf_path = os.path.join(storage_dir, DUMP_FILENAME)
            filename = 'pdf/%s' % DUMP_FILENAME
            files[filename] = saveFileToBlob(dump_pdf_path)

            settings.blob_files = files
            shutil.rmtree(storage_dir)

            # check for old storage to remove... Just in case.
            old_storage_dir = os.path.join(gsettings.storage_location,
                                           context.UID())
            if os.path.exists(old_storage_dir):
                shutil.rmtree(old_storage_dir)
        else:
            # if settings used to be blob, delete file data
            if settings.storage_type == 'Blob' and settings.blob_files:
                del settings._metadata['blob_files']
Beispiel #29
0
def updateSVG(context, normalizedTitle, pt):
    """
    :param context: an object with ``abc`` and ``svgscore`` fields
    :type context: usualy a ABC object
    :param normalizedTitle: used for the blob filename
    :type normalizedTitle: string
    :param pt: tool
    :type pt: portal_tranform tool
    :returns: nothing, update the ``svgscore`` field of the object
    """
    try:
        svgData = pt.convertTo(
            'image/svg+xml',
            context.abc,
            context=context,
            annotate=True
            )
        svgFilename = normalizedTitle + u'.svg'
        svgContenType = 'image/svg+xml'
        context.svgscore = NamedBlobImage()
        context.svgscore.data = svgData.getData()
        context.svgscore.filename = svgFilename
        context.svgscore.contentType = svgContenType
    except Exception:
        msg = u'Failed to create SVG score'
        logger.info(msg)
        annotateObject(context, msg=msg, key='ABC_ERRORS')
Beispiel #30
0
    def get_image(self, item):

        image_url = None

        if 'has_lead_image' in item:
            if item['has_lead_image']:
                image_url = 'https://%s%s/@@images/image' % (AGSCI_DOMAIN,
                                                             item.get('path'))
        else:
            links = item.get('links', [])
            image_links = [
                x.get('href', '') for x in links
                if x.get('rel', None) in ('enclosure', )
            ]

            if image_links:
                image_url = image_links[0]

        if image_url:
            image_data = self.download_image(image_url)

            filename = image_url.split('/')[-1].split('?')[0]

            if filename:
                filename = safe_unicode(filename)
            else:
                filename = u'image'

            if image_data:
                return NamedBlobImage(filename=filename, data=image_data)
Beispiel #31
0
def updatePDF(context, normalizedTitle, pt):
    """
    :param context: an object with a ``pdfscore`` field
    :type context: usualy a ABC object
    :param normalizedTitle: used for the blob filename
    :type normalizedTitle: string
    :param pt: tool
    :type pt: portal_tranform tool
    :returns: nothing, update the ``pdfscore`` field of the object
    """
    try:
        pdfData = pt.convertTo(
            'application/pdf',
            context.abc,
            context=context,
            annotate=True,
            )
        pdfFilename = normalizedTitle + u'.pdf'
        pdfContenType = 'application/pdf'
        context.pdfscore = NamedBlobImage()
        context.pdfscore.data = pdfData.getData()
        context.pdfscore.filename = pdfFilename
        context.pdfscore.contentType = pdfContenType
    except Exception:
        msg = u'Failed to create PDF score'
        logger.info(msg)
        annotateObject(context, msg=msg, key='ABC_ERRORS')
Beispiel #32
0
    def test_lead_image(self):
        from plone.namedfile.file import NamedBlobImage
        filename = u'logo-plone-ok.png'
        self.newsitem.image = NamedBlobImage(data=get_file(filename),
                                             filename=filename)
        self.newsitem.image_caption = u'Mais amor, por favor!'
        amp = etree.HTML(self.view())
        lead_image = amp.find('.//figure/amp-img')
        self.assertIsNotNone(lead_image)
        self.assertTrue(lead_image.attrib['src'].endswith(filename))
        self.assertEqual(lead_image.attrib['layout'], 'responsive')
        self.assertEqual(lead_image.attrib['width'], '231')
        self.assertEqual(lead_image.attrib['height'], '60')
        self.assertEqual(
            amp.find('.//figure/figcaption').text, 'Mais amor, por favor!')

        # lead image information in metadata
        metadata = self._get_metadata_as_json(amp)
        self.assertIn('image', metadata)
        metadata = metadata['image']  # shortcut
        self.assertEqual(metadata['@type'], u'ImageObject')
        url = u'lorem-ipsum/@@download/image/{0}'.format(filename)
        self.assertTrue(metadata['url'].endswith(url))
        self.assertEqual(metadata['width'], 231)
        self.assertEqual(metadata['height'], 60)
Beispiel #33
0
    def test_basic_tile_purge_cache(self):
        provideHandler(queuePurge)

        request = self.request
        alsoProvides(request, IAttributeAnnotatable)
        setRequest(request)

        registry = queryUtility(IRegistry)
        registry.registerInterface(ICachePurgingSettings)
        provideUtility(registry, IRegistry)

        settings = registry.forInterface(ICachePurgingSettings)
        settings.enabled = True
        settings.cachingProxies = ('http://*****:*****@@collective.cover.basic/test',
                '/c1/@@collective.cover.basic/test/@@images/image',
                '/c1/@@collective.cover.basic/test/@@images/icon',
                '/c1/@@collective.cover.basic/test/@@images/mini',
                '/c1/@@collective.cover.basic/test/@@images/large',
                '/c1/@@collective.cover.basic/test/@@images/listing',
                '/c1/@@collective.cover.basic/test/@@images/thumb',
                '/c1/@@collective.cover.basic/test/@@images/preview',
                '/c1/@@collective.cover.basic/test/@@images/tile']),
            IAnnotations(request)['plone.cachepurging.urls'])
Beispiel #34
0
    def ImportImage(self, node):
        """
        Import a base64 encoded image from an XML node.

        :param node: lxml.objectified XML node of image element
        :rtype: (:py:class:`NamedImage`, unicode) tuple
        """
        filename = attr_unicode(node, "filename")
        contentType = node.get("content-type", None)
        if not filename:
            basename = u"image%d.%%s" % random.randint(1, 2 ** 16)
            if contentType and "/" in contentType:
                filename = basename % contentType.split(u"/")[1]
            else:
                filename = basename % u"jpg"
        image = NamedBlobImage(data=node.text.decode("base64"), contentType=contentType, filename=filename)
        if image.contentType is None and image.filename:
            image.contentType = mimetypes.guess_type(image.filename)[0]
        return (image, attr_unicode(node, "caption"))
Beispiel #35
0
def create_lead_image(size=(800, 450), color="blue"):
    """
    Creates an memory object containing an image.
    Expects a size tuple and PIL color.

    :param size: tuple of ints (width, height) default (800, 450)
    :param color: String or PIL color (r,g,b) tuple.
    :return: NamedBlobImage
    """
    # Create an image.
    im = Image.new("RGB", size, color=color)

    # Draw some lines
    draw = ImageDraw.Draw(im)
    color = ImageColor.getrgb(color)
    for i in range(9):
        factor = choice(range(8, 18, 1)) / 10.0
        stroke_color = (
            int(min(color[0] * factor, 255)),
            int(min(color[1] * factor, 255)),
            int(min(color[2] * factor, 255)),
        )
        draw.line(
            [
                (choice(range(0, size[0])), choice(range(0, size[1]))),
                (choice(range(0, size[0])), choice(range(0, size[1])))
            ],
            fill=stroke_color,
            width=int(size[1] / 5)
        )

    # 'Save' the file.
    sio = cStringIO.StringIO()
    im.save(sio, format="PNG")
    sio.seek(0)

    # Create named blob image
    nbi = NamedBlobImage()
    nbi.data = sio.read()
    nbi.filename = u"example.png"

    return nbi
Beispiel #36
0
 def test_filechunk_storable(self):
     fi = NamedBlobImage(FileChunk(getFile('image.gif').read()),
                         filename=u'image.gif')
     self.assertEqual(303, fi.getSize())
Beispiel #37
0
    def handleApply(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        utils._send_emails = False
        try:

            en_folder = self.context.restrictedTraverse('en')
            if 'organisations' in en_folder:
                org_folder = en_folder.restrictedTraverse('organisations')
            else:
                org_folder = content.create(en_folder,
                                            type='osha.hwccontent.organisationfolder',
                                            title='Organisations')
            if 'focalpoints' in en_folder:
                fop_folder = en_folder.restrictedTraverse('focalpoints')
            else:
                fop_folder = content.create(en_folder,
                                            type='osha.hwccontent.organisationfolder',
                                            title='Focalpoints')

            type_mapping = {
                u'Organisation': {
                    'type': 'osha.hwccontent.organisation',
                    'schema': dict(getFieldsInOrder(IOrganisation)),
                    'folder': org_folder,
                    'wf_actions': ('approve_phase_1',),
                },

                u'Focalpoint': {
                    'type': 'osha.hwccontent.focalpoint',
                    'schema': dict(getFieldsInOrder(IFocalPoint)),
                    'folder': fop_folder,
                    'wf_actions': ('publish',),
                }
            }

            count = 0
            for data in json.loads(data['json']):

                # Only keep the data that's in the main schema:
                type_info = type_mapping[data['_type']]
                schema = type_info['schema']
                fields = {}

                if data['title'].startswith('MC-'):
                    continue

                for name, field in schema.items():
                    if name in data:
                        value = data[name]
                        if value and INamedImageField.providedBy(field):
                            content_type = data.get('_%s_content_type' % name, '')
                            filename = data.get('_%s_filename' % name , None)
                            value = NamedBlobImage(base64.b64decode(value), str(content_type), filename)
                        elif value and IRichText.providedBy(field):
                            content_type = data.get('_%s_content_type', None)
                            value = RichTextValue(value, mimeType=content_type)
                        elif name.find("email") >= 0:
                            value = value.strip()

                        fields[name] = value

                new_obj = content.create(container=type_info['folder'],
                                         type= type_info['type'],
                                         id=data['id'],
                                         **fields)
                for transition in type_info['wf_actions']:
                    try:
                        content.transition(new_obj, transition)
                    except Exception:
                        logger.exception('Could not execute %s transition for %s' % (transition, '/'.join(new_obj.getPhysicalPath())))

                logger.info('Imported %s' % new_obj.getId())
                count += 1

            # Set status on this form page
            self.status = "%s partners imported" % count
        except Exception:
            # Enable emails again:
            utils._send_emails = True
            raise
Beispiel #38
0
 def test_str_storable(self):
     fi = NamedBlobImage(getFile('image.gif'), filename=u'image.gif')
     self.assertEqual(303, fi.getSize())
Beispiel #39
0
 def test_pdata_storable(self):
     pdata = Pdata(getFile('image.gif').read())
     fi = NamedBlobImage(pdata, filename=u'image.gif')
     self.assertEqual(303, fi.getSize())
Beispiel #40
0
    def importContent(self):

        # Grab the "force" parameter from the URL, and convert to boolean.
        # If this is true, everyone will be updated.
        force_update = not not self.request.get('force', False)

        # Initialize the return value list
        rv = []

        # Get a list of the people
        people = self.getPeople()

        # Count total people, and initialize counter
        total_people = len(people)
        counter = 0

        # Log progress
        self.log("Downloaded data, %d entries" % total_people)

        # Get listing of valid classifications from current directory
        valid_classifications = [x.value for x in ClassificationsVocabulary()(self.context)]

        # Add other classifications that are OK to import
        valid_classifications.extend([
            'Adjunct and Affiliate Faculty',
            'Emeritus and Retired Faculty',
            'Emeritus Professors and Retirees',
            'Adjunct & Retired Faculty',
            'Emeritus Faculty',
            'Emeriti and Retired',
            'Assistant to the Director',
            'Retired and Emeritus Faculty',
            'District Directors',
        ])

        # Iterate through contents
        for i in people:

            # Increment counter
            counter = counter + 1

            # Set 'product_type' as 'type'
            i['product_type'] = i.get('type', None)

            # If we were passed a URL, don't do a classification check
            if self.person_url:
                pass

            # If the person is not an employee with a valid classification, skip
            # this record.
            elif not set(i.get('directory_classifications', [])) & set(valid_classifications):

                continue

            # Create content importer from person JSON data
            v = self.content_importer(i)

            # Check for person existing in directory (import_path) and create or
            # update appropriately
            if v.data.get_id in self.import_path.objectIds():

                # Update
                item = self.import_path[v.data.get_id]

                # Only update if feed last updated date is greater than the item
                # last updated date.  If a "force" parameter is provided in the
                # URL, all objects will be updated.
                if force_update or DateTime(v.data.modified) > item.modified():
                    item = self.updateObject(item, v)

                    # Log progress
                    self.log("Updated %s" % v.data.get_id)
                else:
                    # Log progress
                    self.log("Skipped %s" % v.data.get_id)
                    continue

            else:
                # Create
                item = self.createObject(self.import_path, v)

                # Log progress
                self.log("Created %s" % v.data.get_id)

            # Set expiration date
            if v.data.expires:
                expires = DateTime(v.data.expires)
                item.setExpirationDate(expires)

            # Set Image
            image_url = i.get('image_url', None)

            if image_url:
                img = NamedBlobImage()
                img.data = urllib2.urlopen(image_url).read()
                item.leadimage = img

            # Set text field for bio. Note this is not a RichTextValue, since
            # it's a field inherited from another schema
            if v.data.html:
                item.bio = v.data.html

            # Finalize item
            self.finalize(item)

            # Append the data structure converted from the JSON data to rv
            rv.append(json.loads(self.getJSON(item)))

            # Log progress
            self.log("Done with %s, %d/%d" % (v.data.get_id, counter, total_people))

        # Deactivate people who are expired and active
        self.deactivateExpiredPeople()

        # Return a full JSON dump of the updated data
        return json.dumps(rv, indent=4, sort_keys=True)
Beispiel #41
0
def onVideoSave(context, event, force=False):

    # Updated flag
    updated = False

    # Check if we have missing fields
    has_leadimage = not not ILeadImageMarker(context).has_leadimage
    has_duration = not not VideoDataAdapter(context).getDuration()
    has_channel = not not VideoDataAdapter(context).getVideoChannel()
    has_aspect_ratio = not not VideoDataAdapter(context).getVideoAspectRatio()
    has_effective_date = not not context.effective_date

    # If 'force' is true, or doesn't have a lead image and duration.
    if force or not has_leadimage or not has_duration \
             or not has_channel or not has_aspect_ratio \
             or not has_effective_date:

        # Get the API data
        data = getDataForYouTubeVideo(context)

        # Lead Image (if force or not exists)
        if force or not has_leadimage:

            # Get the image data via the YouTube API
            # (will be binary data)
            image_data = getImageForYouTubeVideo(data)

            # Set the lead image if we retrieved it
            if image_data:
                filename = '%s-leadimage' % context.getId()
                field = NamedBlobImage(filename.encode('utf-8'))
                field.data = image_data
                context.leadimage = field
                updated = True

        # Duration (if force or not exists)
        if force or not has_duration:

            # Get the duration from the API data
            # (will be integer)
            duration = data.get('duration', None)

            # If there's a duration, set it.
            if duration:
                VideoDataAdapter(context).setDuration(duration)
                updated = True

        # Channel (if force or not exists)
        if force or not has_channel:

            # Get the channel id from the API data
            # (will be string)
            channel_id = data.get('channel_id', None)

            # If there's a channel id, set it.
            if channel_id:
                VideoDataAdapter(context).setVideoChannel(channel_id)
                updated = True

        # Aspect Ratio (if force or not exists)
        if force or not has_aspect_ratio:

            # Get the aspect_ratio from the API data
            # (will be string)
            aspect_ratio = data.get('aspect_ratio', None)

            # If there's a Aspect Ratio, set it.
            if aspect_ratio:
                VideoDataAdapter(context).setVideoAspectRatio(aspect_ratio)
                updated = True

        # Published date
        if force or not has_effective_date:
            try:
                if data['effective']:
                    effective_date = DateTime(data['effective'])
                    context.setEffectiveDate(effective_date)
                    updated = True
            except:
                pass

        # If we updated a value, reindex the object
        if updated:
            context.reindexObject()