Ejemplo n.º 1
0
    def get_file_info(self, public_path):
        path = self._map_path(public_path)
        if path is None:
            raise cherrypy.HTTPError(404)

        filename = os.path.basename(public_path)
        mtype = mimetype(filename)

        type = thumbtype(path)
        turl = None
        summary = None
        if type == "icon":
            turl = mimetypeurl(mtype)
        elif type == "text":
            turl = mimetypeurl(mtype)
            fd = open(path)
            try:
                summary = fd.read(100) + "..."
            except IOError:
                pass
        else:
            turl = url("thumbnail", path=public_path)

        return dict(
            name=filename,
            mimetype=mtype,
            type=type,
            thumburl=turl,
            src=public_path,
            summary=summary,
            url=url("media", path=public_path),
            size=os.path.getsize(path),
            mtime=isotime(os.path.getmtime(path)),
            hidden=_local_is_hidden(path),
        )
Ejemplo n.º 2
0
    def reorder(self, id, **params):
        if getparam('cancel') == '1':
            redirect(url("coll-view", id=id))
        coll = get_or_404(Collection, id)

        context = {}
        if cherrypy.request.method == "POST":
            # FIXME - check csrf token

            order, ordering = coll_order_from_request()

            if getparam('submit') == '1':
                # save order
                coll.autoorder.ordering = ordering
                Collection.objects.set(coll)
                Collection.objects.flush()
                redirect(url("coll-view", id=id))
        else:
            order = []
            for field, dir in coll.autoorder.ordering:
                order.append((len(order), field, dir))

        if not order:
            order.append((0, '', ''))

        context['coll'] = coll
        context['collorder'] = order
        return render("coll-reorder.html", context)
Ejemplo n.º 3
0
 def handle_import_start(self, params):
     """Handle a POST request that starts an import."""
     if getparam("import_cancel", None):
         redirect(url("home"))
     imp = download.Importer()
     imp.start(params)
     if imp.error:
         context = {}
         context['error'] = imp.error
         return render("import/choose-file.html", context)
     self.imports[imp.id] = imp
     redirect(url("import", id=imp.id))
Ejemplo n.º 4
0
 def handle_post(self, params, context):
     context.update(self.build_form_context(params))
     do_import = getparam('import', None, None, params)
     if do_import:
         self.set_next(ImportPerformTask(self.handler, self.importer))
         redirect(url("import", id=self.importer.id))
     return render("import/choose-mappings.html", context)
Ejemplo n.º 5
0
 def handle_post(self, params, context):
     context.update(self.build_form_context(params))
     do_import = getparam('import', None, None, params)
     if do_import:
         self.set_next(BuildExploratourRecordsTask(self.handler, self.importer))
         redirect(url("import", id=self.importer.id))
     return render("import/choose-fields.html", context)
Ejemplo n.º 6
0
    def imp(self, **params):
        stash = {}

        # Get any existing Importer
        imp = None
        imp_id = getintparam("id", None, stash, params)
        if imp_id is not None:
            imp = self.imports.get(imp_id, None)
            if imp is None:
                context = {}
                context['error'] = 'Unknown import ID'
                return render("import/choose-file.html", context)

        if imp is None:
            # No import in progress
            if cherrypy.request.method == "POST":
                return self.handle_import_start(params)
            elif cherrypy.request.method == "GET":
                return render("import/choose-file.html", {})
        else:
            # Import in progress; let it handle the request.
            if cherrypy.request.method == "POST":
                if getparam("import_cancel", None):
                    imp.cancel()
                    redirect(url("home"))
                return imp.handle_post(params)
            elif cherrypy.request.method == "GET":
                return imp.handle_get(params)

        raise cherrypy.NotFound
Ejemplo n.º 7
0
    def create(self, **params):
        context = {}

        if cherrypy.request.method == "POST":
            # FIXME - check csrf token
            title = params.get('newcoll_title', u'').strip()
            parents = coll_parents_from_request()
            if getparam('create'):
                if title:
                    id = create_collection(title, parents)
                    gonext()
                    redirect(url("colls-list", id=id))
                else:
                    context['error'] = "You must set a title for the collection"
        else:
            parents = []

        allowable_parents = set(
            c.id for c in Collection.objects
        )

        context.update(dict(
            parents = tuple(enumerate(parents)),
            allowable_parents = sorted(allowable_parents),
            collections = Collection.objects,
        ))

        return render("coll-new.html", context)
Ejemplo n.º 8
0
    def delete(self, id, **params):
        coll = get_or_404(Collection, id)
        if cherrypy.request.method == "POST":
            # FIXME - check csrf token
            if id:
                if params.get('delete_conf', '') == '':
                    redirect(url("colls-list"))

                coll = get_or_404(Collection, id)

                # Remove the collection's parents
                coll.set_parents(())
                Collection.objects.set(coll)

                # Remove the collection from its childrens parent lists.
                child_colls = coll.children
                for child in child_colls:
                    cparents = set(child.parents)
                    cparents.remove(id)
                    child.set_parents(cparents)
                    Collection.objects.set(child)

                # Iterate through the records in the collection, and remove the
                # collection from them.
                SearchCollection.checkpoint().wait()
                for record in SearchCollection.doc_type('record') \
                   .field.coll.is_in(id)[:]:
                    try:
                        record = record.object
                    except KeyError:
                        # Record is already gone - can't update it.
                        # (This shouldn't happen, but do this check for
                        # robustness.)
                        continue
                    record.collections = filter(lambda x: x != id, record.collections)
                    Record.objects.set(record)

                Collection.objects.remove(id)
                Record.objects.flush()
                Collection.objects.flush()
                gonext()
                redirect(url("colls-list", id=coll.id))
        elif cherrypy.request.method == "GET":
            context = dict(coll=coll)
            return render("coll-delete-confirm.html", context)

        raise cherrypy.HTTPError(404)
Ejemplo n.º 9
0
 def copy(self, id, **params):
     record = copy.deepcopy(get_or_404(Record, id))
     del record.id
     Record.objects.set(record)
     Record.objects.flush()
     redirect(url("record-edit", id=record.id,
                  tmplid=params.get('tmplid', ''),
                  copyof=record.title))
Ejemplo n.º 10
0
    def reparent(self, id, **params):
        if getparam('cancel') == '1':
            redirect(url("coll-view", id=id))
        coll = get_or_404(Collection, id)

        if cherrypy.request.method == "POST":
            # FIXME - check csrf token

            title = getparam('title')
            parents = coll_parents_from_request()

            if getparam('submit') == '1':
                # Save parents
                changed = coll.set_parents(filter(lambda x: x != '', parents))
                if coll.title != title:
                    coll.title = title
                Collection.objects.set(coll)
                Collection.objects.flush()
                Record.objects.flush()
                redirect(url("coll-view", id=id))
        else:
            title = coll.title
            parents = []
            for parent in coll.parents:
                parents.append(parent)
        if not parents:
            parents.append('')

        not_allowed = set(coll.ancestors) - set(coll.parents)
        not_allowed.add(id)

        allowable_parents = set(
            c.id for c in Collection.objects
            if c.id != id and id not in c.ancestors
        )

        context = dict(
            title = title,
            coll = coll,
            parents = tuple(enumerate(parents)),
            allowable_parents = sorted(allowable_parents),
            collections = Collection.objects,
        )

        return render("coll-reparent.html", context)
Ejemplo n.º 11
0
    def thumbnail(self, path, width=64, height=64):
        if not mapper.exists(path):
            redirect(url("/static/icons/thumbs/missing.png"))

        width = int(width)
        height = int(height)

        # Note - the path supplied is supplied as a query parameter, not as
        # part of the path info in the URL, because otherwise cherrypy strips
        # out any double slashes, making it impossible to tell if the path
        # starts with a drivename (on windows) or with an absolute path which
        # should have a / inserted before it (on unix).
        try:
            data, ctype = thumbcache.get_data(mapper._map_path(path), width, height)
            cherrypy.response.headers["Content-Type"] = ctype
            return data
        except IOError:
            redirect(url("/static/icons/thumbs/broken.png"))
Ejemplo n.º 12
0
    def reindex(self, **params):
        stash = {}
        if cherrypy.request.method == "POST":
            progress = pool.get_progress(reindexer_id[0])
            if progress.complete:
                reindexer_id[0] = pool.add_task(Reindexer())
                redirect(url("reindex"))

        context = dict(progress = pool.get_progress(reindexer_id[0]))
        return render("reindex.html", context)
Ejemplo n.º 13
0
    def from_exploratour(self, **params):
        context = {}

        if cherrypy.request.method == "POST":
            imp = import_exploratour.start_import(params)
            if imp.error:
                context['error'] = imp.error
                return render("import/from-exploratour.html", context)
            self.imports[imp.id] = imp
            redirect(url("import-status", id=imp.id))
        return render("import/from-exploratour.html", context)
Ejemplo n.º 14
0
    def export_backup(self, export_id=None, download=False, **params):
        # Read parameters first, to ensure they all get stashed.
        stash = {}

        # Make a new exporter, and get any parameters it needs into the stash.
        exp = Exporter.get('xml')()
        exp.read_params(stash, params)

        # Handle exports which are in progress, or have finished
        if export_id is not None:
            try:
                export_id = int(export_id)
            except ValueError:
                export_id = None
        if export_id is not None:
            try:
                running_exp = exports[export_id]
            except KeyError:
                # Invalid export id (most probably due to a server restart)
                running_exp = None
            if running_exp is not None:
                # Export in progress
                progress = pool.get_progress(export_id)
                context = dict(export_id=export_id, fmt='xml', progress=progress,
                               stash=stash)
                if not progress.complete:
                    return render('export/in_progress.html', context)
                if progress.failed:
                    return render('export/failed.html', context)
                # Export complete
                if not download:
                    # Display a "Export prepared"
                    return render('export/complete.html', context)
                return running_exp.respond()

        # Read the set of things to export.
        search, desc, topcoll = self._get_export_records(stash, None, None, None, True)

        if not getparam('export', False, stash, params):
            # Not ready to start the export yet.
            context = dict(
                           export_desc = desc,
                           stash = stash,
                          )

            exp.add_to_context(context, search, stash, params)
            return render('backup/pick.html', context)

        # Start the exporter
        task = ExportRecords(exp, search)
        export_id = pool.add_task(task)
        exports[export_id] = task

        redirect(url("records-export-inprogress", export_id=export_id, fmt='xml', **stash))
Ejemplo n.º 15
0
 def list(self, **params):
     coll = get_lockto_coll()
     if coll is not None:
         redirect(url("coll-view", id=coll.id))
     groups = [CollGroup(coll.id, coll.title, [coll.id])
               for coll in Collection.objects if not coll.parents]
     groupid = getparam('groupid', '')
     filtered_groups = filter(lambda group: group.id == groupid, groups)
     if len(filtered_groups) > 0:
         currgroup = filtered_groups[0]
     elif len(groups) > 0:
         currgroup = groups[0]
     else:
         currgroup = None
     context = dict(groups=groups, currgroup=currgroup)
     return render("colls-list.html", context)
Ejemplo n.º 16
0
    def _check_delete(self, id, page):
        params = cherrypy.request.params
        if params.get('delete', '') != '':
            tmpl = get_or_404(Template, id)
            context = dict(tmpl=tmpl, page=page)
            return render("tmpl-delete-confirm.html", context)

        if cherrypy.request.method == "POST":
            if params.get('delete_conf', '') != '':
                try:
                    Template.objects.remove(id)
                    Template.objects.flush()
                except KeyError:
                    raise cherrypy.HTTPError(404)
                gonext()
                redirect(url("tmpls-list"))
Ejemplo n.º 17
0
 def roots(self, **params):
     error = None
     if cherrypy.request.method == "POST":
         num = 0
         roots_dict = {}
         roots = []
         dupe_names = set()
         while True:
             name = params.get('rn%d' % num)
             path = params.get('rp%d' % num)
             num += 1
             if name is None or path is None:
                 break
             if name == '':
                 if path != '':
                     error = u'No name specified for path "%s"' % path
             else:
                 if path == '':
                     error = u'Empty path specified for name "%s"' % name
             if name == '' and path == '':
                 continue
             if name != '' and name in roots_dict:
                 dupe_names.add(name)
             path = path.strip()
             roots_dict[name] = path
             roots.append((num - 1, (name, path)))
         if dupe_names:
             if len(dupe_names) == 1:
                 error = u"Duplicated name: \"%s\"" % tuple(dupe_names)[0]
             else:
                 error = u"Duplicated names: \"%s\"" % u'\", \"'.join(sorted(dupe_names))
         if error is None:
             settings = get_settings()
             settings.set_roots(roots_dict)
             Settings.objects.set(settings)
             Settings.objects.flush()
             redirect(url("settings-roots"))
     else:
         roots_dict = get_settings().get_roots()
         if not roots_dict:
             roots_dict = config.default_media_roots
         roots = tuple(enumerate(sorted(roots_dict.items())))
     context = dict(
         error = error,
         roots = roots,
     )
     return render("settings/roots.html", context)
Ejemplo n.º 18
0
    def _check_delete(self, id, page):
        params = cherrypy.request.params
        if params.get('delete', '') != '':
            record = get_or_404(Record, id)
            context = dict(record=record, page=page)
            return render("record-delete-confirm.html", context)

        if cherrypy.request.method == "POST":
            if params.get('delete_conf', '') != '':
                record = get_or_404(Record, id)
                #print "Old collections", record.collections
                record.collections = ()
                # Set the record, to remove the collections 
                Record.objects.set(record)
                Record.objects.remove(id)
                Record.objects.flush()
                Collection.objects.flush()
                gonext()
                redirect(url("search", act='search'))
Ejemplo n.º 19
0
    def _get_export_records(self, stash, record_id, issearch, coll, incsubs):
        """Returns a search queryset, and a description of the export."""

        # record_id is set to export a single record.
        if record_id is not None:
            search = SearchCollection.doc_type('record').field.id == record_id
            return search, "record with id %s" % record_id, None

        # if issearch is set, export the search results.
        if issearch is not None:
            params = SearchParams(stash)
            search_obj = Search(params)
            if not search_obj.validate():
                redirect(url("search", **stash))
            desc = "%d records found by search.\n" % search_obj.match_count
            return search_obj.query, desc + search_obj.query_desc, None

        # FIXME - allow selected records here.

        # If we've got no collection set, but have a lock, set the collection
        # to the locked one.
        lockedto = get_lockto_coll()
        if lockedto is not None and coll is None:
            coll = lockedto.id

        # coll is set to export a whole collection.
        if coll is not None:
            coll_obj = get_or_404(Collection, coll)
            search = coll_obj.items_from_search(incsubs=incsubs)

            desc = "all %d records from collection %s" % (
                len(search),
                coll_obj.title
            )
            if incsubs:
                desc += " (including subcollections)"
            return search, desc, coll_obj

        # If none of the above are set, export everything.
        return SearchCollection.doc_type('record').all()[:], "all records", None
Ejemplo n.º 20
0
 def delete(self, id, **params):
     ret = self._check_delete(id, 'tmpl-delete')
     if ret is not None:
         return ret
     redirect(url("tmpl-view", id=id))
Ejemplo n.º 21
0
    def search(self, **params):
        stash = {}
        context = dict(stash=stash)
        params = SearchParams(stash)
        search = Search(params)
        if not search.validate():
            # If the search doesn't validate, always go to the search entry
            # page.
            params.action = 'entry'
        search.add_to_context(context)
        context['showfull'] = int(getparam('showfull', '0', stash))

        if params.action == 'search':
            return render("search.html", context)
        elif params.action == 'select':
            return render("search_select.html", context)

        elif params.action.startswith('createcoll'):
            if cherrypy.request.method != "POST":
                return render("search_createcoll.html", context)
            subact = params.action[11:]

            parents = []
            for num in getorderparam('parent_order'):
                parent = getparam('parent%d' % num)
                if parent is None or parent == '':
                    continue
                if subact == ('del_parent_%d' % num):
                    continue
                parents.append(unicode(parent))
            if subact == 'add_parent':
                parents.append(u'')
            context['parents'] = tuple(enumerate(parents))
            context['allowable_parents'] = set(
                c.id for c in Collection.objects
            )
            context['collections'] = Collection.objects

            if subact == 'do':
                newtitle = getparam('create_colltitle', '')
                if len(newtitle) == 0:
                    context['error'] = "Cannot create collection with no title"
                    return render("search_createcoll.html", context)

                coll = Collection.find_by_title(newtitle)
                if len(coll) != 0:
                    context['error'] = "Collection with title %s already exists" % newtitle
                    return render("search_createcoll.html", context)

                coll = Collection(None, None, newtitle)
                Collection.objects.set(coll)
                # Have to set the collection before setting the parents, to get
                # an ID for the parents to refer back to.
                coll.set_parents(filter(lambda x: x != '', parents))
                Collection.objects.set(coll)
                Record.objects.flush()
                Collection.objects.flush()

                for record in search.query:
                    record = record.object
                    record.collections = record.collections + [coll.id]
                    Record.objects.set(record)
                Record.objects.flush()
                Collection.objects.flush()

                redirect(url("coll-view", id=coll.id))
            else:
                return render("search_createcoll.html", context)

        elif params.action == 'addtocoll':
            context['all_collections'] = Collection.objects
            if cherrypy.request.method != "POST":
                return render("search_addtocoll.html", context)

            newid = getparam('addto_collid', '')
            if len(newid) == 0:
                context['error'] = "Pick a collection to add to"
                return render("search_addtocoll.html", context)

            coll = Collection.objects.get(newid)
            for record in search.query:
                record = record.object
                record.collections = record.collections + [coll.id]
                Record.objects.set(record)
            Record.objects.flush()
            Collection.objects.flush()

            redirect(url("coll-view", id=coll.id))

            return render("search_addtocoll.html", context)

        elif params.action == 'removefromcoll':
            context['all_collections'] = Collection.objects
            if cherrypy.request.method != "POST":
                return render("search_removefromcoll.html", context)

            newid = getparam('removefrom_collid', '')
            if len(newid) == 0:
                context['error'] = "Pick a collection to remove from"
                return render("search_removefromcoll.html", context)

            coll = Collection.objects.get(newid)
            for record in search.query:
                record = record.object
                record.collections = tuple(filter(lambda x: x != coll.id,
                                                  record.collections))
                Record.objects.set(record)
            Record.objects.flush()
            Collection.objects.flush()

            redirect(url("coll-view", id=coll.id))

            return render("search_removefromcoll.html", context)

        else:
            context['all_collections'] = Collection.objects
            return render("search_entry.html", context)
Ejemplo n.º 22
0
 def delete(self, id, **params):
     ret = self._check_delete(id, 'record-delete')
     if ret is not None:
         return ret
     redirect(url("record-view", id=id, tmplid=params.get('tmplid')))
Ejemplo n.º 23
0
    def export_records(self, export_id=None, fmt='rtf', download=False,
                       **params):
        """Export a set of records.

        """
        # Read parameters first, to ensure they all get stashed.
        stash = {}
        record_id = getparam('record_id', None, stash, params)
        issearch = getparam('issearch', None, stash, params)
        coll = getparam('coll', None, stash, params)
        incsubs = getintparam('incsubs', 1, stash, params)

        # Make a new exporter, and get any parameters it needs into the stash.
        try:
            exp = Exporter.get(fmt)()
        except KeyError:
            raise cherrypy.NotFound
        exp.read_params(stash, params)

        # Handle exports which are in progress, or have finished
        if export_id is not None:
            try:
                export_id = int(export_id)
            except ValueError:
                export_id = None
        if export_id is not None:
            try:
                running_exp = exports[export_id]
            except KeyError:
                # Invalid export id (most probably due to a server restart)
                running_exp = None
            if running_exp is not None:
                # Export in progress
                progress = pool.get_progress(export_id)
                context = dict(export_id=export_id, fmt=fmt, progress=progress,
                               stash=stash)
                if not progress.complete:
                    return render('export/in_progress.html', context)
                if progress.failed:
                    return render('export/failed.html', context)
                # Export complete
                if not download:
                    # Display a "Export prepared"
                    return render('export/complete.html', context)
                return running_exp.respond()

        # Read the set of things to export.
        search, desc, topcoll = self._get_export_records(stash, record_id, issearch,
                                                coll, incsubs)

        if not getparam('export', False, stash, params):
            # Not ready to start the export yet.
            context = dict(
                           fmts = Exporter.fmts(params),
                           fmt = fmt,
                           export_desc = desc,
                           stash = stash,
                          )

            exp.add_to_context(context, search, stash, params)
            return render('export/pickfmt.html', context)

        # Start the exporter
        task = ExportRecords(exp, search)
        export_id = pool.add_task(task)
        exports[export_id] = task

        redirect(url("records-export-inprogress", export_id=export_id, fmt=fmt, **stash))
Ejemplo n.º 24
0
        context['error'] = e.errormsg
        ok = False
        orig_record = get_or_404(Record, id)
        record = dict(inner_xml=params.get('inner_xml', None),
                      collections=validator.collections,
                      fieldnums=orig_record.fieldnums,
                      walkfields=orig_record.walkfields,
                      id=id,
                     )

    if ok and params.get('save', '') != '':
        Record.objects.set(record)
        Record.objects.flush()
        gonext()
        tmplid = params.get('tmplid', '')
        redirect(url("record-view", id=record.id, tmplid=tmplid))

    context['record'] = record

    return context

def tmpl_from_request(id, params):
    context = {}

    params, remcoll = handle_create_collection(params)
    validator = RecordValidator(params, remcoll)
    if validator.invalid_collections:
        return dict(invalid_collections=validator.invalid_collections)

    newid = params.get('newid')
    ok = True