def generate(self, force=False): ''' Generate the preview from the file attribute It tries to spare cpu cycles by generating the thumbnail only if the file is actually changed. For this reason a _video_size parameter on the video_thumb is set ''' mtr = api.portal.get_tool('mimetypes_registry') if not shasattr(self.schema, 'file'): return video = self.schema.file try: mime_type_description = mtr.lookup(video.contentType)[0].id except: logger.exception('Cannot check mimetype') mime_type_description = '' if not mime_type_description == 'MPEG-4 video': self.schema.video_thumb = None return if not force: try: cached_size = self.schema.video_thumb._video_size except AttributeError: cached_size = None if cached_size == video.size: # Highly improbable that a new video with the same size # replaced the old one. We have nothing to do here return fd, tmpfile = tempfile.mkstemp() with openBlob(video) as f: cmd = 'ffmpegthumbnailer -s 0 -i {infile} -o {oufile}'.format( infile=f.name, oufile=tmpfile, ) try: subprocess.call(cmd.split()) except: self.schema.video_thumb = None logger.exception('Error running command %r', cmd) return thumb_name = video.filename.rpartition('.')[0] + u'.png' with open(tmpfile, 'rb') as thumb: nbi = NamedBlobImage( thumb.read(), filename=thumb_name, ) nbi._video_size = video.size self.schema.video_thumb = nbi
def createNewsitem(self, path, title=None): obj = self._createObject('News Item', path, title=title) named_image = NamedBlobImage(random_image(400, 200), filename=u'test.jpg', contentType='image/png') obj.image = named_image obj.reindexObject()
def createImage(self, path, width=800, height=600, title=None): obj = self._createObject('Image', path, title=title) named_image = NamedBlobImage(random_image(width, height), filename=u'test.jpg', contentType='image/png') obj.image = named_image obj.reindexObject()
def setUp(self): super(TestAvatarViews, self).setUp() avatar_file = open( os.path.join(os.path.dirname(__file__), TEST_AVATAR_FILENAME), 'r') self.profile1.portrait = NamedBlobImage(data=avatar_file.read(), filename=TEST_AVATAR_FILENAME) self.default_avatar = default_avatar(self.request.response)
def populate_with_object(self, obj): """Tile can be populated with images and links; in this case we're not going to take care of any modification of the original object; we just copy the data to the tile and deal with it. """ if obj.portal_type not in self.accepted_ct(): return super(BannerTile, self).populate_with_object(obj) # check permissions obj = aq_base(obj) # avoid acquisition title = obj.Title() rights = obj.Rights() if hasattr(obj, 'Rights') else None # if image, store a copy of its data if obj.portal_type == 'Image': if hasattr(obj, 'getImage'): data = obj.getImage().data else: data = obj.image.data image = NamedBlobImage(data) else: image = None image_description = obj.Description() or obj.Title() remote_url = obj.getRemoteUrl() if obj.portal_type == 'Link' else None data_mgr = ITileDataManager(self) data_mgr.set({ 'title': title, 'image': image, 'image_description': image_description, 'remote_url': remote_url, 'rights': rights, })
def get_image_data(self, obj): """Get image data from the object used to populate the tile. :param obj: object used to populate the tile :type obj: content type instance :returns: image :rtype: NamedBlobImage instance or None """ image = None # if has image, store a copy of its data if self._has_image_field(obj) and self._field_is_visible('image'): scales = obj.restrictedTraverse('@@images') image = scales.scale('image', None) if image is not None and image != '': if isinstance(image.data, NamedBlobImage): # Dexterity image = image.data else: # Archetypes data = image.data if hasattr(data, 'data'): # image data weirdness... data = data.data image = NamedBlobImage(data) return image
def fetch_data(self, field_obj, field_value, _obj, row_buffer): field_type = field_obj[1].__class__.__name__ field_title = field_obj[1].title field_name = field_obj[0] if field_type in ('NamedBlobImage', 'NamedBlobFile'): request = urllib2.Request(url=field_value) try: response = urllib2.urlopen(request) filename = os.path.basename(response.url) if field_type == 'NamedBlobFile': blob_file = NamedBlobFile(data=response.read(), filename=safe_unicode(filename)) elif field_type == 'NamedBlobImage': blob_file = NamedBlobImage(data=response.read(), filename=safe_unicode(filename)) setattr(_obj, field_name, blob_file) return True except Exception: field_title = translate(_(field_title), context=self.request) error_doc = translate( _("""The URL you have provided could not be reached."""), context=self.request) msg = u'{0}: {1}; '.format(error_doc, field_title) row_buffer[2] += msg return False
def populate_with_object(self, obj): """Tile can be populated with any content type with image or getImage attribute; in this case we're not going to take care of any modification of the original object; we just copy the data to the tile and deal with it. """ if obj.portal_type not in self.accepted_ct(): return super(BannerTile, self).populate_with_object(obj) # check permissions if hasattr(obj, 'getRemoteUrl'): remote_url = obj.getRemoteUrl() else: # Get object URL # For Image and File objects (or any other in typesUseViewActionInListings) # we must add a /view to prevent the download of the file obj_url = obj.absolute_url_path() props = api.portal.get_tool('portal_properties') stp = props.site_properties view_action_types = stp.getProperty('typesUseViewActionInListings', ()) if hasattr(obj, 'portal_type') and obj.portal_type in view_action_types: obj_url += '/view' remote_url = obj_url image = None # if has image, store a copy of its data if self._has_image_field(obj) and self._field_is_visible('image'): scales = obj.restrictedTraverse('@@images') image = scales.scale('image', None) if image is not None and image != '': if isinstance(image.data, NamedBlobImage): # Dexterity image = image.data else: # Archetypes image = NamedBlobImage(image.data) obj = aq_base(obj) # avoid acquisition title = safe_unicode(obj.Title()) data_mgr = ITileDataManager(self) data_mgr.set({ 'title': title, 'image': image, 'remote_url': remote_url, })
def create_image(self, image, title): filedata = image.data.read() filename = image.data.filename blobimage = NamedBlobImage(data=filedata, filename=filename) obj = ploneapi.content.create(type='Image', title=title, image=blobimage, container=self.context) obj.indexObject() transaction.commit() return obj.UID()
def process(context): video = context.file if not video or video.filename == aws.FILENAME: return try: opened = openBlob(video._blob) bfilepath = opened.name opened.close() except IOError: logger.warn('error opening blob file') return # by default, assume all non-mp4 videos need to be converted # but in reality, all videos need converting, even mp4. # md5 is only what makes this possible convert_it = video.contentType.split('/')[-1] != 'mp4' if md5 is not None: old_hash = getattr(context, '_file_hash', None) current_hash = md5(bfilepath) if old_hash is None or old_hash != current_hash: convert_it = True if context.image and not convert_it: # already an mp4 and already has a screen grab return tmpdir = mkdtemp() tmpfilepath = os.path.join(tmpdir, video.filename) copyfile(bfilepath, tmpfilepath) if convert_it: output_filepath = os.path.join(tmpdir, 'output.mp4') try: avconv.convert(tmpfilepath, output_filepath) except: pass if os.path.exists( output_filepath) and os.path.getsize(output_filepath) > 0: if md5 is not None: try: context._file_hash = md5(output_filepath) except: pass context._p_jar.sync() fi = open(output_filepath) namedblob = NamedBlobFile(fi, filename=switchFileExt( video.filename, 'mp4')) context.file = namedblob fi.close() if not context.image: # try and grab one from video output_filepath = os.path.join(tmpdir, u'screengrab.png') try: avconv.grab_frame(tmpfilepath, output_filepath) if os.path.exists(output_filepath): fi = open(output_filepath) context.image = NamedBlobImage(fi, filename=u'screengrab.png') fi.close() except: logger.warn('error getting thumbnail from video') rmtree(tmpdir)
def _convertFormat(context): # reset these... context.video_file_ogv = None context.video_file_webm = None video = context.video_file context.video_converted = True try: opened = openBlob(video._blob) bfilepath = opened.name opened.close() except IOError: logger.warn('error opening blob file') return tmpdir = mkdtemp() tmpfilepath = os.path.join(tmpdir, video.filename) copyfile(bfilepath, tmpfilepath) try: metadata = avprobe.info(tmpfilepath) except: logger.warn('not a valid video format') return context.metadata = metadata conversion_types = { 'mp4': 'video_file' } portal = getToolByName(context, 'portal_url').getPortalObject() settings = GlobalSettings(portal) for type_ in settings.additional_video_formats: format = getFormat(type_) if format: conversion_types[format.extension] = 'video_file_%s' % ( format.extension ) # sometimes force full video conversion force = settings.force for video_type, fieldname in conversion_types.items(): if video_type == video.contentType.split('/')[-1] and not force: setattr(context, fieldname, video) else: output_filepath = os.path.join(tmpdir, 'output.' + video_type) try: avconv.convert(tmpfilepath, output_filepath, video_type, context) except: logger.warn('error converting to %s' % video_type) continue if os.path.exists(output_filepath): fi = open(output_filepath) namedblob = NamedBlobFile( fi, filename=switchFileExt(video.filename, video_type)) setattr(context, fieldname, namedblob) fi.close() # try and grab one from video output_filepath = os.path.join(tmpdir, u'screengrab.png') try: avconv.grab_frame(tmpfilepath, output_filepath) if os.path.exists(output_filepath): with open(output_filepath, 'rb') as fi: data = fi.read() context.image = NamedBlobImage(data, filename=u'screengrab.png') fi.close() except: logger.warn('error getting thumbnail from video') rmtree(tmpdir)
def _convertFormat(context): # reset these... context.video_file_webm = None video = context.video_file context.video_converted = True try: opened = openBlob(video._blob) bfilepath = opened.name opened.close() except IOError: logger.warn('error opening blob file') return tmpdir = mkdtemp() tmpfilepath = os.path.join(tmpdir, video.filename) copyfile(bfilepath, tmpfilepath) try: metadata = avprobe.info(tmpfilepath) except: logger.warn('NOT a valid video format') return context.metadata = metadata logger.info('Valid video format') try: duration = _get_duration(tmpfilepath) except: logger.warn('cannot recover duration from file') return context.duration = duration conversion_types = {} portal = getToolByName(context, 'portal_url').getPortalObject() settings = GlobalSettings(portal) for type_ in settings.additional_video_formats: format = getFormat(type_) if format: conversion_types[format.type_] = '%s' % (format.quality) for video_type, quality in conversion_types.items(): vt = video_type.split('_')[0] if video_type == video.contentType.split('/')[-1]: setattr(context, vt, video) else: output_filepath = os.path.join(tmpdir, 'output_' + video_type + '.' + vt) try: avconv.convert(tmpfilepath, output_filepath, vt, quality, context) except: logger.warn('error converting to %s' % vt) continue if os.path.exists(output_filepath): fi = open(output_filepath) namedblob = NamedBlobFile(fi, filename=switchFileExt( video.filename, vt)) setattr(context, video_type, namedblob) fi.close() import transaction transaction.commit() # try and grab one from video output_filepath = os.path.join(tmpdir, u'screengrab.png') try: avconv.grab_frame(tmpfilepath, output_filepath) if os.path.exists(output_filepath): with open(output_filepath, 'rb') as fi: data = fi.read() context.image = NamedBlobImage(data, filename=u'screengrab.png') fi.close() except: logger.warn('error getting thumbnail from video') logger.warn('CONVERSIONS FINISHED') rmtree(tmpdir)
def process(context): video = context.file if not video or video.filename == aws.FILENAME: return try: opened = openBlob(video._blob) bfilepath = opened.name opened.close() except IOError: logger.warn('error opening blob file') return # by default, assume all non-mp4 videos need to be converted # but in reality, all videos need converting, even mp4. # md5 is only what makes this possible convert_it = video.contentType.split('/')[-1] != 'mp4' if md5 is not None: old_hash = getattr(context, '_file_hash', None) current_hash = md5(bfilepath) if old_hash is None or old_hash != current_hash: convert_it = True if context.image and not convert_it: # already an mp4 and already has a screen grab return if convert_it and youtube.should_upload(context): try: youtube.upload(context, bfilepath, filename=video.filename) # saving hash tells us we do not need to convert anymore... context._file_hash = md5(bfilepath) convert_it = False except Exception: logger.error('Error uploading youtube video', exc_info=True) tmpdir = mkdtemp() tmpfilepath = os.path.join(tmpdir, video.filename) copyfile(bfilepath, tmpfilepath) if convert_it: output_filepath = os.path.join(tmpdir, 'output.mp4') try: avconv.convert(tmpfilepath, output_filepath) except Exception: logger.info('Could not convert video', exc_info=True) if (os.path.exists(output_filepath) and os.path.getsize(output_filepath) > 0): if md5 is not None: try: context._file_hash = md5(output_filepath) except Exception: logger.info('Could not get md5', exc_info=True) if not getCelery().conf.task_always_eager: context._p_jar.sync() fi = open(output_filepath) namedblob = NamedBlobFile( fi, filename=switchFileExt(video.filename, 'mp4')) context.file = namedblob fi.close() if not context.image: # try and grab one from video output_filepath = os.path.join(tmpdir, u'screengrab.png') try: avconv.grab_frame(tmpfilepath, output_filepath) if os.path.exists(output_filepath): fi = open(output_filepath) context.image = NamedBlobImage(fi, filename=u'screengrab.png') fi.close() except Exception: logger.warning( 'error getting thumbnail from video', exc_info=True) rmtree(tmpdir)
def addMail(self, mailString): """ Store mail as news item Returns created item """ pw = self.context.portal_workflow (header, body) = splitMail(mailString) # if 'keepdate' is set, get date from mail, # XXX 'time' is unused if self.getValueFor('keepdate'): timetuple = rfc822.parsedate_tz(header.get('date')) time = DateTime(rfc822.mktime_tz(timetuple)) # ... take our own date, clients are always lying! else: time = DateTime() (TextBody, ContentType, HtmlBody, Attachments) = unpackMail(mailString) # Test Zeitangabe hinter Subject today = date.today() mydate = today.strftime("%d.%m.%Y") # let's create the news item subject = mime_decode_header(header.get('subject', 'No Subject')) sender = mime_decode_header(header.get('from', 'No From')) title = "%s" % (subject) new_id = IUserPreferredURLNormalizer(self.request).normalize(title) id = self._findUniqueId(new_id) # ContentType is only set for the TextBody if ContentType: body = TextBody else: body = self.HtmlToText(HtmlBody) # XXX als vorlaeufige Loesung from zope.component import getMultiAdapter plone_view = getMultiAdapter((self.context, self.request), name='plone') desc = plone_view.cropText(body, 60) body = '\n'.join([wrap_line(line) for line in body.splitlines()]) uni_aktuell_body = ("<p><strong>%s: %s</strong></p> " "<p> </p><pre>%s</pre>" % (mydate, sender, body)) objid = self.context.invokeFactory( 'News Item', id=id, title=title, text=RichTextValue(uni_aktuell_body), description=desc, ) mailObject = getattr(self.context, objid) images = [ att for att in Attachments if att['maintype'] == 'image' and att['filename'] ] if images and hasattr(mailObject, 'image'): image = Attachments[0] mailObject.image = NamedBlobImage( filename=safe_unicode(image['filename']), data=image['filebody'], ) try: pw.doActionFor(mailObject, 'publish') except Exception as e: log.exception(e) return mailObject
# notes += safe_unicode(str(row)) # # if key in ids: # # setattr(newart, ids[key], value) # # elif key == 'note' and value: # # newart.text = RichTextValue(value, 'text/html', 'text/html') # # # print "Note", # if notes: # re.compile(r'resolveuid/([0-9a-f]+)').sub(resolveUID, notes) # notes = u"<table>%s</table>" % notes # newart.text = RichTextValue(notes, 'text/html', 'text/html') setSite(target_site) notes = u"<dl>%s</dl>" % notes newart.text = RichTextValue(notes, 'text/html', 'text/html') awImageField = awImageItem.Schema().get('image') image = NamedBlobImage() image.data = scaleImage(awImageField, awImageItem) image.contentType = awImageItem.content_type filename = awImageItem.getFilename() if filename: image.filename = filename.decode('ASCII') else: filename = id newart.image = image target_folder[id] = newart print id, if u'resolve' in notes: print 'resolveuid' else: print commit()
def test_avatar_tag_with_portrait(self): self.login_as_portal_owner() profile = pi_api.userprofile.create( username='******', email='*****@*****.**', approve=True, properties={ 'fullname': 'Jane Doe', }, ) profile.portrait = NamedBlobImage( data='GIF89a;', filename=u'avatar.png') self.maxDiff = None tag_no_link = re.sub('[ \n]+', ' ', pi_api.userprofile.avatar_tag( username='******', link_to=None)) self.assertEqual( tag_no_link, u' <span class="pat-avatar avatar" data-initials="{initials}" ' 'title="{fullname}" > ' '<img src="{portal_url}/profiles/{userid}/@@avatar_profile.jpg" ' 'alt="Image of {fullname}" class="" ' 'i18n:attributes="alt"> ' '</span>' ''.format( portal_url=self.portal.absolute_url(), userid=profile.username, fullname=profile.fullname, initials=profile.initials, )) tag_link_profile = re.sub('[ \n]+', ' ', pi_api.userprofile.avatar_tag( username='******', link_to='profile')) self.assertEqual( tag_link_profile, u' <a href="{portal_url}/profiles/{userid}" ' 'class="pat-avatar avatar" data-initials="{initials}" ' 'title="{fullname}" > ' '<img src="{portal_url}/profiles/{userid}/@@avatar_profile.jpg" ' 'alt="Image of {fullname}" class="" ' 'i18n:attributes="alt"> ' '</a>' ''.format( portal_url=self.portal.absolute_url(), userid=profile.username, fullname=profile.fullname, initials=profile.initials, )) tag_link_image = re.sub('[ \n]+', ' ', pi_api.userprofile.avatar_tag( username='******', link_to='image')) self.assertEqual( tag_link_image, u' <a href="{portal_url}/profiles/{userid}/@@avatar_profile.jpg" ' 'class="pat-avatar avatar pat-gallery user-info-avatar" ' 'data-initials="{initials}" title="{fullname}" > ' '<img src="{portal_url}/profiles/{userid}/@@avatar_profile.jpg" ' 'alt="Image of {fullname}" class="" ' 'i18n:attributes="alt"> ' '</a>' ''.format( portal_url=self.portal.absolute_url(), userid=profile.username, fullname=profile.fullname, initials=profile.initials, ))
def render(self): # Get the api key from registry settings = get_settings() # workaround for http://bugs.python.org/issue5285, # map unicode to strings janrain_api_key = str(settings.janrain_api_key) if not janrain_api_key: return 'No Janrain API key configured' # Get the token token = self.request.form.get('token', None) if not token: return 'No token passed in request' # Get the user profile from Janrain auth_info_url = '%s/auth_info?apiKey=%s&token=%s' % ( JANRAIN_API_BASE_URL, janrain_api_key, token, ) if settings.janrain_use_extended_profile: auth_info_url = auth_info_url + '&extended=true' resp = urllib2.urlopen(auth_info_url) auth_info = simplejson.loads(resp.read()) # This is for Plone's built in member management instead of membrane # See if a user already exists for the profile's email # email = auth_info['profile']['email'] # member = None # if email: # member = mtool.getMemberById(email) # See if user already exists using dexterity.membrane profile = auth_info.get('profile', {}) email = profile.get('verifiedEmail', None) # NB: Do NOT accept the 'email' attribute as an alternative # to 'verifiedEmail'. The 'email' attribute can be entered by # users and therefore would be a security hole. if not email: raise AttributeError( 'No email provided from social profile, unable to create ' 'account') email = email.lower() res = get_brains_for_email(self.context, email, self.request) if not res: # create new Person if no existing Person was found # with the same email name = profile.get('name', {}) address = profile.get('address', {}) if not address: addresses = profile.get('addresses', []) if addresses: address = addresses[0] data = { 'first_name': name.get('givenName', None), 'last_name': name.get('familyName', None), 'email': email, 'street_address': address.get('streetAddress', None), 'city': address.get('locality', None), 'state': address.get('region', None), 'zip': address.get('postalCode', None), 'country': address.get('country', None), # 'gender': profile.get('gender', None), 'social_signin': True, } # Create the user people_container = getattr(getSite(), 'people') person = createContentInContainer( people_container, 'collective.salesforce.fundraising.person', checkConstraints=False, **data) # Authenticate the user mtool = getToolByName(self.context, 'portal_membership') acl = getToolByName(self.context, 'acl_users') newSecurityManager(None, acl.getUser(email)) mtool.loginUser() # or use the existing Person if found else: # Authenticate the user mtool = getToolByName(self.context, 'portal_membership') acl = getToolByName(self.context, 'acl_users') newSecurityManager(None, acl.getUser(email)) mtool.loginUser() person = res[0].getObject() if not person.social_signin: person.social_signin = True # Set the photo photo = profile.get('photo', None) if not photo: photos = profile.get('photos', []) if photos: photo = photos[0] if photo and (not person.portrait or not person.portrait.size): img_data = urllib2.urlopen(photo).read() person.portrait = NamedBlobImage(img_data) # See if came_from was passed came_from = self.request.form.get('came_from', None) # fix odd bug where came_from is a list of two values if came_from and isinstance(came_from, (list, tuple)): came_from = came_from[0] if came_from: return self.request.response.redirect(came_from) # merge in with standard plone login process. login_next = self.context.restrictedTraverse('login_next') login_next()