Example #1
0
def makeTempFileIntoThumbnail(tmpFileFullPath, thumbnailFormat,
                              fileStorageDirectory):
    """Given a temporarily saved file, prepare and store a thumbnail."""
    mimeType = determineFileProperties(tmpFileFullPath).get('file_mime_type')
    resizeMethod = imageMimeTypeToResizeMethodMap.get(mimeType)
    if resizeMethod == 'resize':
        newId = uuid4().hex
        if resizeToThumbnail(
                tmpFileFullPath,
                fileIdToPath(newId, fileStorageDirectory=fileStorageDirectory),
                thumbnailFormat=thumbnailFormat,
        ):
            return newId, mimeType
    elif resizeMethod == 'copy':
        newId = uuid4().hex
        shutil.copy(
            tmpFileFullPath,
            fileIdToPath(newId, fileStorageDirectory=fileStorageDirectory),
        )
        return newId, mimeType
    else:
        # if mime type not listed, fail and that's it
        return None, None
Example #2
0
def placeFSFileInBox(db,
                     user,
                     fileStorageDirectory,
                     box,
                     filePhysicalPath,
                     fileName,
                     fileDescription,
                     fileTextualMode='',
                     fileThumbnailFormat=None):
    """
        Given an actual file at a physical location,
        insert it as a Ostracion file by handling the
        filesystem DB as well as the actual file copy
        into the storage directories.
    """
    # can user write to box?
    if userHasPermission(db, user, box.permissions, 'w'):
        # is the name available?
        if not isNameUnderParentBox(db, box, fileName):
            protoFile = {
                'box_id': box.box_id,
                'name': fileName,
                'description': fileDescription,
                'date': datetime.datetime.now(),
            }
            userName = user.username
            newFile = File(**recursivelyMergeDictionaries(
                protoFile,
                defaultMap={
                    'creator_username': userName,
                    'icon_file_id_username': userName,
                    'metadata_username': userName,
                    'editor_username': userName,
                    'textual_mode': fileTextualMode,
                },
            ))
            filePath = fileIdToPath(
                newFile.file_id,
                fileStorageDirectory=fileStorageDirectory,
            )
            shutil.copy2(filePhysicalPath, filePath)
            #
            fileProperties = determineFileProperties(filePath)
            newFile.mime_type = fileProperties['file_mime_type']
            newFile.type = fileProperties['file_type']
            newFile.size = fileProperties['file_size']
            #
            if (fileThumbnailFormat is not None
                    and isImageMimeType(newFile.mime_type)):
                # thumbnail preparation
                fileThumbnailId, fileThumbnailMimeType = makeFileThumbnail(
                    newFile.file_id,
                    newFile.mime_type,
                    thumbnailFormat=fileThumbnailFormat,
                    fileStorageDirectory=fileStorageDirectory,
                )
                if fileThumbnailId is not None:
                    newFile.icon_file_id = fileThumbnailId
                    newFile.icon_mime_type = fileThumbnailMimeType
            #
            makeFileInParent(db, parentBox=box, newFile=newFile)
            db.commit()
        else:
            raise OstracionError('Cannot create a file with that name')
    else:
        raise OstracionError('User has no write permission on box')
Example #3
0
def saveAndAnalyseFilesInBox(db,
                             files,
                             parentBox,
                             user,
                             thumbnailFormat,
                             fileStorageDirectory,
                             pastActionVerbForm='uploaded'):
    """ Save files and enrich them with type/mimetype,
        unless something fails - this handles overwrites
        (file-on-file) and blockades (file has same name as box)
    """
    #
    # checking for name clashes with boxes
    if any(
            isBoxNameUnderParentBox(db, parentBox, fName)
            for fName in (fObj['name'] for fObj in files)):
        raise OstracionError('Files cannot have the name of existing boxes')
    else:
        if not userHasPermission(db, user, parentBox.permissions, 'w'):
            raise OstracionError('User has no write permission on this box')
        else:
            userName = user.username
            fsDeletionQueue = []
            numReplacements = 0
            #
            for file in files:
                newFile = File(**recursivelyMergeDictionaries(
                    {k: v
                     for k, v in file.items() if k != 'fileObject'},
                    defaultMap={
                        'creator_username': userName,
                        'icon_file_id_username': userName,
                        'metadata_username': userName,
                        'editor_username': userName,
                        'textual_mode': 'plain',
                    },
                ))
                # are we overwriting a file?
                if isFileNameUnderParentBox(db, parentBox, newFile.name):
                    # delete the old file entry
                    # AND mark the file and its thumbnail
                    # (if any) for later deletion
                    prevFile = getFileFromParent(
                        db,
                        parentBox,
                        newFile.name,
                        user,
                    )
                    fsDeletionQueue += deleteFile(
                        db,
                        parentBox,
                        prevFile,
                        user,
                        fileStorageDirectory=fileStorageDirectory,
                        skipCommit=True,
                    )
                    numReplacements += 1
                #
                filePath = fileIdToPath(
                    newFile.file_id,
                    fileStorageDirectory=fileStorageDirectory,
                )
                file['fileObject'].save(filePath)
                #
                fileProperties = determineFileProperties(filePath)
                newFile.mime_type = fileProperties['file_mime_type']
                newFile.type = fileProperties['file_type']
                newFile.size = fileProperties['file_size']
                #
                if (thumbnailFormat is not None
                        and isImageMimeType(newFile.mime_type)):
                    # thumbnail preparation
                    fileThumbnailId, fileThumbnailMimeType = makeFileThumbnail(
                        newFile.file_id,
                        newFile.mime_type,
                        thumbnailFormat=thumbnailFormat,
                        fileStorageDirectory=fileStorageDirectory,
                    )
                    if fileThumbnailId is not None:
                        newFile.icon_file_id = fileThumbnailId
                        newFile.icon_mime_type = fileThumbnailMimeType
                #
                makeFileInParent(db, parentBox=parentBox, newFile=newFile)
            flushFsDeleteQueue(fsDeletionQueue)
            db.commit()
            return '%i file%s %s successfully%s.' % (
                len(files), '' if len(files) == 1 else 's', pastActionVerbForm,
                '' if numReplacements == 0 else
                (' (%i replaced)' % numReplacements))
Example #4
0
def storeFileAsThumbnail(db, fileToSave, mode, thumbnailFormat, targetItem,
                         parentBox, user, tempFileDirectory,
                         fileStorageDirectory):
    """ Handle setting/unsetting of thumbnail for various items
        (box,file,user,setting,user-as-admin).

        If a file to save is provided:
            store the file on the temp dir
            and if it is a valid thumbnail deal with its preparation
            and setting on the item, including possibly deletion of
            the previous thumbnail if necessary.
        if None is passed:
            simply delete any previous thumbnail if present

        Return True iff the (un/)setting is successful
    """
    # permission checks
    if mode == 'b':
        if not userHasPermission(db, user, targetItem.permissions, 'w'):
            raise OstracionError('User has no icon permission on this item')
    elif mode == 'f':
        if not userHasPermission(db, user, parentBox.permissions, 'w'):
            raise OstracionError('User has no icon permission on this item')
    elif mode == 'l':
        if not userHasPermission(db, user, parentBox.permissions, 'w'):
            raise OstracionError('User has no icon permission on this item')
    elif mode == 'u':
        if user.username != targetItem.username:
            raise OstracionError('Insufficient permissions')
    elif mode == 'au':
        if not userIsAdmin(db, user):
            raise OstracionError('Insufficient permissions')
    elif mode == 's':
        if not userIsAdmin(db, user):
            raise OstracionError('Insufficient permissions')
    #
    if fileToSave is not None:
        tempFileName = temporaryFileName(tempFileDirectory=tempFileDirectory)
        fileToSave.save(tempFileName)
        fileProperties = determineFileProperties(tempFileName)
    else:
        tempFileName = None
    #
    failures = False
    if tempFileName is None:
        thumbnailId = None
        thbMimeType = None
    else:
        if isImageMimeType(fileProperties['file_mime_type']):
            # make thumbnail and get the new ID
            thumbnailId, thbMimeType = makeTempFileIntoThumbnail(
                tempFileName,
                thumbnailFormat=thumbnailFormat,
                fileStorageDirectory=fileStorageDirectory,
            )
        else:
            failures = True
    if not failures:
        # un/set the icon ID
        if mode == 'f':
            fsDeleteQueue = updateFileThumbnail(
                db,
                targetItem,
                thumbnailId,
                thbMimeType,
                user,
                fileStorageDirectory=fileStorageDirectory)
        elif mode == 'l':
            fsDeleteQueue = updateLinkThumbnail(
                db,
                targetItem,
                thumbnailId,
                thbMimeType,
                user,
                fileStorageDirectory=fileStorageDirectory)
        elif mode == 'b':
            fsDeleteQueue = updateBoxThumbnail(
                db,
                targetItem,
                thumbnailId,
                thbMimeType,
                user,
                fileStorageDirectory=fileStorageDirectory)
        elif mode in {'u', 'au'}:
            fsDeleteQueue = updateUserThumbnail(
                db,
                targetItem,
                thumbnailId,
                thbMimeType,
                user,
                fileStorageDirectory=fileStorageDirectory)
        elif mode == 's':
            fsDeleteQueue = updateSettingThumbnail(
                db,
                targetItem,
                thumbnailId,
                thbMimeType,
                user,
                fileStorageDirectory=fileStorageDirectory)
        else:
            raise NotImplementedError('Unhandled storeFileAsThumbnail mode')
        flushFsDeleteQueue(fsDeleteQueue)
    #
    return not failures
Example #5
0
def editTextFileView(fsPathString=''):
    """Edit-text-file route."""
    user = g.user
    db = dbGetDatabase()
    lsPath = splitPathString(fsPathString)
    boxPath, fileName = lsPath[:-1], lsPath[-1]
    request._onErrorUrl = url_for(
        'lsView',
        lsPathString='/'.join(boxPath[1:]),
    )
    fileStorageDirectory = g.settings['system']['system_directories'][
        'fs_directory']['value']
    parentBox = getBoxFromPath(db, boxPath, user)
    file = getFileFromParent(db, parentBox, fileName, user)
    if file is None:
        raise OstracionError('File not found.')
    else:
        fileActions = prepareFileActions(
            db,
            file,
            boxPath[1:] + [file.name],
            parentBox,
            user,
            discardedActions={'text_edit'},
        )
        fileInfo = prepareFileInfo(db, file)
        form = EditTextFileForm()
        form.textformat.choices = [
            (mId, mDesc['title'])
            for mId, mDesc in sorted(
                textFileViewingModes.items(),
                key=lambda kv: kv[1]['index'],
            )
        ]
        ##
        if form.validate_on_submit():
            newcontents = form.filecontents.data
            filePath = fileIdToPath(
                file.file_id,
                fileStorageDirectory=fileStorageDirectory,
            )
            with open(filePath, 'w') as openFile:
                openFile.write('%s' % newcontents)
            # file properties
            fileProperties = determineFileProperties(filePath)
            newFile = File(**file.asDict())
            newFile.mime_type = fileProperties['file_mime_type']
            newFile.type = fileProperties['file_type']
            newFile.size = fileProperties['file_size']
            newFile.textual_mode = form.textformat.data
            newFile.editor_username = user.username
            updateFile(db, boxPath, file.name, newFile, user)
            #
            flashMessage('Info', 'Info', 'File "%s" saved.' % file.name)
            return redirect(
                url_for(
                    'lsView',
                    lsPathString='/'.join(boxPath[1:]),
                )
            )
        else:
            form.filecontents.data = applyDefault(
                form.filecontents.data,
                open(
                    fileIdToPath(
                        file.file_id,
                        fileStorageDirectory=fileStorageDirectory,
                    )
                ).read(),
            )
            form.textformat.data = applyDefault(
                form.textformat.data,
                file.textual_mode,
                additionalNulls=['None'],
            )
            pathBCrumbs = makeBreadCrumbs(
                boxPath,
                g,
                appendedItems=[
                    {
                        'kind': 'file',
                        'target': file,
                    },
                    {
                        'kind': 'link',
                        'target': None,
                        'name': 'Edit text',
                    }
                ],
            )
            return render_template(
                'edittextfile.html',
                user=user,
                form=form,
                fileActions=fileActions,
                fileInfo=fileInfo,
                pageTitle='"%s" file edit' % file.name,
                pageSubtitle='Click "Save" to commit the changes',
                breadCrumbs=pathBCrumbs,
            )