Example #1
0
    def new_folder(self, name, subpath=None):
        """ Create a new collection ``name`` inside the folder ``subpath `` """

        if self.is_readonly:
            raise zExceptions.Forbidden(_('Connector is readonly'))

        if not name:
            raise ValueError(_('No name given'))

        name = safe_unicode(name)
        subpath = safe_unicode(subpath or self.subpath)
        handle = self.context.get_handle(subpath)

        if handle.exists(name):
            msg = _('{}/{} already exists found').format(subpath, name)
            self.messages.add(msg, 'error')
            return self.request.response.redirect(self.context.absolute_url() + '/view/' + subpath)

        try:
            handle.makedir(name)
        except Exception as e:
            msg = _('{}/{} could not be created ({})').format(subpath, name, str(e))
            self.messages.add(msg, 'error')
            return self.request.response.redirect(self.context.absolute_url() + '/' + subpath)

        msg = _('Created {}/{}').format(subpath, name)
        self.messages.add(msg, 'info')
        self.request.response.redirect(self.context.absolute_url() + '/view/' + subpath + '/' + name)
Example #2
0
    def remove(self, resource_name):
        """ Remove a resource by path/name """

        if self.is_readonly:
            raise zExceptions.Forbidden(_('Connector is readonly'))

        subpath = safe_unicode(self.request.get('subpath', self.subpath))

        handle = self.context.get_handle()
        if not handle.exists(resource_name):
            msg = 'Not found {}'.format(resource_name)
            raise zExceptions.NotFound(msg)

        if handle.isdir(resource_name):
            try:
                handle.removetree(resource_name)
            except Exception as e:
                msg = resource_name + _(' could not be deleted') + ' ({})'.format(e)
                self.request.response.setStatus(500)
                return msg

        elif handle.isfile(resource_name):
            try:
                handle.remove(resource_name)
            except Exception as e:
                msg = _('{} could not be deleted ({})').format(resource_name, e)
                self.request.response.setStatus(500)
                return msg

        else:
            msg = _('Unhandled file type for {}').format(resource_name)
            raise RuntimeError(msg)

        msg = _('Deleted {}').format(resource_name)
        self.request.response.setStatus(200)
Example #3
0
    def rename(self, resource_name, new_name):
        """ Rename a resource """

        if self.is_readonly:
            raise zExceptions.Forbidden(_('Connector is readonly'))

        resource_name = safe_unicode(resource_name)
        new_name = safe_unicode(new_name)

        dirname = fs.path.dirname(resource_name)
        new_resource_name = fs.path.join(dirname, new_name)
        handle = self.context.get_handle()

        if handle.exists(new_resource_name):
            raise ValueError(_('Target {} exists').format(resource_name))

        if handle.isfile(resource_name):
            try:
                handle.move(resource_name, new_resource_name)
            except Exception as e:
                msg = resource_name + _(' could not be moved') + ' ({})'.format(e)
                self.request.response.setStatus(500)
                return msg
        else:
            try:
                fs.move.move_dir(handle, resource_name, handle, new_resource_name)
            except Exception as e:
                msg = resource_name + _(' could not be moved') + ' ({})'.format(e)
                self.request.response.setStatus(500)
                return msg

        msg = _('Renamed {} to {}').format(resource_name, new_name)
        self.request.response.setStatus(200)
class DBSettingsEditForm(controlpanel.RegistryEditForm):

    schema = IConnectorSettings
    label = _(u'XML Director Connector settings')
    description = _(u'')

    def updateFields(self):
        super(DBSettingsEditForm, self).updateFields()

    def updateWidgets(self):
        super(DBSettingsEditForm, self).updateWidgets()
Example #5
0
class IConnector(model.Schema):

    connector_url = schema.TextLine(title=_(u'(optional) connection URL of storage'),
                                    description=_(
                                        u'WebDAV: webdav://host:port/path/to/webdav, '
                                        'local filesystem: file://path/to/directory, '
                                        'AWS S3: s3://bucketname, ', 'SFTP sftp://host/path'),
                                    required=False)

    connector_username = schema.TextLine(title=_(u'(optional) username overriding the system settings'), required=False)

    connector_password = schema.Password(title=_(u'(optional) password overriding the system settings'), required=False)

    connector_subpath = schema.TextLine(title=_(u'Subdirectory relative to the global connection URL'),
                                        description=_(u'Use this value for configuring a more specific subpath'),
                                        required=False)

    connector_readonly = schema.Bool(title=_(u'Readonly access'), default=False, required=False)

    form.widget("connector_reference", SelectWidget)
    connector_reference = schema.Choice(
        title=_("Reference to other connector "),
        required=False,
        source=get_connector_references,
        default=None,
    )
Example #6
0
    def zip_import_ui(self, zip_file=None, subpath=None, clean_directories=None):
        """ Import WebDAV subfolder from an uploaded ZIP file """

        if self.is_readonly:
            raise zExceptions.Forbidden(_('Connector is readonly'))

        try:
            imported_files = self.zip_import(zip_file, subpath, clean_directories)
        except Exception as e:
            msg = u'ZIP import failed'
            LOG.error(msg, exc_info=True)
            return self.redirect(msg, 'error')

        self.logger.log(
            'ZIP file imported ({}, {} files)'.format(zip_file, len(imported_files)), details=imported_files)
        return self.redirect(_(u'Uploaded ZIP archive imported'), subpath=subpath)
Example #7
0
    def zip_import(self, zip_file=None):
        """ Import subfolder from an uploaded ZIP file """

        if self.is_readonly:
            raise zExceptions.Forbidden(_('Connector is readonly'))

        subpath = self.request.get('subpath') or self.subpath
        handle = self.context.get_handle(subpath)

        if not zip_file:
            zip_filename = self.request.zipfile.filename
            temp_fn = tempfile.mktemp(suffix='.zip')
            with open(temp_fn, 'wb') as fp:
                self.request.zipfile.seek(0)
                fp.write(self.request.zipfile.read())
            zip_file = temp_fn
        else:
            zip_filename = zip_file

        if not zip_filename:
            raise ValueError(u'No filename detected. Did you really upload a ZIP file?')
        if not zip_filename.endswith('.zip'):
            raise ValueError(u'Uploaded file did not end with .zip. Did you really upload a ZIP file?')

        try:
            with fs.zipfs.ZipFS(zip_file, encoding='utf-8') as zip_handle:

                # import all files from ZIP into WebDAV
                count = 0
                dirs_created = set()
                for i, name in enumerate(zip_handle.walk.files()):

                    target_filename = unicodedata.normalize('NFC', name).lstrip('/')
                    if self.subpath:
                        target_filename = u'{}/{}'.format(self.subpath, target_filename)

                    target_dirname = '/'.join(target_filename.split('/')[:-1])
                    if target_dirname not in dirs_created:
                        try:
                            handle.makedirs(target_dirname, recreate=True)
                            dirs_created.add(target_dirname)
                        except Exception as e:

                            LOG.error('Failed creating {} failed ({})'.format(target_dirname, e))

                    LOG.info(u'ZIP filename({})'.format(name))

                    out_fp = handle.open(target_filename, 'wb')
                    zip_fp = zip_handle.open(name, 'rb')
                    out_fp.write(zip_fp.read())
                    out_fp.close()
                    count += 1

        except Exception as e:
            msg = 'Error opening ZIP file: {}'.format(e)
            raise

        self.request.response.redirect(self.context.absolute_url() + '/view/' + subpath)
Example #8
0
    def upload_file(self):
        """ AJAX callback for Uploadify """

        if self.is_readonly:
            raise zExceptions.Forbidden(_('Connector is readonly'))

        subpath = safe_unicode(self.request.get('subpath', self.subpath))
        filename = safe_unicode(os.path.basename(self.request.file.filename))
        basename, ext = os.path.splitext(filename)

        handle = self.context.get_handle(subpath)

        with handle.open(filename, 'wb') as fp:
            self.request.file.seek(0)
            data = self.request.file.read()
            fp.write(data)

        self.request.response.setStatus(200)
class IConnectorSettings(Interface):
    """ Connector settings """

    connector_url = schema.TextLine(
        title=_(u'Connection URL of storage'),
        description=_(u'WebDAV: webdav://host:port/path/to/webdav, '
                      'local filesystem: file://path/to/directory, '
                      'AWS S3: s3://bucketname, SFTP sftp://host/path'),
        default=u'',
        required=True)

    connector_username = schema.TextLine(
        title=_(u'Username for external storage'),
        description=_(u'Username'),
        default=u'admin',
        required=False)

    connector_password = schema.Password(title=_(u'Password external storage'),
                                         description=_(u'Password'),
                                         default=u'',
                                         required=False)