def add(self, path, newfile, replacepath=None):
        """Add the uploaded file to the specified path. Unlike
        the other methods, this method must return its JSON response wrapped in
        an HTML <textarea>, so the MIME type of the response is text/html
        instead of text/plain. The upload form in the File Manager passes the
        current path as a POST param along with the uploaded file. The response
        includes the path as well as the name used to store the file. The
        uploaded file's name should be safe to use as a path component in a
        URL, so URL-encoded at a minimum.
        """

        if six.PY2:
            path = safe_encode(path, 'utf-8')
        if six.PY2 and replacepath is not None:
            replacepath = safe_encode(replacepath, 'utf-8')

        parentPath = self.normalizePath(path)

        error = ''
        code = 0

        name = newfile.filename
        if six.PY2 and isinstance(name, six.text_type):
            name = safe_encode(name, 'utf-8')

        if replacepath:
            newPath = replacepath
            parentPath = '/'.join(replacepath.split('/')[:-1])
        else:
            newPath = '{0}/{1}'.format(parentPath, name,)

        try:
            parent = self.getObject(parentPath)
        except KeyError:
            error = translate(_(u'filemanager_invalid_parent',
                              default=u'Parent folder not found.'),
                              context=self.request)
            code = 1
        else:
            if name in parent and not replacepath:
                error = translate(_(u'filemanager_error_file_exists',
                                  default=u'File already exists.'),
                                  context=self.request)
                code = 1
            else:
                try:
                    self.resourceDirectory.writeFile(newPath, newfile)
                except ValueError:
                    error = translate(_(u'filemanager_error_file_invalid',
                                      default=u'Could not read file.'),
                                      context=self.request)
                    code = 1

        return {
            'parent': self.normalizeReturnPath(parentPath),
            'path': self.normalizeReturnPath(path),
            'name': name,
            'error': error,
            'code': code,
        }
Exemple #2
0
 def test_safe_encode(self):
     """safe_encode should always encode unicode to the specified encoding.
     """
     from Products.CMFPlone.utils import safe_encode
     self.assertEqual(safe_encode(u'späm'), b'sp\xc3\xa4m')
     self.assertEqual(safe_encode(u'späm', 'utf-8'), b'sp\xc3\xa4m')
     self.assertEqual(safe_encode(u'späm', encoding='latin-1'), b'sp\xe4m')
 def test_safe_encode(self):
     """safe_encode should always encode unicode to the specified encoding.
     """
     from Products.CMFPlone.utils import safe_encode
     self.assertEqual(safe_encode(u'späm'), 'sp\xc3\xa4m')
     self.assertEqual(safe_encode(u'späm', 'utf-8'), 'sp\xc3\xa4m')
     self.assertEqual(safe_encode(u'späm', encoding='latin-1'), 'sp\xe4m')
     self.assertEqual(('spam'), 'spam')
    def saveFile(self, path, value):
        processInputs(self.request)

        path = self.request.form.get('path', path)
        value = self.request.form.get('value', value)
        if six.PY2:
            path = safe_encode(path, 'utf-8')
            value = safe_encode(value, 'utf-8')
        path = path.lstrip('/')
        value = value.replace('\r\n', '\n')
        self.context.writeFile(path, value)
        return ' '  # Zope no likey empty responses
    def addFolder(self, path, name):
        """Create a new directory on the server within the given path.
        """
        if six.PY2:
            path = safe_encode(path, 'utf-8')
            name = safe_encode(name, 'utf-8')

        code = 0
        error = ''

        parentPath = self.normalizePath(path)
        parent = None

        try:
            parent = self.getObject(parentPath)
        except KeyError:
            error = translate(_(u'filemanager_invalid_parent',
                              default=u'Parent folder not found.'),
                              context=self.request)
            code = 1
        else:
            if not validateFilename(name):
                error = translate(_(u'filemanager_invalid_foldername',
                                  default=u'Invalid folder name.'),
                                  context=self.request)
                code = 1
            elif name in parent:
                error = translate(_(u'filemanager_error_folder_exists',
                                  default=u'Folder already exists.'),
                                  context=self.request)
                code = 1
            else:
                try:
                    parent.makeDirectory(name)
                except UnicodeDecodeError:
                    error = translate(
                        _(
                            u'filemanager_invalid_foldername',
                            default=u'Invalid folder name.'
                        ),
                        context=self.request
                    )
                    code = 1

        self.request.response.setHeader('Content-Type', 'application/json')
        return json.dumps({
            'parent': self.normalizeReturnPath(parentPath),
            'name': name,
            'error': error,
            'code': code,
        })
    def test_subscribers_upload_create_subscribers(self):
        template = """salutation,name_prefix,firstname,lastname,email,organization
Ms,PhD,Jane,Doe,[email protected],Doe Cörp
Mr,PhD,John,Doe,[email protected],Doe Cörp
"""
        filename = os.path.join(os.path.dirname(__file__),
                                "easynewsletter-subscribers.csv")
        if six.PY2:
            with open(filename, "wb") as f:
                f.write(safe_encode(template))
        else:
            with open(filename, "w", newline="") as f:
                f.write(safe_unicode(template))
        if six.PY2:
            file = open(filename)
        else:
            file = open(filename, "rb")

        self.portal.REQUEST.form.update({
            'form.button.Import': 'submit',
            'csv_upload': file,
        })
        view = getMultiAdapter((self.newsletter, self.portal.REQUEST),
                               name="subscribers-upload")
        self.assertTrue(view.__name__ == "subscribers-upload")
        view.create_subscribers()
        file.close()
Exemple #7
0
    def writeDataFile(self, filename, text, content_type, subdir=None):
        if filename not in self.filenames:
            return

        if filename == 'types.xml':
            # Remove all the types except our targets.
            # Strategy: suck into ElementTree element, remove nodes,
            # convert back to text, prettify.
            root = etree.fromstring(text)
            todelete = []
            for element in root.getchildren():
                name = element.attrib['name']
                if name != 'title' and name not in self.typelist:
                    todelete.append(element)
            for element in todelete:
                root.remove(element)
            # Add a marker for ZopeSkel additions
            root.append(etree.Comment(' -*- extra stuff goes here -*- '))
            # minor prettifying
            root_str = safe_unicode(etree.tostring(root))
            text = '<?xml version="1.0"?>\n{0}'.format(root_str)
            text = text.replace('<!--', ' <!--')
            text = text.replace('-->', '-->\n')

        self._archive.writestr(filename, safe_encode(text))
Exemple #8
0
 def handleSubmit(self, action):
     unsorted_data, errors = self.extractData()
     if errors:
         self.status = self.formErrorsMessage
         return
     unsorted_data = self.updateServerSideData(unsorted_data)
     errors = self.processActions(unsorted_data)
     if errors:
         return self.setErrorsMessage(errors)
     data = OrderedDict(
         [x for x in getFieldsInOrder(self.schema) if x[0] in unsorted_data]
     )
     data.update(unsorted_data)
     thanksPageOverride = self.context.thanksPageOverride
     if not thanksPageOverride:
         # we come back to the form itself.
         # the thanks page is handled in the __call__ method
         return
     thanksPageOverrideAction = self.context.thanksPageOverrideAction
     thanksPage = get_expression(self.context, thanksPageOverride)
     if six.PY2 and isinstance(thanksPage, six.text_type):
         thanksPage = thanksPage.encode("utf-8")
     if thanksPageOverrideAction == "redirect_to":
         self.request.response.redirect(thanksPage)
         return
     if thanksPageOverrideAction == "traverse_to":
         thanksPage = self.context.restrictedTraverse(thanksPage)
         thanksPage = mapply(thanksPage, self.request.args, self.request)
         self.request.response.write(safe_encode(thanksPage))
Exemple #9
0
    def writeDataFile(self, filename, text, content_type, subdir=None):
        if filename not in self.filenames:
            return

        if filename == 'types.xml':
            # Remove all the types except our targets.
            # Strategy: suck into ElementTree element, remove nodes,
            # convert back to text, prettify.
            root = etree.fromstring(text)
            todelete = []
            for element in root.getchildren():
                name = element.attrib['name']
                if name != 'title' and name not in self.typelist:
                    todelete.append(element)
            for element in todelete:
                root.remove(element)
            # Add a marker for ZopeSkel additions
            root.append(etree.Comment(' -*- extra stuff goes here -*- '))
            # minor prettifying
            root_str = safe_unicode(etree.tostring(root))
            text = '<?xml version="1.0"?>\n{0}'.format(root_str)
            text = text.replace('<!--', ' <!--')
            text = text.replace('-->', '-->\n')

        self._archive.writestr(filename, safe_encode(text))
Exemple #10
0
    def getFolder(self, path, getSizes=False):
        """Returns a dict of file and folder objects representing the
        contents of the given directory (indicated by a "path" parameter). The
        values are dicts as returned by getInfo().

        A boolean parameter "getsizes" indicates whether image dimensions
        should be returned for each item. Folders should always be returned
        before files.

        Optionally a "type" parameter can be specified to restrict returned
        files (depending on the connector). If a "type" parameter is given for
        the HTML document, the same parameter value is reused and passed
        to getFolder(). This can be used for example to only show image files
        in a file system tree.
        """
        if six.PY2:
            path = safe_encode(path, 'utf-8')

        folders = []
        files = []

        path = self.normalizePath(path)
        folder = self.getObject(path)

        for name in folder.listDirectory():
            if IResourceDirectory.providedBy(folder[name]):
                folders.append(self.getInfo(
                    path='{0}/{1}/'.format(path, name), getSize=getSizes))
            else:
                files.append(self.getInfo(
                    path='{0}/{1}'.format(path, name), getSize=getSizes))
        return folders + files
Exemple #11
0
    def delete(self, path):
        """Delete the item at the given path.
        """
        if six.PY2:
            path = safe_encode(path, 'utf-8')

        npath = self.normalizePath(path)
        parentPath = '/'.join(npath.split('/')[:-1])
        name = npath.split('/')[-1]
        code = 0
        error = ''

        try:
            parent = self.getObject(parentPath)
        except KeyError:
            error = translate(_(u'filemanager_invalid_parent',
                              default=u'Parent folder not found.'),
                              context=self.request)
            code = 1
        else:
            try:
                del parent[name]
            except KeyError:
                error = translate(_(u'filemanager_error_file_not_found',
                                  default=u'File not found.'),
                                  context=self.request)
                code = 1

        self.request.response.setHeader('Content-Type', 'application/json')
        return json.dumps({
            'path': self.normalizeReturnPath(path),
            'error': error,
            'code': code,
        })
Exemple #12
0
    def getFile(self, path):
        if six.PY2:
            path = safe_encode(path, 'utf-8')
        path = self.normalizePath(path)
        ext = self.getExtension(path=path)
        result = {'ext': ext}
        self.request.response.setHeader('Content-Type', 'application/json')

        if ext in self.imageExtensions:
            obj = self.getObject(path)
            info = self.getInfo(obj)
            info['preview'] = path
            result['info'] = self.previewTemplate(info=info)
            return json.dumps(result)
        else:
            data = self.context.openFile(path)
            try:
                data = data.read()

                if six.PY2 and isinstance(data, six.text_type):
                    result['contents'] = data.encode('utf8')
                else:
                    result['contents'] = safe_unicode(data)
                try:
                    return json.dumps(result)
                except UnicodeDecodeError:
                    # The file we're trying to get isn't unicode encodable
                    # so we just return the file information, not the content
                    del result['contents']
                    obj = self.getObject(path)
                    info = self.getInfo(obj)
                    result['info'] = self.previewTemplate(info=info)
                    return json.dumps(result)
            except AttributeError:
                return None
Exemple #13
0
 def safe_nativestring(value, encoding='utf-8'):
     """Convert a value to str in py2 and to text in py3
     """
     if six.PY2 and isinstance(value, six.text_type):
         value = safe_encode(value, encoding)
     if not six.PY2 and isinstance(value, six.binary_type):
         value = safe_unicode(value, encoding)
     return value
Exemple #14
0
    def renameFile(self, path, newName):
        """Rename the item at the given path to the new name
        """

        if six.PY2:
            path = safe_encode(path, 'utf-8')
            newName = safe_encode(newName, 'utf-8')

        npath = self.normalizePath(path)
        oldPath = newPath = '/'.join(npath.split('/')[:-1])
        oldName = npath.split('/')[-1]

        code = 0
        error = ''

        try:
            parent = self.getObject(oldPath)
        except KeyError:
            error = translate(_(u'filemanager_invalid_parent',
                              default=u'Parent folder not found.'),
                              context=self.request)
            code = 1
        else:
            if newName != oldName:
                if newName in parent:
                    error = translate(
                        _(
                            u'filemanager_error_file_exists',
                            default=u'File already exists.'
                        ),
                        context=self.request)
                    code = 1
                else:
                    parent.rename(oldName, newName)

        self.request.response.setHeader('Content-Type', 'application/json')
        return json.dumps({
            'oldParent': self.normalizeReturnPath(oldPath),
            'oldName': oldName,
            'newParent': self.normalizeReturnPath(newPath),
            'newName': newName,
            'error': error,
            'code': code,
        })
    def __call__(self):
        context = aq_inner(self.context)
        # Create CSV file
        filename = tempfile.mktemp()
        if six.PY2:
            file = open(filename, "wb")
            csvWriter = UnicodeWriter(file, {
                "delimiter": ",",
                "quotechar": '"',
                "quoting": csv.QUOTE_MINIMAL
            })
        else:
            file = open(filename, "w", newline="")
            csvWriter = csv.writer(
                file,
                dialect="excel",
                delimiter=",",
                quotechar='"',
                quoting=csv.QUOTE_MINIMAL,
            )

        csvWriter.writerow([x for x in CSV_HEADER])
        for subscriber in api.content.find(portal_type="Newsletter Subscriber",
                                           context=self.context,
                                           sort_on="email"):
            obj = subscriber.getObject()
            csvWriter.writerow([
                obj.salutation,
                obj.name_prefix,
                obj.firstname,
                obj.lastname,
                # obj.nl_language,
                obj.email,
                obj.organization,
            ])
        file.close()

        with open(filename, "r") as f:
            data = f.read()
        data = safe_encode(data)
        # Create response
        response = context.REQUEST.response
        response.addHeader(
            "Content-Disposition",
            "attachment; filename=easynewsletter-subscribers.csv")
        response.addHeader("Content-Type", "text/csv")
        response.addHeader("Content-Length", "%d" % len(data))
        response.addHeader("Pragma", "no-cache")
        response.addHeader(
            "Cache-Control",
            "must-revalidate, post-check=0, pre-check=0, public")
        response.addHeader("Expires", "0")

        # Return CSV data
        return data
Exemple #16
0
    def addFile(self, path, name):
        """Add a new empty file in the given directory
        """
        if six.PY2:
            path = safe_encode(path, 'utf-8')
            name = safe_encode(name, 'utf-8')

        error = ''
        code = 0

        parentPath = self.normalizePath(path)
        newPath = '{0}/{1}'.format(parentPath, name,)

        try:
            parent = self.getObject(parentPath)
        except KeyError:
            error = translate(_(u'filemanager_invalid_parent',
                              default=u'Parent folder not found.'),
                              context=self.request)
            code = 1
        else:
            if not validateFilename(name):
                error = translate(_(u'filemanager_invalid_filename',
                                  default=u'Invalid file name.'),
                                  context=self.request)
                code = 1
            elif name in parent:
                error = translate(_(u'filemanager_error_file_exists',
                                  default=u'File already exists.'),
                                  context=self.request)
                code = 1
            else:
                self.resourceDirectory.writeFile(newPath, b'')

        self.request.response.setHeader('Content-Type', 'application/json')
        return json.dumps({
            'parent': self.normalizeReturnPath(parentPath),
            'name': name,
            'error': error,
            'code': code,
            'path': path
        })
 def writerow(self, row):
     # row = [s or '' for s in row]
     row = [safe_encode(s) or b"" for s in row]
     self.writer.writerow(row)
     data = self.queue.getvalue()
     data = safe_unicode(data)
     data = self.encoder.encode(safe_unicode(data))
     # write to the target stream
     self.stream.write(data)
     # empty queue
     self.queue.truncate(0)
Exemple #18
0
    def saveFile(self, path, value):
        path = path.lstrip('/')
        if six.PY2:
            path = safe_encode(path, 'utf-8')
        value = value.strip()
        if six.PY2:
            value = safe_encode(value, 'utf-8')

        value = value.replace('\r\n', '\n')

        if path in self.context:
            if IResourceDirectory.providedBy(self.context[path]):
                return json.dumps({'error': 'invalid path'})

        if 'relativeUrls' in self.request.form:
            reg = re.compile('url\(([^)]+)\)')
            urls = reg.findall(value)

            # Trim off the @@plone.resourceeditor bit to just give us the
            # theme url
            limit = self.request.URL.find('@@plone.resourceeditor')
            location = self.request.URL[0:limit]
            base = urlparse(location)
            for url in urls:
                asset = urlparse(url.strip("'").strip('"'))
                if base.netloc != asset.netloc:
                    continue

                base_dir = '.' + posixpath.dirname(base.path)
                target = '.' + asset.path
                out = posixpath.relpath(target, start=base_dir)
                value = value.replace(url.strip('"').strip("'"), out)

        self.request.response.setHeader('Content-Type', 'application/json')
        if isinstance(self.context, FilesystemResourceDirectory):
            # we cannot save in an FS directory, but we return the file content
            # (useful when we compile less from the theming editor)
            return json.dumps({'success': 'tmp', 'value': value})
        else:
            self.context.writeFile(path, value)
            return json.dumps({'success': 'save'})
def exportRegistry(context):

    logger = context.getLogger('plone.app.registry')
    registry = queryUtility(IRegistry)

    if registry is None:
        logger.info("Cannot find registry")
        return

    exporter = RegistryExporter(registry, context)
    body = exporter.exportDocument()
    if body is not None:
        context.writeDataFile('registry.xml', safe_encode(body), 'text/xml')
def fix_workspace_members(context):
    """ This makes sense only on Python2 because on Python3 the index keys
    will already be str instances in any case
    """
    if not six.PY2:
        return
    pc = api.portal.get_tool("portal_catalog")
    index = pc._catalog.indexes.get("workspace_members")
    if not index:
        return
    keys_to_fix = (key for key in index._index
                   if isinstance(key, six.text_type))
    for key in keys_to_fix:
        index._index[safe_encode(key)] = index._index.pop(key)
Exemple #21
0
    def getFile(self, path):
        self.setup()
        if six.PY2:
            path = safe_encode(path, 'utf-8')

        path = self.normalizePath(path)
        file = self.context.context.unrestrictedTraverse(path)
        ext = self.getExtension(path, file)
        result = {'ext': ext}
        if ext not in self.imageExtensions:
            result['contents'] = str(file.data)
        else:
            info = self.getInfo(path)
            result['info'] = self.previewTemplate(info=info)

        self.request.response.setHeader('Content-Type', 'application/json')
        return json.dumps(result)
Exemple #22
0
    def download(self, path):
        """Serve the requested file to the user
        """
        if six.PY2:
            path = safe_encode(path, 'utf-8')

        npath = self.normalizePath(path)
        parentPath = '/'.join(npath.split('/')[:-1])
        name = npath.split('/')[-1]

        parent = self.getObject(parentPath)

        self.request.response.setHeader('Content-Type',
                                        'application/octet-stream')
        self.request.response.setHeader(
            'Content-Disposition',
            'attachment; filename="{0}"'.format(name)
        )

        # TODO: Use streams here if we can
        return parent.readFile(name)
Exemple #23
0
    def __call__(
        self,
        fieldname=None,
        direction="thumbnail",
        height=None,
        width=None,
        scale=None,
        **parameters
    ):

        """Factory for image scales`.
        """
        orig_value = getattr(self.context, fieldname, None)
        if orig_value is None:
            return

        if height is None and width is None:
            dummy, format_ = orig_value.contentType.split("/", 1)
            return None, format_, (orig_value._width, orig_value._height)
        elif not parameters and height and width \
                and height == getattr(orig_value, "_height", None) \
                and width == getattr(orig_value, "_width", None):
            dummy, format_ = orig_value.contentType.split("/", 1)
            return orig_value, format_, (orig_value._width, orig_value._height)
        orig_data = None
        try:
            orig_data = orig_value.open()
        except AttributeError:
            orig_data = getattr(aq_base(orig_value), "data", orig_value)
        if not orig_data:
            return
        # Handle cases where large image data is stored in FileChunks instead
        # of plain string
        if isinstance(orig_data, tuple(FILECHUNK_CLASSES)):
            # Convert data to 8-bit string
            # (FileChunk does not provide read() access)
            orig_data = str(orig_data)

        # If quality wasn't in the parameters, try the site's default scaling
        # quality if it exists.
        if "quality" not in parameters:
            quality = self.get_quality()
            if quality:
                parameters["quality"] = quality

        if not getattr(orig_value, "contentType", "") == "image/svg+xml":
            try:
                result = self.create_scale(
                    orig_data,
                    direction=direction,
                    height=height,
                    width=width,
                    **parameters
                )
            except (ConflictError, KeyboardInterrupt):
                raise
            except Exception:
                logger.exception(
                    'Could not scale "{0!r}" of {1!r}'.format(
                        orig_value, self.context.absolute_url(),
                    ),
                )
                return
            if result is None:
                return
        else:
            if isinstance(orig_data, (six.text_type)):
                orig_data = safe_encode(orig_data)
            if isinstance(orig_data, (bytes)):
                orig_data = BytesIO(orig_data)

            result = orig_data.read(), "svg+xml", (width, height)

        data, format_, dimensions = result
        mimetype = "image/{0}".format(format_.lower())
        value = orig_value.__class__(
            data, contentType=mimetype, filename=orig_value.filename,
        )
        value.fieldname = fieldname

        # make sure the file is closed to avoid error:
        # ZODB-5.5.1-py3.7.egg/ZODB/blob.py:339: ResourceWarning:
        # unclosed file <_io.FileIO ... mode='rb' closefd=True>
        if isinstance(orig_data, BlobFile):
            orig_data.close()

        return value, format_, dimensions
Exemple #24
0
def scrub_html(self, orig):
    # append html tag to create a dummy parent for the tree
    html_parser = html.HTMLParser(encoding="utf-8")
    orig = safe_encode(orig)
    tag = b"<html"
    if tag in orig.lower():
        # full html
        tree = html.fromstring(orig, parser=html_parser)
        strip_outer = bodyfinder
    else:
        # partial html (i.e. coming from WYSIWYG editor)
        tree = html.fragment_fromstring(orig,
                                        create_parent=True,
                                        parser=html_parser)

        def strip_outer(s):
            return s[5:-6]

    for elem in tree.iter(etree.Element):
        if elem is not None:
            for attrib, value in elem.attrib.items():
                if hasScript(value):
                    del elem.attrib[attrib]

    registry = getUtility(IRegistry)
    self.settings = registry.forInterface(IFilterSchema, prefix="plone")

    valid_tags = self.settings.valid_tags
    nasty_tags = [t for t in self.settings.nasty_tags if t not in valid_tags]
    if six.PY2:
        safe_attrs = [attr.decode() for attr in html.defs.safe_attrs]
    else:
        safe_attrs = [i for i in html.defs.safe_attrs]
    safe_attrs.extend(self.settings.custom_attributes)
    remove_script = "script" in nasty_tags and 1 or 0
    cleaner = Cleaner(
        kill_tags=nasty_tags,
        remove_tags=[],
        allow_tags=valid_tags,
        page_structure=False,
        safe_attrs_only=True,
        safe_attrs=safe_attrs,
        embedded=False,
        remove_unknown_tags=False,
        meta=False,
        javascript=remove_script,
        scripts=remove_script,
        forms=False,
        style=False,
    )
    try:
        cleaner(tree)
    except AssertionError:
        # some VERY invalid HTML
        return ""
    # remove all except body or outer div
    # changes in
    # https://github.com/plone/Products.PortalTransforms/pull/43
    if six.PY2:
        result = etree.tostring(tree, encoding="utf-8", method="html").strip()
    else:
        result = etree.tounicode(tree, method="html").strip()
    return strip_outer(result)
Exemple #25
0
    def move(self, path, directory):
        """Move the item at the given path to a new directory
        """
        if six.PY2:
            path = safe_encode(path, 'utf-8')
            directory = safe_encode(directory, 'utf-8')

        npath = self.normalizePath(path)
        newParentPath = self.normalizePath(directory)

        parentPath = self.parentPath(npath)
        filename = npath.split('/')[-1]

        code = 0
        error = ''
        newCanonicalPath = '{0}/{1}'.format(newParentPath, filename)

        try:
            parent = self.getObject(parentPath)
        except KeyError:
            error = translate(_(u'filemanager_invalid_parent',
                              default=u'Parent folder not found.'),
                              context=self.request)
            code = 1
            return json.dumps({
                'code': code,
                'error': error,
                'newPath': self.normalizeReturnPath(newCanonicalPath),
            })

        try:
            target = self.getObject(newParentPath)
        except KeyError:
            error = translate(_(u'filemanager_error_folder_exists',
                              default=u'Destination folder not found.'),
                              context=self.request)
            code = 1
            return json.dumps({
                'code': code,
                'error': error,
                'newPath': self.normalizeReturnPath(newCanonicalPath),
            })

        if filename not in parent:
            error = translate(_(u'filemanager_error_file_not_found',
                              default=u'File not found.'),
                              context=self.request)
            code = 1
        elif filename in target:
            error = translate(_(u'filemanager_error_file_exists',
                              default=u'File already exists.'),
                              context=self.request)
            code = 1
        else:
            obj = parent[filename]
            del parent[filename]
            target[filename] = obj

        return json.dumps({
            'code': code,
            'error': error,
            'newPath': self.normalizeReturnPath(newCanonicalPath),
        })
Exemple #26
0
def createThemeFromTemplate(title, description, baseOn='template'):
    """Create a new theme from the given title and description based on
    another theme resource directory
    """

    source = queryResourceDirectory(THEME_RESOURCE_NAME, baseOn)
    if source is None:
        raise KeyError("Theme {0:s} not found".format(baseOn))

    themeName = getUtility(IURLNormalizer).normalize(title)
    if six.PY2 and isinstance(themeName, six.text_type):
        themeName = themeName.encode('utf-8')

    resources = getOrCreatePersistentResourceDirectory()

    resources.makeDirectory(themeName)
    target = resources[themeName]

    cloneResourceDirectory(source, target)

    manifest = SafeConfigParser()

    if MANIFEST_FILENAME in target:
        if six.PY2:
            fp = target.openFile(MANIFEST_FILENAME)
            try:
                if hasattr(manifest, "read_file"):
                    # backports.configparser
                    manifest.read_file(fp)
                else:
                    manifest.readfp(fp)
            finally:
                fp.close()

        else:
            # configparser can only read/write text
            # but in py3 plone.resource objects are BytesIO objects.
            fp = target.openFile(MANIFEST_FILENAME)
            try:
                data = fp.read()
            finally:
                fp.close()
            manifest.read_string(safe_unicode(data))

    if not manifest.has_section('theme'):
        manifest.add_section('theme')

    if six.PY2 and isinstance(title, six.text_type):
        title = title.encode('utf-8')
    if six.PY2 and isinstance(description, six.text_type):
        description = description.encode('utf-8')
    manifest.set('theme', 'title', title)
    manifest.set('theme', 'description', description)

    if manifest.has_option('theme', 'prefix'):
        prefix = u"/++%s++%s" % (THEME_RESOURCE_NAME, themeName)
        manifest.set('theme', 'prefix', prefix)

    if manifest.has_option('theme', 'rules'):
        rule = manifest.get('theme', 'rules')
        rule_file_name = rule.split('/')[-1]  # extract real rules file name
        rules = u"/++%s++%s/%s" % (THEME_RESOURCE_NAME, themeName,
                                   rule_file_name)
        manifest.set('theme', 'rules', rules)

    paths_to_fix = [
        'development-css', 'production-css', 'tinymce-content-css',
        'development-js', 'production-js'
    ]
    for var_path in paths_to_fix:
        if not manifest.has_option('theme', var_path):
            continue
        val = manifest.get('theme', var_path)
        if not val:
            continue
        template_prefix = '++%s++%s/' % (THEME_RESOURCE_NAME, baseOn)
        if template_prefix in val:
            # okay, fix
            val = val.replace(template_prefix,
                              '++%s++%s/' % (THEME_RESOURCE_NAME, themeName))
            manifest.set('theme', var_path, val)

    # plone.resource uses OFS.File which is a BytesIO objects
    # but configparser can only deal with text (StringIO).
    # So we need to do this stupid dance to write manifest.cfg
    tempfile = six.StringIO()
    manifest.write(tempfile)
    tempfile.seek(0)
    data = tempfile.read()
    tempfile.close()
    manifestContents = six.BytesIO(safe_encode(data))

    target.writeFile(MANIFEST_FILENAME, manifestContents)
    return themeName
Exemple #27
0
    def getInfo(self, path, getSize=False):
        """Returns information about a single file. Requests
        with mode "getinfo" will include an additional parameter, "path",
        indicating which file to inspect. A boolean parameter "getsize"
        indicates whether the dimensions of the file (if an image) should be
        returned.
        """
        if six.PY2:
            path = safe_encode(path, 'utf-8')

        path = self.normalizePath(path)
        obj = self.getObject(path)

        filename = obj.__name__
        error = ''
        errorCode = 0

        properties = {
            'dateModified': None,
        }

        if isinstance(obj, File):
            properties['dateModified'] = DateTime(obj._p_mtime).strftime('%c')
            size = obj.get_size() / 1024
            if size < 1024:
                size_specifier = u'kb'
            else:
                size_specifier = u'mb'
                size = size / 1024
            properties['size'] = '{0}{1}'.format(
                size,
                translate(_(u'filemanager_{0}'.format(size_specifier),
                            default=size_specifier), context=self.request)
            )

        fileType = 'txt'

        siteUrl = self.portalUrl
        resourceName = self.resourceDirectory.__name__

        preview = '{0}/{1}/images/fileicons/default.png'.format(
            siteUrl,
            self.staticFiles
        )

        if IResourceDirectory.providedBy(obj):
            preview = '{0}/{1}/images/fileicons/_Open.png'.format(
                siteUrl,
                self.staticFiles
            )
            fileType = 'dir'
            path = path + '/'
        else:
            fileType = self.getExtension(path, obj)
            if fileType in self.imageExtensions:
                preview = '{0}/++{1}++{2}/{3}'.format(
                    siteUrl,
                    self.resourceType,
                    resourceName,
                    path
                )
            elif fileType in self.extensionsWithIcons:
                preview = '{0}/{1}/images/fileicons/{2}.png'.format(
                    siteUrl,
                    self.staticFiles,
                    fileType
                )

        if isinstance(obj, Image):
            properties['height'] = obj.height
            properties['width'] = obj.width

        return {
            'path': self.normalizeReturnPath(path),
            'filename': filename,
            'fileType': fileType,
            'preview': preview,
            'properties': properties,
            'error': error,
            'code': errorCode,
        }
def export_schema(context):
    """Export TTW schema
    """
    schema = ttw.serialize_ttw_schema()
    context.writeDataFile(FILE, safe_encode(schema), 'text/xml')
    logger.info('Exported schema')