Example #1
0
def send_image(req):
    try:
        nid, file_ext = split_image_path(req.path)
    except ValueError:
        return 400

    version_id = version_id_from_req(req)

    node = get_node_or_version(nid, version_id, Content)

    # XXX: should be has_data_access instead, see #1135
    if node is None or not node.has_read_access():
        return 404

    image_files_by_mimetype = {
        f.mimetype: f
        for f in node.files.filter_by(filetype=u"image")
    }

    if not image_files_by_mimetype:
        # no image files? forget it...
        return 404

    def _send(fileobj):
        return req.sendFile(fileobj.abspath, fileobj.mimetype)

    client_mimetype = None

    if file_ext:
        # client wants a specific mimetype
        client_mimetype = node.MIMETYPE_FOR_EXTENSION.get(file_ext)
        if not client_mimetype:
            return httpstatus.HTTP_NOT_ACCEPTABLE

        image_file = image_files_by_mimetype.get(client_mimetype)
        if image_file:
            return _send(image_file)
        else:
            return httpstatus.HTTP_NOT_ACCEPTABLE

    # figure out what we want to send, in that order:
    server_preferred_mimetypes = preference_sorted_image_mimetypes(
        node, iterkeys(image_files_by_mimetype))

    accept_mimetypes = req.accept_mimetypes

    if accept_mimetypes:
        client_mimetype = req.accept_mimetypes.best_match(
            server_preferred_mimetypes)
        if client_mimetype:
            # file for mimetype must exist here
            image_file = image_files_by_mimetype[client_mimetype]
            return _send(image_file)
        else:
            return httpstatus.HTTP_NOT_ACCEPTABLE
    else:
        # client doesn't have any preferences, send our choice
        return _send(image_files_by_mimetype[server_preferred_mimetypes[0]])

    return 404
Example #2
0
def _send_thumbnail(thumb_type, req):
    try:
        nid = node_id_from_req_path(req)
    except ValueError:
        return 400

    version_id = version_id_from_req(req)

    node_or_version = get_node_or_version(nid, version_id, Data)

    if not node_or_version.has_read_access():
        return 404

    FileVersion = version_class(File)
    if version_id:
        version = node_or_version
        files = version.files.filter_by(
            filetype=thumb_type, transaction_id=version.transaction_id).all()
        if not files:
            # files may be None if in this version only metadata changed
            # then try previous transaction_ids
            files = version.files.filter(FileVersion.filetype==thumb_type, FileVersion.transaction_id<=version.transaction_id). \
                order_by(FileVersion.transaction_id.desc())
        for f in files:
            if f.exists:
                return _request_handler.sendFile(req, f.abspath, f.mimetype)

        ntype, schema = version.type, version.schema
    else:
        # no version id given
        # XXX: better to use scalar(), but we must ensure that we have no dupes first
        node = node_or_version
        for f in node.files.filter_by(filetype=thumb_type):
            if f.exists:
                return _request_handler.sendFile(req, f.abspath, f.mimetype)

        try:
            ntype, schema = node.type, node.schema
        except NoResultFound:
            return 404

    for p in _request_handler.getFileStorePaths("/img/"):
        for test in [
                "default_thumb_%s_%s.*" % (ntype, schema),
                "default_thumb_%s.*" % schema,
                "default_thumb_%s.*" % ntype
        ]:
            fps = glob.glob(os.path.join(p, test))
            if fps:
                thumb_mimetype, thumb_type = utils.utils.getMimeType(fps[0])
                return _request_handler.sendFile(req,
                                                 fps[0],
                                                 thumb_mimetype,
                                                 force=1)

    return _request_handler.sendFile(req,
                                     config.basedir +
                                     "/web/img/questionmark.png",
                                     "image/png",
                                     force=1)
Example #3
0
def send_image(req):
    try:
        nid, file_ext = split_image_path(req.path)
    except ValueError:
        return 400

    version_id = version_id_from_req(req)

    node = get_node_or_version(nid, version_id, Content)

    # XXX: should be has_data_access instead, see #1135
    if node is None or not node.has_read_access():
        return 404

    image_files_by_mimetype = {f.mimetype: f for f in node.files.filter_by(filetype=u"image")}

    if not image_files_by_mimetype:
        # no image files? forget it...
        return 404

    def _send(fileobj):
        return req.sendFile(fileobj.abspath, fileobj.mimetype)

    client_mimetype = None

    if file_ext:
        # client wants a specific mimetype
        client_mimetype = node.MIMETYPE_FOR_EXTENSION.get(file_ext)
        if not client_mimetype:
            return httpstatus.HTTP_NOT_ACCEPTABLE

        image_file = image_files_by_mimetype.get(client_mimetype)
        if image_file:
            return _send(image_file)
        else:
            return httpstatus.HTTP_NOT_ACCEPTABLE

    # figure out what we want to send, in that order:
    server_preferred_mimetypes = preference_sorted_image_mimetypes(node, iterkeys(image_files_by_mimetype))

    accept_mimetypes = req.accept_mimetypes

    if accept_mimetypes:
        client_mimetype = req.accept_mimetypes.best_match(server_preferred_mimetypes)
        if client_mimetype:
            # file for mimetype must exist here
            image_file = image_files_by_mimetype[client_mimetype]
            return _send(image_file)
        else:
            return httpstatus.HTTP_NOT_ACCEPTABLE
    else:
        # client doesn't have any preferences, send our choice
        return _send(image_files_by_mimetype[server_preferred_mimetypes[0]])

    return 404
Example #4
0
def _send_thumbnail(thumb_type, req):
    try:
        nid = node_id_from_req_path(req)
    except ValueError:
        return 400


    version_id = version_id_from_req(req)

    node_or_version = get_node_or_version(nid, version_id, Data)

    if not node_or_version.has_read_access():
        return 404

    FileVersion = version_class(File)
    if version_id:
        version = node_or_version
        files = version.files.filter_by(filetype=thumb_type, transaction_id=version.transaction_id).all()
        if not files:
            # files may be None if in this version only metadata changed
            # then try previous transaction_ids
            files = version.files.filter(FileVersion.filetype==thumb_type, FileVersion.transaction_id<=version.transaction_id). \
                order_by(FileVersion.transaction_id.desc())
        for f in files:
            if f.exists:
                return req.sendFile(f.abspath, f.mimetype)

        ntype, schema = version.type, version.schema
    else:
        # no version id given
        # XXX: better to use scalar(), but we must ensure that we have no dupes first
        node = node_or_version
        for f in node.files.filter_by(filetype=thumb_type):
            if f.exists:
                return req.sendFile(f.abspath, f.mimetype)

        try:
            ntype, schema = node.type, node.schema
        except NoResultFound:
            return 404

    for p in athana.getFileStorePaths("/img/"):
        for test in ["default_thumb_%s_%s.*" % (ntype, schema),
                     "default_thumb_%s.*" % schema,
                     "default_thumb_%s.*" % ntype]:
            fps = glob.glob(os.path.join(p, test))
            if fps:
                thumb_mimetype, thumb_type = utils.utils.getMimeType(fps[0])
                return req.sendFile(fps[0], thumb_mimetype, force=1)

    return req.sendFile(config.basedir + "/web/img/questionmark.png", "image/png", force=1)
Example #5
0
def send_attfile(req):
    """send single attachment file to user"""
    parts = req.path[9:].split('/')

    if len(parts) < 2:
        return 400

    nid = userinput.string_to_int(parts[0])
    if nid is None:
        return 400

    version_id = version_id_from_req(req)

    node = get_node_or_version(nid, version_id, Data)

    # XXX: why do we want to send attachments from containers?
    if (node is None
            or isinstance(node, Container) and not node.has_read_access()
            or isinstance(node, Content) and not node.has_data_access()):
        return 404

    paths = ["/".join(parts[1:]), "/".join(parts[1:-1])]
    fileobjs = [fo for fo in node.files if fo.path in paths]

    if not fileobjs:
        return 404

    fileobj = fileobjs[0]

    if fileobj.mimetype == u'inode/directory':
        # files in attachment directory cannot be found in node.files
        # so send file directly as it was made in mysql
        filename = clean_path("/".join(parts[1:]))
        path = os.path.join(config.get("paths.datadir"), filename)
        mime, type = getMimeType(filename)
        if (get_filesize(filename) > 16 * 1048576):
            req.reply_headers[
                "Content-Disposition"] = 'attachment; filename="{}"'.format(
                    filename)

        return req.sendFile(path, mime)

    if (fileobj.size > 16 * 1048576):
        req.reply_headers[
            "Content-Disposition"] = u'attachment; filename="{}"'.format(
                fileobj.base_name).encode('utf8')

    return req.sendFile(fileobj.abspath, fileobj.mimetype)
Example #6
0
def send_attachment(req):
    try:
        nid = node_id_from_req_path(req)
        version_id = version_id_from_req(req)
    except ValueError:
        return 400

    node = get_node_or_version(nid, version_id, Data)

    if (node is None
            or isinstance(node, Container) and not node.has_read_access()
            or isinstance(node, Content) and not node.has_data_access()):
        return 404

    attachment_file = node.files.filter_by(filetype=u"attachment").first()
    if attachment_file is not None:
        # filename is attachment.zip
        sendZipFile(req, file.abspath)
Example #7
0
def send_attachment(req):
    try:
        nid = node_id_from_req_path(req)
        version_id = version_id_from_req(req)
    except ValueError:
        return 400

    node = get_node_or_version(nid, version_id, Data)

    if (node is None
            or isinstance(node, Container) and not node.has_read_access()
            or isinstance(node, Content) and not node.has_data_access()):
        return 404

    attachment_file = node.files.filter_by(filetype=u"attachment").first()
    if attachment_file is not None:
        # filename is attachment.zip
        sendZipFile(req, file.abspath)
Example #8
0
def send_attfile(req):
    """send single attachment file to user"""
    parts = req.path[9:].split('/')

    if len(parts) < 2:
        return 400

    nid = userinput.string_to_int(parts[0])
    if nid is None:
        return 400

    version_id = version_id_from_req(req)

    node = get_node_or_version(nid, version_id, Data)

    # XXX: why do we want to send attachments from containers?
    if (node is None
            or isinstance(node, Container) and not node.has_read_access()
            or isinstance(node, Content) and not node.has_data_access()):
        return 404

    paths = ["/".join(parts[1:]), "/".join(parts[1:-1])]
    fileobjs = [fo for fo in node.files if fo.path in paths]

    if not fileobjs:
        return 404

    fileobj = fileobjs[0]

    if fileobj.mimetype == u'inode/directory':
        # files in attachment directory cannot be found in node.files
        # so send file directly as it was made in mysql
        filename = clean_path("/".join(parts[1:]))
        path = os.path.join(config.get("paths.datadir"), filename)
        mime, type = getMimeType(filename)
        if (get_filesize(filename) > 16 * 1048576):
            req.reply_headers["Content-Disposition"] = 'attachment; filename="{}"'.format(filename)

        return req.sendFile(path, mime)

    if (fileobj.size > 16 * 1048576):
        req.reply_headers["Content-Disposition"] = u'attachment; filename="{}"'.format(fileobj.base_name).encode('utf8')

    return req.sendFile(fileobj.abspath, fileobj.mimetype)
Example #9
0
def send_original_file(req):
    try:
        nid = node_id_from_req_path(req)
    except ValueError:
        return 400

    version_id = version_id_from_req(req)

    node = get_node_or_version(nid, version_id, Data)

    if node is None or not node.has_data_access():
        return 404

    original_filetype = node.get_original_filetype()
    original_file = node.files.filter_by(filetype=original_filetype).scalar()
    if original_file is not None:
        return req.sendFile(original_file.abspath, original_file.mimetype)

    return 404
Example #10
0
def send_original_file(req):
    try:
        nid = node_id_from_req_path(req)
    except ValueError:
        return 400

    version_id = version_id_from_req(req)

    node = get_node_or_version(nid, version_id, Data)

    if node is None or not node.has_data_access():
        return 404

    original_filetype = node.get_original_filetype()
    original_file = node.files.filter_by(filetype=original_filetype).scalar()
    if original_file is not None:
        return req.sendFile(original_file.abspath, original_file.mimetype)

    return 404
Example #11
0
def _send_file_with_type(filetype, mimetype, req, checkonly=False):
    try:
        nid = node_id_from_req_path(req)
    except ValueError:
        return 400

    version_id = version_id_from_req(req)
    node = get_node_or_version(nid, version_id, Content)

    if node is None or not node.has_data_access():
        return 404

    fileobj = None
    file_query = node.files.filter_by(filetype=filetype)
    # if version_id == u"published":
    if version_id:
        file_query = file_query.filter_by(transaction_id=node.transaction_id)
        fileobj = file_query.scalar()
        # fileobj may be None if in this version only metadata changed
        # then try previous transaction_ids
        if not fileobj:
            FileVersion = version_class(File)
            # this a long lasting query
            file_query = node.files.filter_by(filetype=filetype)
            fileobj = file_query.filter(FileVersion.transaction_id <= node.transaction_id).\
                order_by(FileVersion.transaction_id.desc()).first()
    if mimetype:
        file_query = file_query.filter_by(mimetype=mimetype)

    if not fileobj:
        fileobj = file_query.scalar()
    if fileobj is not None:
        if checkonly:
            return 200
        return _request_handler.sendFile(req, fileobj.abspath,
                                         fileobj.mimetype)

    return 404
Example #12
0
def _send_file_with_type(filetype, mimetype, req, checkonly=False):
    try:
        nid = node_id_from_req_path(req)
    except ValueError:
        return 400

    version_id = version_id_from_req(req)
    node = get_node_or_version(nid, version_id, Content)

    if node is None or not node.has_data_access():
        return 404

    fileobj = None
    file_query = node.files.filter_by(filetype=filetype)
    # if version_id == u"published":
    if version_id:
        file_query = file_query.filter_by(transaction_id=node.transaction_id)
        fileobj = file_query.scalar()
        # fileobj may be None if in this version only metadata changed
        # then try previous transaction_ids
        if not fileobj:
            FileVersion = version_class(File)
            # this a long lasting query
            file_query = node.files.filter_by(filetype=filetype)
            fileobj = file_query.filter(FileVersion.transaction_id <= node.transaction_id).\
                order_by(FileVersion.transaction_id.desc()).first()
    if mimetype:
        file_query = file_query.filter_by(mimetype=mimetype)

    if not fileobj:
        fileobj = file_query.scalar()
    if fileobj is not None:
        if checkonly:
            return 200
        return req.sendFile(fileobj.abspath, fileobj.mimetype)

    return 404
Example #13
0
def send_file(req):
    parts = splitpath(req.path)
    if len(parts) != 2:
        return 400

    nidstr, filename = parts
    if nidstr.endswith("_transfer.zip"):
        nidstr = nidstr[:-13]

    nid = userinput.string_to_int(nidstr)
    if nid is None:
        return 400

    version_id = version_id_from_req(req)

    node = get_node_or_version(nid, version_id)

    if (node is None
            or isinstance(node, Container) and not node.has_read_access()
            or isinstance(node, Content) and not node.has_data_access()):
        return 404

    def _send_attachment(filepath, mimetype):
        file_ext = os.path.splitext(filepath)[1]
        if existMetaField(node.schema, u'nodename'):
            display_file_name = u'{}{}'.format(os.path.splitext(os.path.basename(node.name))[0], file_ext)
        else:
            display_file_name = filename
        try:
            display_file_name.encode('ascii')
        except UnicodeEncodeError:
            req.reply_headers["Content-Disposition"] = u'attachment; filename="{0}"; filename*=UTF-8\'\'{0}'.\
                format(quote(display_file_name.encode('utf8')))
        else:
            req.reply_headers["Content-Disposition"] = u'attachment; filename="{}"'.format(display_file_name)
        return req.sendFile(filepath, mimetype)

    if filename is None:
        # build zip-file and return it
        with tempfile.NamedTemporaryFile() as tmpfile:
            files_written = build_transferzip(tmpfile, node)
            if files_written == 0:
                return 404
            # don't enable nginx x_accel_redirect for temporary files
            return req.sendFile(tmpfile.name, "application/zip", nginx_x_accel_redirect_enabled=False)

    # try full filename
    for f in node.files:
        if f.base_name == filename:
            return _send_attachment(f.abspath, f.mimetype)

    archive = get_archive_for_node(node)
    if archive:
        filepath = archive.get_local_filepath(node)
        mimetype, _ = getMimeType(filepath)
        return _send_attachment(filepath, mimetype)

    else:
        # try only extension
        file_ext = os.path.splitext(filename)[1]
        for f in node.files:
            if os.path.splitext(f.base_name)[1] == file_ext and f.filetype in [u'document', u'original', u'mp3']:
                logg.warn("serving file %s for node %s only by matched extension", f.path, node.id)
                return _send_attachment(f.abspath, f.mimetype)

    return 404
Example #14
0
def send_file(req):
    parts = splitpath(req.path)
    if len(parts) != 2:
        return 400

    nidstr, filename = parts
    if nidstr.endswith("_transfer.zip"):
        nidstr = nidstr[:-13]

    nid = userinput.string_to_int(nidstr)
    if nid is None:
        return 400

    version_id = version_id_from_req(req)

    node = get_node_or_version(nid, version_id)

    if (node is None
            or isinstance(node, Container) and not node.has_read_access()
            or isinstance(node, Content) and not node.has_data_access()):
        return 404

    def _send_attachment(filepath, mimetype):
        file_ext = os.path.splitext(filepath)[1]
        if existMetaField(node.schema, u'nodename'):
            display_file_name = u'{}{}'.format(
                os.path.splitext(os.path.basename(node.name))[0], file_ext)
        else:
            display_file_name = filename
        req.reply_headers[
            "Content-Disposition"] = u'attachment; filename="{}"'.format(
                display_file_name)
        return req.sendFile(filepath, mimetype)

    if filename is None:
        # build zip-file and return it
        with tempfile.NamedTemporaryFile() as tmpfile:
            files_written = build_transferzip(tmpfile, node)
            if files_written == 0:
                return 404
            return req.sendFile(tmpfile.name, "application/zip")

    # try full filename
    for f in node.files:
        if f.base_name == filename:
            return _send_attachment(f.abspath, f.mimetype)

    archive = get_archive_for_node(node)
    if archive:
        filepath = archive.get_local_filepath(node)
        mimetype, _ = getMimeType(filepath)
        return _send_attachment(filepath, mimetype)

    else:
        # try only extension
        file_ext = os.path.splitext(filename)[1]
        for f in node.files:
            if os.path.splitext(f.base_name)[1] == file_ext and f.filetype in [
                    u'document', u'original', u'mp3'
            ]:
                logg.warn(
                    "serving file %s for node %s only by matched extension",
                    f.path, node.id)
                return _send_attachment(f.abspath, f.mimetype)

    return 404