def __call__(self, value, size=1048576, allowed_types=None, forbidden_types=None): if not value: return False if not INamed.providedBy(value): return False if size and value.getSize() > size: return _( "msg_file_too_big", mapping={"size": size}, default=u"File is bigger than allowed size of ${size} bytes!", ) ftype = splitext(value.filename)[-1] # remove leading dot '.' from file extension ftype = ftype and ftype[1:].lower() or "" if allowed_types and ftype not in allowed_types: return _( "msg_file_not_allowed", mapping={"ftype": ftype.upper()}, default=u'File type "${ftype}" is not allowed!', ) if forbidden_types and ftype in forbidden_types: return _( "msg_file_not_allowed", mapping={"ftype": ftype.upper()}, default=u'File type "${ftype}" is not allowed!', ) return False
def toFieldValue(self, value): if value is None or value == '': return self.field.missing_value if INamed.providedBy(value): return value elif utils.is_file_upload(value): filename = safe_basename(value.filename) if filename is not None and isinstance(filename, six.binary_type): # Work-around for # https://bugs.launchpad.net/zope2/+bug/499696 filename = filename.decode('utf-8') value.seek(0) data = value.read() if data or filename: return self.field._type(data=data, filename=filename) else: return self.field.missing_value else: if isinstance(value, six.text_type): value = value.encode('utf-8') return self.field._type(data=value)
def toFieldValue(self, value): if value is None or value == '': return self.field.missing_value if INamed.providedBy(value): return value elif isinstance(value, FileUpload): filename = safe_basename(value.filename) if filename is not None and not isinstance(filename, unicode): # Work-around for # https://bugs.launchpad.net/zope2/+bug/499696 filename = filename.decode('utf-8') value.seek(0) data = value.read() if data or filename: return self.field._type(data=data, filename=filename) else: return self.field.missing_value else: return self.field._type(data=str(value))
def file_size(self, file_): """Returns the file-size of the `file_` in KB. """ if INamed.providedBy(file_): return file_.getSize() / 1024 else: return 0
def filename(self): if INamed.providedBy(self.value): return self.value.filename elif utils.is_file_upload(self.value): return safe_basename(self.value.filename) else: return None
def _make_namedfile(value, field, widget): """Return a NamedImage or NamedFile instance, if it isn't already one - e.g. when it's base64 encoded data. """ if INamed.providedBy(value): return value string_types = (six.binary_type, six.text_type) if isinstance(value, string_types) and IBytes.providedBy(field): filename, data = b64decode_file(value) elif isinstance(value, dict) or isinstance(value, PersistentDict): filename = value['filename'] data = value['data'] if INamedBlobImageField.providedBy(field): value = NamedBlobImage(data=data, filename=filename) elif INamedImageField.providedBy(field): value = NamedImage(data=data, filename=filename) elif INamedBlobFileField.providedBy(field): value = NamedBlobFile(data=data, filename=filename) else: value = NamedFile(data=data, filename=filename) return value
def toFieldValue(self, value): if value is None or value == '': return self.field.missing_value if INamed.providedBy(value): return value elif isinstance(value, FileUpload): headers = value.headers filename = safe_basename(value.filename) if filename is not None and not isinstance(filename, unicode): # Work-around for # https://bugs.launchpad.net/zope2/+bug/499696 filename = filename.decode('utf-8') contentType = 'application/octet-stream' if headers: contentType = headers.get('Content-Type', contentType) value.seek(0) data = value.read() if data or filename: return self.field._type(data=data, contentType=contentType, filename=filename) else: return self.field.missing_value else: return self.field._type(data=str(value))
def __call__(self, value, size=1048576, allowed_types=None, forbidden_types=None): if not value: return False if not INamed.providedBy(value): return False if size and value.getSize() > size: return _( 'msg_file_too_big', mapping={'size': size}, default=u'File is bigger than allowed size of ${size} bytes!' ) ftype = splitext(value.filename)[-1] # remove leading dot '.' from file extension ftype = ftype and ftype[1:].lower() or '' if allowed_types and ftype not in allowed_types: return _( 'msg_file_not_allowed', mapping={'ftype': ftype.upper()}, default=u'File type "${ftype}" is not allowed!' ) if forbidden_types and ftype in forbidden_types: return _( 'msg_file_not_allowed', mapping={'ftype': ftype.upper()}, default=u'File type "${ftype}" is not allowed!' ) return False
def filename(self): if self.field is not None and self.value == self.field.missing_value: return None elif INamed.providedBy(self.value): return self.value.filename elif isinstance(self.value, FileUpload): return safe_basename(self.value.filename) else: return None
def _toFieldSubValue(self, value, current_field_value): """ Converts a subvalue to an `INamedFile`. Parameters: value -- The value extracted from the request by the widget. current_field_value -- The current value of the field on the context. Return: a value of the fields value_type or it's `missing_value` if the value cannot be converted. See plone.formwidget.namedfile.converter.NamedDataConverter """ value_type = self.field.value_type._type missing_value = self.field.value_type.missing_value if value is None or value == '': return missing_value elif INamed.providedBy(value): return value elif isinstance(value, basestring) and value.startswith('index:'): # we already have the file index = int(value.split(':')[1]) try: return current_field_value[index] except IndexError: return missing_value elif isinstance(value, FileUpload): # create a new file headers = value.headers filename = safe_basename(value.filename) if filename is not None and not isinstance(filename, unicode): # Work-around for # https://bugs.launchpad.net/zope2/+bug/499696 filename = filename.decode('utf-8') contentType = 'application/octet-stream' if headers: contentType = headers.get('Content-Type', contentType) value.seek(0) data = value.read() if data or filename: return value_type(data=data, contentType=contentType, filename=filename) else: return missing_value else: return value_type(data=str(value))
def file_upload_id(self): """Temporary store the uploaded file contents with a file_upload_id key. In case of form validation errors the already uploaded image can then be reused. This is only useful on a POST request: forms should not be using GET, especially when you save something to the database. Note that if we want this on a GET request, we should add a safeWrite call in the code below: plone.protect.utils.safeWrite(up.upload_map, self.request) Otherwise plone.protect auto csrf will complain for example when getting @@site-controlpanel or @@personal-information See https://github.com/plone/Products.CMFPlone/issues/2628 and https://github.com/plone/Products.CMFPlone/issues/2709 """ if self.request.method != 'POST': return '' if self._file_upload_id: # cache this property for multiple calls within one request. # This avoids storing a file upload multiple times. return self._file_upload_id upload_id = None if self.is_uploaded: data = None if INamed.providedBy(self.value): # previously uploaded and failed data = self.value.data else: self.value.seek(0) data = self.value.read() upload_id = uuid.uuid4().hex up = IFileUploadTemporaryStorage(getSite()) up.cleanup() up.upload_map[upload_id] = PersistentDict( filename=self.value.filename, data=data, dt=datetime.now(), ) self._file_upload_id = upload_id return upload_id
def toFieldValue(self, value): filename = None data = None if INamed.providedBy(value): filename = value.filename data = value.data elif isinstance(value, FileUpload): filename = safe_basename(value.filename) value.seek(0) data = value.read() if not data: return self.field.missing_value return b64encode_file(filename, data)
def get_export_data( self, portal_type, blob_format, richtext_format, blacklist, whitelist, query, ): """Return a list of dicts with a dict for each object. The key is the name of the field/value and the value the value. """ all_fields = get_schema_info(portal_type, blacklist, whitelist) results = [] catalog = api.portal.get_tool('portal_catalog') if not query: query = dict() query['portal_type'] = portal_type if 'Language' not in query and HAS_MULTILINGUAL and \ 'Language' in catalog.indexes(): query['Language'] = 'all' brains = catalog.unrestrictedSearchResults(query) for brain in brains: obj = brain.getObject() item_dict = dict() for fieldname, field in all_fields: if fieldname in self.ADDITIONAL_MAPPING: # The way to access the value from this fields is # overridden in ADDITIONAL_MAPPING continue try: value = field.get(field.interface(obj)) except: print("Skipping object at {0}".format(obj.absolute_url())) break if not value: # set a value anyway to keep the dimensions of all value = '' # make sure we do no more transforms field = None if IRichTextValue.providedBy(value): value = transform_richtext(value, mimetype=richtext_format) if IRelationList.providedBy(field): rel_val = [] for relation in value: rel_val.append(get_url_for_relation(relation)) value = pretty_join(rel_val) if IRelationChoice.providedBy(field): value = get_url_for_relation(value) if INamed.providedBy(value): value = get_blob_url(value, brain, blob_format, fieldname) if ICollection.providedBy(field): r = [] for v in value: if INamed.providedBy(v): r.append(u'{0}/@@download/{1}'.format( obj.absolute_url(), fieldname)) # r.append(base64.b64encode(v.data)) else: r.append(v) value = r if IDatetime.providedBy(field) or IDate.providedBy(field): if value.year < 1000: if value.year < 16: year = value.year + 2000 else: year = value.year + 1900 if IDate.providedBy(field): value = datetime.date(month=value.month, day=value.day, year=year) elif IDatetime.providedBy(field): value = datetime.datetime(month=value.month, day=value.day, year=year, hour=value.hour, minute=value.minute, second=value.second) value = api.portal.get_localized_time(value, long_format=True) if safe_callable(value): value = value() if isinstance(value, list) or isinstance(value, tuple): value = pretty_join(value) item_dict[fieldname] = value else: # Update the data with additional info or overridden getters item_dict.update(self.additional_data(obj, blacklist)) results.append(item_dict) continue # executed if the loop ended normally (no break) break # executed if 'continue' was skipped (break) return results
def file_size(self): if INamed.providedBy(self.value): return self.value.getSize() / 1024 else: return 0
def _render_obj(self, obj, new_req=None): """ Render object to string. """ if isinstance(obj, basestring): return obj if new_req is None: new_req = self.request try: if IResource.providedBy(obj): try: f = open(obj.context.path) result = f.read() f.close() except AttributeError: result = obj.context.data except IOError: log.error("Couldn't open '%s' file with resource" % ( obj.context.path)) return None return result if isinstance(obj, (BrowserView, FSPageTemplate, PythonScript)): try: return obj() except NotFound: log.error("Resource '%s' not found" % repr(obj)) return None if isinstance(obj, (FSFile, FSImage)): return self._render_obj(obj._readFile(None)) if isinstance(obj, FSDTMLMethod): return self._render_obj(obj.read()) mt = None try: mt = obj.aq_base.portal_type except AttributeError: pass if mt in self.file_types or isinstance(obj, (ImageField, OFSImage, Pdata, File)): return self._render_obj(obj.data) if PLONE_RESOURCE_INSTALLED and isinstance(obj, FilesystemFile): if not obj.request: obj.request = new_req return obj().read() if PLONE_APP_BLOB_INSTALLED and IBlobWrapper.providedBy(obj): return obj.data if PLONE_NAMEDFILE_INSTALLED and \ INamed.providedBy(obj): return obj.data if IBaseObject.providedBy(obj) or isinstance(obj, PloneSite) or \ DEXTERITY_INSTALLED and IDexterityContent.providedBy(obj): default_page_helper = getMultiAdapter((obj, self.request), name='default_page') def_page_id = default_page_helper.getDefaultPage() if def_page_id: def_page = obj[def_page_id] return self._render_obj(def_page) view_name = obj.getLayout() view = queryMultiAdapter((obj, new_req), name=view_name) if view_name == 'language-switcher': lang = new_req.get('LANGUAGE') def_page = getattr(obj, lang, None) if def_page: return self._render_obj(def_page) if view: try: return view.context() except (ContentProviderLookupError, TypeError): pass view = obj.restrictedTraverse(view_name, None) if view: try: return view.context() except (AttributeError, TypeError): try: return view() except Exception, error: log.warning( "Unable to render view: '%s'! Error occurred: %s" % ( view, error)) else: try: return obj() except AttributeError: pass finally: pass log.warning("Not recognized object '%s'!" % repr(obj)) return None
def file_size(self): if INamed.providedBy(self.value): return byteDisplay(self.value.getSize()) else: return "0 KB"
def export_file(result, header_mapping, request=None): if not result: return None if request is None: request = getRequest() transforms = api.portal.get_tool('portal_transforms') catalog = api.portal.get_tool("portal_catalog") data = [] for row in result: items_dict = dict() if getattr(row, 'getObject', None): obj = row.getObject() else: obj = row for d in header_mapping: fieldid = d['field'] if obj is None: items_dict[d['header']] = row(fieldid) continue if fieldid == '_path': path = obj.getPhysicalPath() virtual_path = request.physicalPathToVirtualPath(path) items_dict[d['header']] = ( '/'.join(virtual_path)).decode('utf-8') continue elif fieldid == '_url': items_dict[d['header']] = (obj.absolute_url()).decode('utf-8') continue value = "" for schemata in iterSchemata(obj): if fieldid not in schemata: continue field = schemata[fieldid] try: value = field.get(schemata(obj)) except AttributeError: continue if value is field.missing_value: continue if IRichTextValue.providedBy(value): # Convert to plain text value = transforms.convertTo(target_mimetype='text/plain', orig=value.raw_encoded, encoding=value.encoding, mimetype=value.mimeType) value = safe_unicode(value.getData()) break if IList.providedBy(field): # Check if items in list point to objects and use titles # instead names = [] for item_id in value: # Loop through choices query = dict(id=item_id) results = catalog(**query) if results: names.append(results[0].Title) if names: value = names value = ', '.join(value) break if INamed.providedBy(value): # Image, file field value = u'{0}/@@download/{1}'.format(row.getURL(), fieldid) break serializer = ISerializer(field) value = serializer(value, {}) break # Added due to an ascii error related to csv export. We convert to # unicode as unicodecsv requires unicode value = safe_unicode(value) items_dict[d['header']] = value data.append(items_dict) dataset = tablib.Dataset() dataset.dict = data return dataset
def is_uploaded(self): return utils.is_file_upload(self.value)\ or INamed.providedBy(self.value)
def get_export_data( self, portal_type, blob_format, richtext_format, blacklist, whitelist, query, ): """Return a list of dicts with a dict for each object. The key is the name of the field/value and the value the value. """ all_fields = get_schema_info(portal_type, blacklist, whitelist) results = [] catalog = api.portal.get_tool('portal_catalog') if not query: query = dict() query['portal_type'] = portal_type if 'Language' not in query and HAS_MULTILINGUAL and \ 'Language' in catalog.indexes(): query['Language'] = 'all' if 'path' not in query: query['path'] = {} query['path']['query'] = '/'.join(self.context.getPhysicalPath()) brains = catalog(query) for brain in brains: obj = brain.getObject() item_dict = dict() for fieldname, field in all_fields: if fieldname in self.ADDITIONAL_MAPPING: # The way to access the value from this fields is # overridden in ADDITIONAL_MAPPING continue value = field.get(field.interface(obj)) if not value: # set a value anyway to keep the dimensions of all value = '' # make sure we do no more transforms field = None if IRichTextValue.providedBy(value): value = transform_richtext(value, mimetype=richtext_format) if IRelationList.providedBy(field): rel_val = [] for relation in value: rel_val.append(get_url_for_relation(relation)) value = pretty_join(rel_val) if IRelationChoice.providedBy(field): value = get_url_for_relation(value) if INamed.providedBy(value): value = get_blob_url(value, brain, blob_format, fieldname) if IDatetime.providedBy(field) or IDate.providedBy(field): value = api.portal.get_localized_time(value, long_format=True) if safe_callable(value): value = value() if isinstance(value, list) or isinstance(value, tuple): value = pretty_join(value) if HAS_GEOLOCATION and isinstance(value, Geolocation): value = value.__dict__ item_dict[fieldname] = value # Update the data with additional info or overridden getters item_dict.update(self.additional_data(obj, blacklist)) results.append(item_dict) return results
def get_export_data( self, portal_type, blob_format, richtext_format, blacklist, whitelist, query, ): """Return a list of dicts with a dict for each object. The key is the name of the field/value and the value the value. """ all_fields = get_schema_info(portal_type, blacklist, whitelist) results = [] catalog = api.portal.get_tool('portal_catalog') if not query: query = dict() query['portal_type'] = portal_type if 'Language' not in query and HAS_MULTILINGUAL and \ 'Language' in catalog.indexes(): query['Language'] = 'all' brains = catalog(query) for brain in brains: obj = brain.getObject() item_dict = dict() for fieldname, field in all_fields: if fieldname in self.ADDITIONAL_MAPPING: # The way to access the value from this fields is # overridden in ADDITIONAL_MAPPING continue value = field.get(field.interface(obj)) if not value: # set a value anyway to keep the dimensions of all value = '' # make sure we do no more transforms field = None if IRichTextValue.providedBy(value): value = transform_richtext(value, mimetype=richtext_format) if IRelationList.providedBy(field): rel_val = [] for relation in value: rel_val.append(get_url_for_relation(relation)) value = pretty_join(rel_val) if IRelationChoice.providedBy(field): value = get_url_for_relation(value) if INamed.providedBy(value): value = get_blob_url(value, brain, blob_format, fieldname) if IDatetime.providedBy(field) or IDate.providedBy(field): value = api.portal.get_localized_time( value, long_format=True) if safe_callable(value): value = value() if isinstance(value, list) or isinstance(value, tuple): value = pretty_join(value) item_dict[fieldname] = value # Update the data with additional info or overridden getters item_dict.update(self.additional_data(obj, blacklist)) results.append(item_dict) return results
def file_size(self): """file_size.""" if INamed.providedBy(self.context.file): return byteDisplay(self.context.file.getSize()) return "0 KB"