Exemplo n.º 1
0
def download_file(request, repo_id, obj_id):
    """Download file.

    Arguments:
    - `request`:
    - `repo_id`:
    - `obj_id`:
    """
    username = request.user.username
    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    if repo.encrypted and not seafile_api.is_password_set(repo_id, username):
        return HttpResponseRedirect(reverse('repo', args=[repo_id]))

    # If vistor's file shared token in url params matches the token in db,
    # then we know the vistor is from file shared link.
    share_token = request.GET.get('t', '')
    fileshare = FileShare.objects.get(
        token=share_token) if share_token else None
    shared_by = None
    if fileshare:
        from_shared_link = True
        shared_by = fileshare.username
    else:
        from_shared_link = False

    if from_shared_link:
        # check whether owner's traffic over the limit
        if user_traffic_over_limit(fileshare.username):
            messages.error(
                request,
                _(u'Unable to access file: share link traffic is used up.'))
            next = request.META.get('HTTP_REFERER', settings.SITE_ROOT)
            return HttpResponseRedirect(next)

    # Permission check and generate download link
    path = request.GET.get('p', '')
    if check_repo_access_permission(repo_id, request.user) or \
            get_file_access_permission(repo_id, path, username) or from_shared_link:
        # Get a token to access file
        token = seafserv_rpc.web_get_access_token(repo_id, obj_id, 'download',
                                                  username)
    else:
        messages.error(request, _(u'Unable to download file'))
        next = request.META.get('HTTP_REFERER', settings.SITE_ROOT)
        return HttpResponseRedirect(next)

    # send stats message
    if from_shared_link:
        try:
            file_size = seafile_api.get_file_size(repo.store_id, repo.version,
                                                  obj_id)
            send_message(
                'seahub.stats', 'file-download\t%s\t%s\t%s\t%s' %
                (repo.id, shared_by, obj_id, file_size))
        except Exception, e:
            logger.error('Error when sending file-download message: %s' %
                         str(e))
Exemplo n.º 2
0
def view_shared_file(request, token):
    """
    Preview file via shared link.
    """
    assert token is not None    # Checked by URLconf

    try:
        fileshare = FileShare.objects.get(token=token)
    except FileShare.DoesNotExist:
        raise Http404

    shared_by = fileshare.username
    repo_id = fileshare.repo_id
    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    path = fileshare.path.rstrip('/') # Normalize file path 
    obj_id = seafile_api.get_file_id_by_path(repo_id, path)
    if not obj_id:
        return render_error(request, _(u'File does not exist'))
    file_size = seafile_api.get_file_size(obj_id)
    
    filename = os.path.basename(path)
    filetype, fileext = get_file_type_and_ext(filename)
    access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id,
                                                     'view', '')
    raw_path = gen_file_get_url(access_token, filename)
    inner_path = gen_inner_file_get_url(access_token, filename)

    # get file content
    ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '',
                'file_encoding_list': [], 'html_exists': False,
                'filetype': filetype}
    fsize = get_file_size(obj_id)
    exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype)
    if exceeds_limit:
        err = err_msg
    else:
        """Choose different approach when dealing with different type of file."""

        if is_textual_file(file_type=filetype):
            handle_textual_file(request, filetype, inner_path, ret_dict)
        elif filetype == DOCUMENT:
            handle_document(inner_path, obj_id, fileext, ret_dict)
        elif filetype == PDF:
            handle_pdf(inner_path, obj_id, fileext, ret_dict)

        # Increase file shared link view_cnt, this operation should be atomic
        fileshare.view_cnt = F('view_cnt') + 1
        fileshare.save()

        # send statistic messages
        if ret_dict['filetype'] != 'Unknown':
            try:
                obj_size = seafserv_threaded_rpc.get_file_size(obj_id)
                send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \
                             (repo.id, shared_by, obj_id, obj_size))
            except SearpcError, e:
                logger.error('Error when sending file-view message: %s' % str(e))
Exemplo n.º 3
0
def view_shared_file(request, token):
    """
    Preview file via shared link.
    """
    assert token is not None    # Checked by URLconf

    try:
        fileshare = FileShare.objects.get(token=token)
    except FileShare.DoesNotExist:
        raise Http404

    shared_by = fileshare.username
    repo_id = fileshare.repo_id
    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    path = fileshare.path.rstrip('/') # Normalize file path 
    obj_id = seafile_api.get_file_id_by_path(repo_id, path)
    if not obj_id:
        return render_error(request, _(u'File does not exist'))
    file_size = seafile_api.get_file_size(obj_id)
    
    filename = os.path.basename(path)
    filetype, fileext = get_file_type_and_ext(filename)
    access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id,
                                                     'view', '')
    raw_path = gen_file_get_url(access_token, filename)
    inner_path = gen_inner_file_get_url(access_token, filename)

    # get file content
    ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '',
                'file_encoding_list': [], 'html_exists': False,
                'filetype': filetype}
    fsize = get_file_size(obj_id)
    exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype)
    if exceeds_limit:
        err = err_msg
    else:
        """Choose different approach when dealing with different type of file."""

        if is_textual_file(file_type=filetype):
            handle_textual_file(request, filetype, inner_path, ret_dict)
        elif filetype == DOCUMENT:
            handle_document(inner_path, obj_id, fileext, ret_dict)
        elif filetype == PDF:
            handle_pdf(inner_path, obj_id, fileext, ret_dict)

        # Increase file shared link view_cnt, this operation should be atomic
        fileshare.view_cnt = F('view_cnt') + 1
        fileshare.save()

        # send statistic messages
        if ret_dict['filetype'] != 'Unknown':
            try:
                obj_size = seafserv_threaded_rpc.get_file_size(obj_id)
                send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \
                             (repo.id, shared_by, obj_id, obj_size))
            except SearpcError, e:
                logger.error('Error when sending file-view message: %s' % str(e))
Exemplo n.º 4
0
Arquivo: file.py Projeto: swpd/seahub
def view_file_via_shared_dir(request, token):
    assert token is not None    # Checked by URLconf

    try:
        fileshare = FileShare.objects.get(token=token)
    except FileShare.DoesNotExist:
        raise Http404

    shared_by = fileshare.username
    repo_id = fileshare.repo_id
    repo = get_repo(repo_id)
    if not repo:
        raise Http404
    
    path = request.GET.get('p', '').rstrip('/')
    if not path:
        raise Http404
    if not path.startswith(fileshare.path): # Can not view upper dir of shared dir
        raise Http404
    zipped = gen_path_link(path, '')

    obj_id = seafile_api.get_file_id_by_path(repo_id, path)
    if not obj_id:
        return render_error(request, _(u'File does not exist'))
    file_size = seafile_api.get_file_size(obj_id)

    filename = os.path.basename(path)
    filetype, fileext = get_file_type_and_ext(filename)
    access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id,
                                                     'view', '')
    raw_path = gen_file_get_url(access_token, filename)
    inner_path = gen_inner_file_get_url(access_token, filename)

    # get file content
    ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '',
                'file_encoding_list': [], 'html_exists': False,
                'filetype': filetype}
    fsize = get_file_size(obj_id)
    exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype)
    if exceeds_limit:
        err = err_msg
    else:
        """Choose different approach when dealing with different type of file."""

        if is_textual_file(file_type=filetype):
            handle_textual_file(request, filetype, inner_path, ret_dict)
        elif filetype == DOCUMENT:
            handle_document(inner_path, obj_id, fileext, ret_dict)
        elif filetype == PDF:
            handle_pdf(inner_path, obj_id, fileext, ret_dict)

        # send statistic messages
        try:
            obj_size = seafserv_threaded_rpc.get_file_size(obj_id)
            send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \
                         (repo.id, shared_by, obj_id, obj_size))
        except SearpcError, e:
            logger.error('Error when sending file-view message: %s' % str(e))
Exemplo n.º 5
0
def download_file(request, repo_id, obj_id):
    """Download file.

    Arguments:
    - `request`:
    - `repo_id`:
    - `obj_id`:
    """
    username = request.user.username
    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    if repo.encrypted and not seafile_api.is_password_set(repo_id, username):
        return HttpResponseRedirect(reverse("repo", args=[repo_id]))

    # If vistor's file shared token in url params matches the token in db,
    # then we know the vistor is from file shared link.
    share_token = request.GET.get("t", "")
    fileshare = FileShare.objects.get(token=share_token) if share_token else None
    shared_by = None
    if fileshare:
        from_shared_link = True
        shared_by = fileshare.username
    else:
        from_shared_link = False

    if from_shared_link:
        # check whether owner's traffic over the limit
        if user_traffic_over_limit(fileshare.username):
            messages.error(request, _(u"Unable to access file: share link traffic is used up."))
            next = request.META.get("HTTP_REFERER", settings.SITE_ROOT)
            return HttpResponseRedirect(next)

    # Permission check and generate download link
    path = request.GET.get("p", "")
    if (
        check_repo_access_permission(repo_id, request.user)
        or get_file_access_permission(repo_id, path, username)
        or from_shared_link
    ):
        # Get a token to access file
        token = seafserv_rpc.web_get_access_token(repo_id, obj_id, "download", username)
    else:
        messages.error(request, _(u"Unable to download file"))
        next = request.META.get("HTTP_REFERER", settings.SITE_ROOT)
        return HttpResponseRedirect(next)

    # send stats message
    if from_shared_link:
        try:
            file_size = seafile_api.get_file_size(repo.store_id, repo.version, obj_id)
            send_message("seahub.stats", "file-download\t%s\t%s\t%s\t%s" % (repo.id, shared_by, obj_id, file_size))
        except Exception, e:
            logger.error("Error when sending file-download message: %s" % str(e))
Exemplo n.º 6
0
def send_draft_publish_msg(draft, username, path):
    """
    send draft publish msg to seafevents
    """

    repo_id = draft.origin_repo_id
    old_path = draft.draft_file_path

    msg = '%s\t%s\t%s\t%s\t%s\t%s' % ("publish", "draft", repo_id, username, path, old_path)
    msg_utf8 = msg.encode('utf-8')

    try:
        send_message('seahub.draft', msg_utf8)
    except Exception as e:
        logger.error("Error when sending draft publish message: %s" % str(e))
Exemplo n.º 7
0
def send_draft_publish_msg(draft, username, path):
    """
    send draft publish msg to seafevents
    """

    repo_id = draft.origin_repo_id
    old_path = draft.draft_file_path

    msg = '%s\t%s\t%s\t%s\t%s\t%s' % ("publish", "draft", repo_id, username,
                                      path, old_path)
    msg_utf8 = msg.encode('utf-8')

    try:
        send_message('seahub.draft', msg_utf8)
    except Exception as e:
        logger.error("Error when sending draft publish message: %s" % str(e))
Exemplo n.º 8
0
def send_perm_audit_msg(etype, from_user, to, repo_id, path, perm):
    """Send repo permission audit msg.

    Arguments:
    - `request`:
    - `repo`:
    - `obj_id`:
    - `dl_type`: web or api
    """
    msg = 'perm-update\t%s\t%s\t%s\t%s\t%s\t%s' % \
        (etype, from_user, to, repo_id, path, perm)
    msg_utf8 = msg.encode('utf-8')

    try:
        send_message('seahub.stats', msg_utf8)
    except Exception as e:
        logger.error("Error when sending perm-audit-%s message: %s" %
                     (etype, str(e)))
Exemplo n.º 9
0
def send_perm_audit_msg(etype, from_user, to, repo_id, path, perm):
    """Send repo permission audit msg.

    Arguments:
    - `request`:
    - `repo`:
    - `obj_id`:
    - `dl_type`: web or api
    """
    msg = 'perm-update\t%s\t%s\t%s\t%s\t%s\t%s' % \
        (etype, from_user, to, repo_id, path, perm)
    msg_utf8 = msg.encode('utf-8')

    try:
        send_message('seahub.stats', msg_utf8)
    except Exception as e:
        logger.error("Error when sending perm-audit-%s message: %s" %
                     (etype, str(e)))
Exemplo n.º 10
0
def send_perm_audit_msg(etype, from_user, to, repo_id, path, perm):
    """Send repo permission audit msg.

    Arguments:
    - `etype`: add/modify/delete-repo-perm
    - `from_user`: email
    - `to`: email or group_id or all(public)
    - `repo_id`: origin repo id
    - `path`: dir path
    - `perm`: r or rw
    """
    msg = "perm-update\t%s\t%s\t%s\t%s\t%s\t%s" % (etype, from_user, to, repo_id, path, perm)
    msg_utf8 = msg.encode("utf-8")

    try:
        seaserv.send_message("seahub.stats", msg_utf8)
    except Exception as e:
        logger.error("Error when sending perm-audit-%s message: %s" % (etype, str(e)))
Exemplo n.º 11
0
def _download_dir_from_share_link(request, fileshare, repo, real_path):
    # check whether owner's traffic over the limit
    if user_traffic_over_limit(fileshare.username):
        return render_error(
            request,
            _(u'Unable to access file: share link traffic is used up.'))

    shared_by = fileshare.username
    if real_path == '/':
        dirname = repo.name
    else:
        dirname = os.path.basename(real_path.rstrip('/'))

    dir_id = seafile_api.get_dir_id_by_path(repo.id, real_path)
    if not dir_id:
        return render_error(request,
                            _(u'Unable to download: folder not found.'))

    try:
        total_size = seaserv.seafserv_threaded_rpc.get_dir_size(
            repo.store_id, repo.version, dir_id)
    except Exception as e:
        logger.error(str(e))
        return render_error(request, _(u'Internal Error'))

    if total_size > seaserv.MAX_DOWNLOAD_DIR_SIZE:
        return render_error(
            request,
            _(u'Unable to download directory "%s": size is too large.') %
            dirname)

    token = seafile_api.get_fileserver_access_token(repo.id, dir_id,
                                                    'download-dir',
                                                    request.user.username)

    try:
        seaserv.send_message(
            'seahub.stats', 'dir-download\t%s\t%s\t%s\t%s' %
            (repo.id, shared_by, dir_id, total_size))
        send_file_access_msg(request, repo, real_path, 'web')
    except Exception as e:
        logger.error('Error when sending dir-download message: %s' % str(e))

    return HttpResponseRedirect(gen_file_get_url(token, dirname))
Exemplo n.º 12
0
def _download_dir_from_share_link(request, fileshare, repo, real_path):
    # check whether owner's traffic over the limit
    if user_traffic_over_limit(fileshare.username):
        return render_error(
            request,
            _(u'Unable to access file: share link traffic is used up.'))

    shared_by = fileshare.username
    if real_path == '/':
        dirname = repo.name
    else:
        dirname = os.path.basename(real_path.rstrip('/'))

    dir_id = seafile_api.get_dir_id_by_path(repo.id, real_path)
    if not dir_id:
        return render_error(request,
                            _(u'Unable to download: folder not found.'))

    try:
        total_size = seaserv.seafserv_threaded_rpc.get_dir_size(
            repo.store_id, repo.version, dir_id)
    except Exception as e:
        logger.error(str(e))
        return render_error(request, _(u'Internal Error'))

    if total_size > seaserv.MAX_DOWNLOAD_DIR_SIZE:
        return render_error(
            request,
            _(u'Unable to download directory "%s": size is too large.') %
            dirname)

    token = seafile_api.get_fileserver_access_token(
        repo.id, dir_id, 'download-dir', request.user.username)

    try:
        seaserv.send_message(
            'seahub.stats', 'dir-download\t%s\t%s\t%s\t%s' %
            (repo.id, shared_by, dir_id, total_size))
    except Exception as e:
        logger.error('Error when sending dir-download message: %s' % str(e))

    return HttpResponseRedirect(gen_file_get_url(token, dirname))
Exemplo n.º 13
0
def send_perm_audit_msg(etype, from_user, to, repo_id, path, perm):
    """Send repo permission audit msg.

    Arguments:
    - `etype`: add/modify/delete-repo-perm
    - `from_user`: email
    - `to`: email or group_id or all(public)
    - `repo_id`: origin repo id
    - `path`: dir path
    - `perm`: r or rw
    """
    msg = 'perm-update\t%s\t%s\t%s\t%s\t%s\t%s' % \
        (etype, from_user, to, repo_id, path, perm)
    msg_utf8 = msg.encode('utf-8')

    try:
        seaserv.send_message('seahub.stats', msg_utf8)
    except Exception as e:
        logger.error("Error when sending perm-audit-%s message: %s" %
                     (etype, str(e)))
Exemplo n.º 14
0
def send_file_download_msg(request, repo, path, dl_type):
    """Send file downlaod msg.
    
    Arguments:
    - `request`:
    - `repo`:
    - `obj_id`:
    - `dl_type`: web or api
    """
    username = request.user.username
    ip = get_remote_ip(request)
    user_agent = request.META.get("HTTP_USER_AGENT")

    msg = "file-download-%s\t%s\t%s\t%s\t%s\t%s\t%s" % (dl_type, username, ip, user_agent, repo.id, repo.name, path)
    msg_utf8 = msg.encode("utf-8")

    try:
        send_message("seahub.stats", msg_utf8)
    except Exception as e:
        logger.error("Error when sending file-download-%s message: %s" % (dl_type, str(e)))
Exemplo n.º 15
0
def send_file_download_msg(request, repo, path, dl_type):
    """Send file downlaod msg.
    
    Arguments:
    - `request`:
    - `repo`:
    - `obj_id`:
    - `dl_type`: web or api
    """
    username = request.user.username
    ip = get_remote_ip(request)
    user_agent = request.META.get("HTTP_USER_AGENT")

    msg = 'file-download-%s\t%s\t%s\t%s\t%s\t%s\t%s' % \
        (dl_type, username, ip, user_agent, repo.id, repo.name, path)
    msg_utf8 = msg.encode('utf-8')

    try:
        send_message('seahub.stats', msg_utf8)
    except Exception as e:
        logger.error("Error when sending file-download-%s message: %s" %
                     (dl_type, str(e)))
Exemplo n.º 16
0
def send_review_status_msg(request, review):
    """
    send review status change to seafevents
    """
    status = review.status.lower()
    if status not in ['open', 'finished', 'closed']:
        logger.warn('Invalid status in review status msg: %s' % status)
        return

    repo_id = review.origin_repo_id
    op_user = request.user.username
    review_id = review.id
    draft_flag = os.path.splitext(os.path.basename(
        review.draft_file_path))[0][-7:]
    if draft_flag == '(draft)':
        old_path = review.draft_file_path
        if status == 'finished':
            publish_path = posixpath.join(review.origin_file_uuid.parent_path,
                                          review.origin_file_uuid.filename)
        else:
            publish_path = None
    else:
        old_path = posixpath.join(review.origin_file_uuid.parent_path,
                                  review.origin_file_uuid.filename)
        publish_path = review.draft_file_path if status == 'finished' else None
    path = publish_path if publish_path else old_path

    creator = review.creator

    msg = '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s' % (
        status, repo_id, op_user, "review", path, review_id, old_path, creator)
    msg_utf8 = msg.encode('utf-8')

    try:
        send_message('seahub.review', msg_utf8)
    except Exception as e:
        logger.error("Error when sending %s message: %s" % (status, str(e)))
Exemplo n.º 17
0
def view_shared_file(request, token):
    """
    Preview file via shared link.
    """
    assert token is not None  # Checked by URLconf

    fileshare = FileShare.objects.get_valid_file_link_by_token(token)
    if fileshare is None:
        raise Http404

    if fileshare.is_encrypted():
        if not check_share_link_access(request.user.username, token):
            d = {
                'token': token,
                'view_name': 'view_shared_file',
            }
            if request.method == 'POST':
                post_values = request.POST.copy()
                post_values['enc_password'] = fileshare.password
                form = SharedLinkPasswordForm(post_values)
                d['form'] = form
                if form.is_valid():
                    # set cache for non-anonymous user
                    if request.user.is_authenticated():
                        set_share_link_access(request.user.username, token)
                else:
                    return render_to_response(
                        'share_access_validation.html',
                        d,
                        context_instance=RequestContext(request))
            else:
                return render_to_response(
                    'share_access_validation.html',
                    d,
                    context_instance=RequestContext(request))

    shared_by = fileshare.username
    repo_id = fileshare.repo_id
    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    path = fileshare.path.rstrip('/')  # Normalize file path
    obj_id = seafile_api.get_file_id_by_path(repo_id, path)
    if not obj_id:
        return render_error(request, _(u'File does not exist'))
    file_size = seafile_api.get_file_size(repo.store_id, repo.version, obj_id)

    filename = os.path.basename(path)
    filetype, fileext = get_file_type_and_ext(filename)
    access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id, 'view',
                                                     '')
    raw_path = gen_file_get_url(access_token, filename)
    inner_path = gen_inner_file_get_url(access_token, filename)

    # get file content
    ret_dict = {
        'err': '',
        'file_content': '',
        'encoding': '',
        'file_enc': '',
        'file_encoding_list': [],
        'html_exists': False,
        'filetype': filetype
    }
    exceeds_limit, err_msg = file_size_exceeds_preview_limit(
        file_size, filetype)
    if exceeds_limit:
        ret_dict['err'] = err_msg
    else:
        """Choose different approach when dealing with different type of file."""

        if is_textual_file(file_type=filetype):
            handle_textual_file(request, filetype, inner_path, ret_dict)
        elif filetype == DOCUMENT:
            handle_document(inner_path, obj_id, fileext, ret_dict)
        elif filetype == SPREADSHEET:
            handle_spreadsheet(inner_path, obj_id, fileext, ret_dict)
        elif filetype == OPENDOCUMENT:
            if file_size == 0:
                ret_dict['err'] = _(u'Invalid file format.')
        elif filetype == PDF:
            handle_pdf(inner_path, obj_id, fileext, ret_dict)

        # Increase file shared link view_cnt, this operation should be atomic
        fileshare.view_cnt = F('view_cnt') + 1
        fileshare.save()

        # send statistic messages
        if ret_dict['filetype'] != 'Unknown':
            try:
                send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \
                             (repo.id, shared_by, obj_id, file_size))
            except SearpcError, e:
                logger.error('Error when sending file-view message: %s' %
                             str(e))
Exemplo n.º 18
0
def view_file_via_shared_dir(request, token):
    assert token is not None    # Checked by URLconf

    fileshare = FileShare.objects.get_valid_file_link_by_token(token)
    if fileshare is None:
        raise Http404

    shared_by = fileshare.username
    repo_id = fileshare.repo_id
    repo = get_repo(repo_id)
    if not repo:
        raise Http404
    
    path = request.GET.get('p', '').rstrip('/')
    if not path:
        raise Http404
    if not path.startswith(fileshare.path): # Can not view upper dir of shared dir
        raise Http404
    zipped = gen_path_link(path, '')

    obj_id = seafile_api.get_file_id_by_path(repo_id, path)
    if not obj_id:
        return render_error(request, _(u'File does not exist'))
    file_size = seafile_api.get_file_size(repo.store_id, repo.version, obj_id)

    filename = os.path.basename(path)
    filetype, fileext = get_file_type_and_ext(filename)
    access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id,
                                                     'view', '')
    raw_path = gen_file_get_url(access_token, filename)
    inner_path = gen_inner_file_get_url(access_token, filename)

    img_prev = None
    img_next = None

    # get file content
    ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '',
                'file_encoding_list': [], 'html_exists': False,
                'filetype': filetype}
    exceeds_limit, err_msg = file_size_exceeds_preview_limit(file_size, filetype)
    if exceeds_limit:
        ret_dict['err'] = err_msg
    else:
        """Choose different approach when dealing with different type of file."""

        if is_textual_file(file_type=filetype):
            handle_textual_file(request, filetype, inner_path, ret_dict)
        elif filetype == DOCUMENT:
            handle_document(inner_path, obj_id, fileext, ret_dict)
        elif filetype == SPREADSHEET:
            handle_spreadsheet(inner_path, obj_id, fileext, ret_dict)
        elif filetype == PDF:
            handle_pdf(inner_path, obj_id, fileext, ret_dict)
        elif filetype == IMAGE:
            current_commit = get_commits(repo_id, 0, 1)[0]
            parent_dir = os.path.dirname(path)
            dirs = seafile_api.list_dir_by_commit_and_path(current_commit.repo_id,
                                                           current_commit.id, parent_dir)
            if not dirs:
                raise Http404

            img_list = []
            for dirent in dirs:
                if not stat.S_ISDIR(dirent.props.mode):
                    fltype, flext = get_file_type_and_ext(dirent.obj_name)
                    if fltype == 'Image':
                        img_list.append(dirent.obj_name)

            if len(img_list) > 1:
                img_list.sort(lambda x, y : cmp(x.lower(), y.lower()))
                cur_img_index = img_list.index(filename) 
                if cur_img_index != 0:
                    img_prev = posixpath.join(parent_dir, img_list[cur_img_index - 1])
                if cur_img_index != len(img_list) - 1:
                    img_next = posixpath.join(parent_dir, img_list[cur_img_index + 1])

        # send statistic messages
        if ret_dict['filetype'] != 'Unknown':
            try:
                send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \
                             (repo.id, shared_by, obj_id, file_size))
            except SearpcError, e:
                logger.error('Error when sending file-view message: %s' % str(e))
Exemplo n.º 19
0
def view_shared_file(request, token):
    """
    Preview file via shared link.
    """
    assert token is not None    # Checked by URLconf

    fileshare = FileShare.objects.get_valid_file_link_by_token(token)
    if fileshare is None:
        raise Http404

    if fileshare.is_encrypted():
        if not check_share_link_access(request.user.username, token):
            d = {'token': token, 'view_name': 'view_shared_file', }
            if request.method == 'POST':
                post_values = request.POST.copy()
                post_values['enc_password'] = fileshare.password
                form = SharedLinkPasswordForm(post_values)
                d['form'] = form
                if form.is_valid():
                    # set cache for non-anonymous user
                    if request.user.is_authenticated():
                        set_share_link_access(request.user.username, token)
                else:
                    return render_to_response('share_access_validation.html', d,
                                              context_instance=RequestContext(request))
            else:
                return render_to_response('share_access_validation.html', d,
                                          context_instance=RequestContext(request))
    
    shared_by = fileshare.username
    repo_id = fileshare.repo_id
    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    path = fileshare.path.rstrip('/') # Normalize file path 
    obj_id = seafile_api.get_file_id_by_path(repo_id, path)
    if not obj_id:
        return render_error(request, _(u'File does not exist'))
    file_size = seafile_api.get_file_size(repo.store_id, repo.version, obj_id)

    filename = os.path.basename(path)
    filetype, fileext = get_file_type_and_ext(filename)
    access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id,
                                                     'view', '')
    raw_path = gen_file_get_url(access_token, filename)
    inner_path = gen_inner_file_get_url(access_token, filename)

    # get file content
    ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '',
                'file_encoding_list': [], 'html_exists': False,
                'filetype': filetype}
    exceeds_limit, err_msg = file_size_exceeds_preview_limit(file_size, filetype)
    if exceeds_limit:
        ret_dict['err'] = err_msg
    else:
        """Choose different approach when dealing with different type of file."""

        if is_textual_file(file_type=filetype):
            handle_textual_file(request, filetype, inner_path, ret_dict)
        elif filetype == DOCUMENT:
            handle_document(inner_path, obj_id, fileext, ret_dict)
        elif filetype == SPREADSHEET:
            handle_spreadsheet(inner_path, obj_id, fileext, ret_dict)
        elif filetype == OPENDOCUMENT:
            if file_size == 0:
                ret_dict['err'] = _(u'Invalid file format.')
        elif filetype == PDF:
            handle_pdf(inner_path, obj_id, fileext, ret_dict)

        # Increase file shared link view_cnt, this operation should be atomic
        fileshare.view_cnt = F('view_cnt') + 1
        fileshare.save()

        # send statistic messages
        if ret_dict['filetype'] != 'Unknown':
            try:
                send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \
                             (repo.id, shared_by, obj_id, file_size))
            except SearpcError, e:
                logger.error('Error when sending file-view message: %s' % str(e))
Exemplo n.º 20
0
    def get(self, request):
        """ Return repos user can access.

        Permission checking:
        1. all authenticated user can perform this action.
        """

        filter_by = {
            'mine': False,
            'shared': False,
            'group': False,
            'public': False,
        }

        request_type_list = request.GET.getlist('type', "")
        if not request_type_list:
            # set all to True, no filter applied
            filter_by = filter_by.fromkeys(filter_by.iterkeys(), True)

        for request_type in request_type_list:
            request_type = request_type.strip()
            filter_by[request_type] = True

        email = request.user.username

        # Use dict to reduce memcache fetch cost in large for-loop.
        contact_email_dict = {}
        nickname_dict = {}

        org_id = None
        if is_org_context(request):
            org_id = request.user.org.org_id

        try:
            starred_repos = UserStarredFiles.objects.get_starred_repos_by_user(
                email)
            starred_repo_id_list = [item.repo_id for item in starred_repos]
        except Exception as e:
            logger.error(e)
            starred_repo_id_list = []

        repo_info_list = []
        if filter_by['mine']:

            if org_id:
                owned_repos = seafile_api.get_org_owned_repo_list(
                    org_id, email, ret_corrupted=True)
            else:
                owned_repos = seafile_api.get_owned_repo_list(
                    email, ret_corrupted=True)

            # Reduce memcache fetch ops.
            modifiers_set = set([x.last_modifier for x in owned_repos])
            for e in modifiers_set:
                if e not in contact_email_dict:
                    contact_email_dict[e] = email2contact_email(e)
                if e not in nickname_dict:
                    nickname_dict[e] = email2nickname(e)

            owned_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify))
            for r in owned_repos:

                # do not return virtual repos
                if r.is_virtual:
                    continue

                repo_info = {
                    "type":
                    "mine",
                    "repo_id":
                    r.id,
                    "repo_name":
                    r.name,
                    "owner_email":
                    email,
                    "owner_name":
                    email2nickname(email),
                    "owner_contact_email":
                    email2contact_email(email),
                    "last_modified":
                    timestamp_to_isoformat_timestr(r.last_modify),
                    "modifier_email":
                    r.last_modifier,
                    "modifier_name":
                    nickname_dict.get(r.last_modifier, ''),
                    "modifier_contact_email":
                    contact_email_dict.get(r.last_modifier, ''),
                    "size":
                    r.size,
                    "encrypted":
                    r.encrypted,
                    "permission":
                    'rw',  # Always have read-write permission to owned repo
                    "starred":
                    r.repo_id in starred_repo_id_list,
                    "status":
                    normalize_repo_status_code(r.status),
                }

                if is_pro_version() and ENABLE_STORAGE_CLASSES:
                    repo_info['storage_name'] = r.storage_name
                    repo_info['storage_id'] = r.storage_id

                repo_info_list.append(repo_info)

        if filter_by['shared']:

            if org_id:
                shared_repos = seafile_api.get_org_share_in_repo_list(
                    org_id, email, -1, -1)
            else:
                shared_repos = seafile_api.get_share_in_repo_list(
                    email, -1, -1)

            repos_with_admin_share_to = ExtraSharePermission.objects.\
                    get_repos_with_admin_permission(email)

            # Reduce memcache fetch ops.
            owners_set = set([x.user for x in shared_repos])
            modifiers_set = set([x.last_modifier for x in shared_repos])
            for e in owners_set | modifiers_set:
                if e not in contact_email_dict:
                    contact_email_dict[e] = email2contact_email(e)
                if e not in nickname_dict:
                    nickname_dict[e] = email2nickname(e)

            shared_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify))
            for r in shared_repos:

                owner_email = r.user

                group_name = ''
                is_group_owned_repo = False
                if '@seafile_group' in owner_email:
                    is_group_owned_repo = True
                    group_id = get_group_id_by_repo_owner(owner_email)
                    group_name = group_id_to_name(group_id)

                owner_name = group_name if is_group_owned_repo else \
                        nickname_dict.get(owner_email, '')
                owner_contact_email = '' if is_group_owned_repo else \
                        contact_email_dict.get(owner_email, '')

                repo_info = {
                    "type":
                    "shared",
                    "repo_id":
                    r.repo_id,
                    "repo_name":
                    r.repo_name,
                    "last_modified":
                    timestamp_to_isoformat_timestr(r.last_modify),
                    "modifier_email":
                    r.last_modifier,
                    "modifier_name":
                    nickname_dict.get(r.last_modifier, ''),
                    "modifier_contact_email":
                    contact_email_dict.get(r.last_modifier, ''),
                    "owner_email":
                    owner_email,
                    "owner_name":
                    owner_name,
                    "owner_contact_email":
                    owner_contact_email,
                    "size":
                    r.size,
                    "encrypted":
                    r.encrypted,
                    "permission":
                    r.permission,
                    "starred":
                    r.repo_id in starred_repo_id_list,
                    "status":
                    normalize_repo_status_code(r.status),
                }

                if r.repo_id in repos_with_admin_share_to:
                    repo_info['is_admin'] = True
                else:
                    repo_info['is_admin'] = False

                repo_info_list.append(repo_info)

        if filter_by['group']:

            if org_id:
                group_repos = seafile_api.get_org_group_repos_by_user(
                    email, org_id)
            else:
                group_repos = seafile_api.get_group_repos_by_user(email)

            group_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify))

            # Reduce memcache fetch ops.
            share_from_set = set([x.user for x in group_repos])
            modifiers_set = set([x.last_modifier for x in group_repos])
            for e in modifiers_set | share_from_set:
                if e not in contact_email_dict:
                    contact_email_dict[e] = email2contact_email(e)
                if e not in nickname_dict:
                    nickname_dict[e] = email2nickname(e)

            for r in group_repos:
                repo_info = {
                    "type":
                    "group",
                    "group_id":
                    r.group_id,
                    "group_name":
                    r.group_name,
                    "repo_id":
                    r.repo_id,
                    "repo_name":
                    r.repo_name,
                    "last_modified":
                    timestamp_to_isoformat_timestr(r.last_modify),
                    "modifier_email":
                    r.last_modifier,
                    "modifier_name":
                    nickname_dict.get(r.last_modifier, ''),
                    "modifier_contact_email":
                    contact_email_dict.get(r.last_modifier, ''),
                    "size":
                    r.size,
                    "encrypted":
                    r.encrypted,
                    "permission":
                    r.permission,
                    "starred":
                    r.repo_id in starred_repo_id_list,
                    "status":
                    normalize_repo_status_code(r.status),
                }
                repo_info_list.append(repo_info)

        if filter_by['public'] and request.user.permissions.can_view_org():
            public_repos = list_inner_pub_repos(request)

            # get repo id owner dict
            all_repo_owner = []
            repo_id_owner_dict = {}
            for repo in public_repos:
                repo_id = repo.repo_id
                if repo_id not in repo_id_owner_dict:
                    repo_owner = get_repo_owner(request, repo_id)
                    all_repo_owner.append(repo_owner)
                    repo_id_owner_dict[repo_id] = repo_owner

            # Reduce memcache fetch ops.
            owner_set = set(all_repo_owner)
            share_from_set = set([x.user for x in public_repos])
            modifiers_set = set([x.last_modifier for x in public_repos])
            for e in modifiers_set | share_from_set | owner_set:
                if e not in contact_email_dict:
                    contact_email_dict[e] = email2contact_email(e)
                if e not in nickname_dict:
                    nickname_dict[e] = email2nickname(e)

            for r in public_repos:
                repo_owner = repo_id_owner_dict[r.repo_id]
                repo_info = {
                    "type":
                    "public",
                    "repo_id":
                    r.repo_id,
                    "repo_name":
                    r.repo_name,
                    "last_modified":
                    timestamp_to_isoformat_timestr(r.last_modify),
                    "modifier_email":
                    r.last_modifier,
                    "modifier_name":
                    nickname_dict.get(r.last_modifier, ''),
                    "modifier_contact_email":
                    contact_email_dict.get(r.last_modifier, ''),
                    "owner_email":
                    repo_owner,
                    "owner_name":
                    nickname_dict.get(repo_owner, ''),
                    "owner_contact_email":
                    contact_email_dict.get(repo_owner, ''),
                    "size":
                    r.size,
                    "encrypted":
                    r.encrypted,
                    "permission":
                    r.permission,
                    "starred":
                    r.repo_id in starred_repo_id_list,
                    "status":
                    normalize_repo_status_code(r.status),
                }
                repo_info_list.append(repo_info)

        utc_dt = datetime.datetime.utcnow()
        timestamp = utc_dt.strftime('%Y-%m-%d %H:%M:%S')
        org_id = request.user.org.org_id if is_org_context(request) else -1
        try:
            send_message('seahub.stats',
                         'user-login\t%s\t%s\t%s' % (email, timestamp, org_id))
        except Exception as e:
            logger.error('Error when sending user-login message: %s' % str(e))

        return Response({'repos': repo_info_list})
Exemplo n.º 21
0
Arquivo: file.py Projeto: swpd/seahub
def view_file_via_shared_dir(request, token):
    assert token is not None  # Checked by URLconf

    try:
        fileshare = FileShare.objects.get(token=token)
    except FileShare.DoesNotExist:
        raise Http404

    shared_by = fileshare.username
    repo_id = fileshare.repo_id
    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    path = request.GET.get('p', '').rstrip('/')
    if not path:
        raise Http404
    if not path.startswith(
            fileshare.path):  # Can not view upper dir of shared dir
        raise Http404
    zipped = gen_path_link(path, '')

    obj_id = seafile_api.get_file_id_by_path(repo_id, path)
    if not obj_id:
        return render_error(request, _(u'File does not exist'))
    file_size = seafile_api.get_file_size(obj_id)

    filename = os.path.basename(path)
    filetype, fileext = get_file_type_and_ext(filename)
    access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id, 'view',
                                                     '')
    raw_path = gen_file_get_url(access_token, filename)
    inner_path = gen_inner_file_get_url(access_token, filename)

    # get file content
    ret_dict = {
        'err': '',
        'file_content': '',
        'encoding': '',
        'file_enc': '',
        'file_encoding_list': [],
        'html_exists': False,
        'filetype': filetype
    }
    fsize = get_file_size(obj_id)
    exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype)
    if exceeds_limit:
        err = err_msg
    else:
        """Choose different approach when dealing with different type of file."""

        if is_textual_file(file_type=filetype):
            handle_textual_file(request, filetype, inner_path, ret_dict)
        elif filetype == DOCUMENT:
            handle_document(inner_path, obj_id, fileext, ret_dict)
        elif filetype == PDF:
            handle_pdf(inner_path, obj_id, fileext, ret_dict)

        # send statistic messages
        try:
            obj_size = seafserv_threaded_rpc.get_file_size(obj_id)
            send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \
                         (repo.id, shared_by, obj_id, obj_size))
        except SearpcError, e:
            logger.error('Error when sending file-view message: %s' % str(e))
Exemplo n.º 22
0
    def get(self, request, token):
        """ Get FileServer download url of the shared file/dir.

        Permission checking:
        1. only admin can perform this action.
        """

        try:
            sharelink = FileShare.objects.get(token=token)
        except FileShare.DoesNotExist:
            error_msg = 'Share link %s not found.' % token
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        repo_id = sharelink.repo_id
        repo = seafile_api.get_repo(repo_id)
        if not repo:
            error_msg = 'Library not found.'
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        result = {}
        obj_path = sharelink.path
        if sharelink.s_type == 'f':
            # download shared file
            obj_id = seafile_api.get_file_id_by_path(repo_id, obj_path)
            if not obj_id:
                error_msg = 'File not found.'
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            try:
                # `username` parameter only used for encrypted repo
                download_token = seafile_api.get_fileserver_access_token(
                    repo_id,
                    obj_id,
                    'download',
                    sharelink.username,
                    use_onetime=False)
            except Exception as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            if not download_token:
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                 error_msg)

            obj_name = os.path.basename(obj_path.rstrip('/'))
            result['download_link'] = gen_file_get_url(download_token,
                                                       obj_name)
        else:
            # download (sub) file/folder in shared dir
            obj_id = seafile_api.get_dir_id_by_path(repo_id, obj_path)
            if not obj_id:
                error_msg = 'Folder not found.'
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            download_type = request.GET.get('type', None)
            if not download_type or download_type not in ('file', 'folder'):
                error_msg = 'type invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            req_path = request.GET.get('path', None)
            if not req_path:
                error_msg = 'path invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if req_path == '/':
                real_path = obj_path
            else:
                real_path = posixpath.join(obj_path, req_path.strip('/'))

            if download_type == 'file':
                # download sub file in shared dir
                real_obj_id = seafile_api.get_file_id_by_path(
                    repo_id, real_path)
                if not real_obj_id:
                    error_msg = 'File not found.'
                    return api_error(status.HTTP_404_NOT_FOUND, error_msg)

                try:
                    download_token = seafile_api.get_fileserver_access_token(
                        repo_id,
                        real_obj_id,
                        'download',
                        sharelink.username,
                        use_onetime=False)
                except Exception as e:
                    logger.error(e)
                    error_msg = 'Internal Server Error'
                    return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                     error_msg)

                if not download_token:
                    error_msg = 'Internal Server Error'
                    return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                     error_msg)

                file_name = os.path.basename(real_path.rstrip('/'))
                result['download_link'] = gen_file_get_url(
                    download_token, file_name)
            else:
                # download sub folder in shared dir
                if real_path[-1] != '/':
                    real_path += '/'

                real_obj_id = seafile_api.get_dir_id_by_path(
                    repo_id, real_path)
                if not real_obj_id:
                    error_msg = 'Folder %s not found.' % req_path
                    return api_error(status.HTTP_404_NOT_FOUND, error_msg)

                dir_name = repo.name if real_path == '/' else \
                        os.path.basename(real_path.rstrip('/'))

                dir_size = seafile_api.get_dir_size(repo.store_id,
                                                    repo.version, real_obj_id)
                if dir_size > seaserv.MAX_DOWNLOAD_DIR_SIZE:
                    error_msg = 'Unable to download directory "%s": size is too large.' % dir_name
                    return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

                # get file server access token
                is_windows = 0
                if is_windows_operating_system(request):
                    is_windows = 1

                fake_obj_id = {
                    'obj_id': real_obj_id,
                    'dir_name': dir_name,
                    'is_windows': is_windows
                }

                try:
                    zip_token = seafile_api.get_fileserver_access_token(
                        repo_id,
                        json.dumps(fake_obj_id),
                        'download-dir',
                        sharelink.username,
                        use_onetime=False)
                except Exception as e:
                    logger.error(e)
                    error_msg = 'Internal Server Error'
                    return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                                     error_msg)

                try:
                    # used for file audit
                    send_file_access_msg(request, repo, real_path,
                                         'share-link')
                    # used for traffic
                    seaserv.send_message(
                        'seahub.stats', 'dir-download\t%s\t%s\t%s\t%s' %
                        (repo_id, sharelink.username, real_obj_id, dir_size))
                except Exception as e:
                    logger.error(e)

                result['download_link'] = gen_dir_zip_download_url(zip_token)

        return Response(result)
Exemplo n.º 23
0
def view_file_via_shared_dir(request, token):
    assert token is not None  # Checked by URLconf

    fileshare = FileShare.objects.get_valid_file_link_by_token(token)
    if fileshare is None:
        raise Http404

    shared_by = fileshare.username
    repo_id = fileshare.repo_id
    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    path = request.GET.get('p', '').rstrip('/')
    if not path:
        raise Http404
    if not path.startswith(
            fileshare.path):  # Can not view upper dir of shared dir
        raise Http404
    zipped = gen_path_link(path, '')

    obj_id = seafile_api.get_file_id_by_path(repo_id, path)
    if not obj_id:
        return render_error(request, _(u'File does not exist'))
    file_size = seafile_api.get_file_size(repo.store_id, repo.version, obj_id)

    filename = os.path.basename(path)
    filetype, fileext = get_file_type_and_ext(filename)
    access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id, 'view',
                                                     '')
    raw_path = gen_file_get_url(access_token, filename)
    inner_path = gen_inner_file_get_url(access_token, filename)

    img_prev = None
    img_next = None

    # get file content
    ret_dict = {
        'err': '',
        'file_content': '',
        'encoding': '',
        'file_enc': '',
        'file_encoding_list': [],
        'html_exists': False,
        'filetype': filetype
    }
    exceeds_limit, err_msg = file_size_exceeds_preview_limit(
        file_size, filetype)
    if exceeds_limit:
        ret_dict['err'] = err_msg
    else:
        """Choose different approach when dealing with different type of file."""

        if is_textual_file(file_type=filetype):
            handle_textual_file(request, filetype, inner_path, ret_dict)
        elif filetype == DOCUMENT:
            handle_document(inner_path, obj_id, fileext, ret_dict)
        elif filetype == SPREADSHEET:
            handle_spreadsheet(inner_path, obj_id, fileext, ret_dict)
        elif filetype == PDF:
            handle_pdf(inner_path, obj_id, fileext, ret_dict)
        elif filetype == IMAGE:
            current_commit = get_commits(repo_id, 0, 1)[0]
            parent_dir = os.path.dirname(path)
            dirs = seafile_api.list_dir_by_commit_and_path(
                current_commit.repo_id, current_commit.id, parent_dir)
            if not dirs:
                raise Http404

            img_list = []
            for dirent in dirs:
                if not stat.S_ISDIR(dirent.props.mode):
                    fltype, flext = get_file_type_and_ext(dirent.obj_name)
                    if fltype == 'Image':
                        img_list.append(dirent.obj_name)

            if len(img_list) > 1:
                img_list.sort(lambda x, y: cmp(x.lower(), y.lower()))
                cur_img_index = img_list.index(filename)
                if cur_img_index != 0:
                    img_prev = posixpath.join(parent_dir,
                                              img_list[cur_img_index - 1])
                if cur_img_index != len(img_list) - 1:
                    img_next = posixpath.join(parent_dir,
                                              img_list[cur_img_index + 1])

        # send statistic messages
        if ret_dict['filetype'] != 'Unknown':
            try:
                send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \
                             (repo.id, shared_by, obj_id, file_size))
            except SearpcError, e:
                logger.error('Error when sending file-view message: %s' %
                             str(e))
Exemplo n.º 24
0
    def get(self, request):
        """ Return repos user can access.

        Permission checking:
        1. all authenticated user can perform this action.
        """

        filter_by = {
            'mine': False,
            'shared': False,
            'group': False,
            'public': False,
        }

        request_type_list = request.GET.getlist('type', "")
        if not request_type_list:
            # set all to True, no filter applied
            filter_by = filter_by.fromkeys(filter_by.iterkeys(), True)

        for request_type in request_type_list:
            request_type = request_type.strip()
            filter_by[request_type] = True

        email = request.user.username

        # Use dict to reduce memcache fetch cost in large for-loop.
        contact_email_dict = {}
        nickname_dict = {}

        org_id = None
        if is_org_context(request):
            org_id = request.user.org.org_id

        try:
            starred_repos = UserStarredFiles.objects.get_starred_repos_by_user(email)
            starred_repo_id_list = [item.repo_id for item in starred_repos]
        except Exception as e:
            logger.error(e)
            starred_repo_id_list = []

        repo_info_list = []
        if filter_by['mine']:

            if org_id:
                owned_repos = seafile_api.get_org_owned_repo_list(org_id,
                        email, ret_corrupted=True)
            else:
                owned_repos = seafile_api.get_owned_repo_list(email,
                        ret_corrupted=True)

            # Reduce memcache fetch ops.
            modifiers_set = set([x.last_modifier for x in owned_repos])
            for e in modifiers_set:
                if e not in contact_email_dict:
                    contact_email_dict[e] = email2contact_email(e)
                if e not in nickname_dict:
                    nickname_dict[e] = email2nickname(e)

            owned_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify))
            for r in owned_repos:

                # do not return virtual repos
                if r.is_virtual:
                    continue

                repo_info = {
                    "type": "mine",
                    "repo_id": r.id,
                    "repo_name": r.name,
                    "owner_email": email,
                    "owner_name": email2nickname(email),
                    "owner_contact_email": email2contact_email(email),
                    "last_modified": timestamp_to_isoformat_timestr(r.last_modify),
                    "modifier_email": r.last_modifier,
                    "modifier_name": nickname_dict.get(r.last_modifier, ''),
                    "modifier_contact_email": contact_email_dict.get(r.last_modifier, ''),
                    "size": r.size,
                    "encrypted": r.encrypted,
                    "permission": 'rw',  # Always have read-write permission to owned repo
                    "starred": r.repo_id in starred_repo_id_list,
                }

                if is_pro_version() and ENABLE_STORAGE_CLASSES:
                    repo_info['storage_name'] = r.storage_name
                    repo_info['storage_id'] = r.storage_id

                repo_info_list.append(repo_info)

        if filter_by['shared']:

            if org_id:
                shared_repos = seafile_api.get_org_share_in_repo_list(org_id,
                        email, -1, -1)
            else:
                shared_repos = seafile_api.get_share_in_repo_list(
                        email, -1, -1)

            repos_with_admin_share_to = ExtraSharePermission.objects.\
                    get_repos_with_admin_permission(email)

            # Reduce memcache fetch ops.
            owners_set = set([x.user for x in shared_repos])
            modifiers_set = set([x.last_modifier for x in shared_repos])
            for e in owners_set | modifiers_set:
                if e not in contact_email_dict:
                    contact_email_dict[e] = email2contact_email(e)
                if e not in nickname_dict:
                    nickname_dict[e] = email2nickname(e)

            shared_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify))
            for r in shared_repos:

                owner_email = r.user

                group_name = ''
                is_group_owned_repo = False
                if '@seafile_group' in owner_email:
                    is_group_owned_repo = True
                    group_id = get_group_id_by_repo_owner(owner_email)
                    group_name= group_id_to_name(group_id)

                owner_name = group_name if is_group_owned_repo else \
                        nickname_dict.get(owner_email, '')
                owner_contact_email = '' if is_group_owned_repo else \
                        contact_email_dict.get(owner_email, '')

                repo_info = {
                    "type": "shared",
                    "repo_id": r.repo_id,
                    "repo_name": r.repo_name,
                    "last_modified": timestamp_to_isoformat_timestr(r.last_modify),
                    "modifier_email": r.last_modifier,
                    "modifier_name": nickname_dict.get(r.last_modifier, ''),
                    "modifier_contact_email": contact_email_dict.get(r.last_modifier, ''),
                    "owner_email": owner_email,
                    "owner_name": owner_name,
                    "owner_contact_email": owner_contact_email,
                    "size": r.size,
                    "encrypted": r.encrypted,
                    "permission": r.permission,
                    "starred": r.repo_id in starred_repo_id_list,
                }

                if r.repo_id in repos_with_admin_share_to:
                    repo_info['is_admin'] = True
                else:
                    repo_info['is_admin'] = False

                repo_info_list.append(repo_info)

        if filter_by['group']:

            if org_id:
                group_repos = seafile_api.get_org_group_repos_by_user(email, org_id)
            else:
                group_repos = seafile_api.get_group_repos_by_user(email)

            group_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify))

            # Reduce memcache fetch ops.
            share_from_set = set([x.user for x in group_repos])
            modifiers_set = set([x.last_modifier for x in group_repos])
            for e in modifiers_set | share_from_set:
                if e not in contact_email_dict:
                    contact_email_dict[e] = email2contact_email(e)
                if e not in nickname_dict:
                    nickname_dict[e] = email2nickname(e)

            for r in group_repos:
                repo_info = {
                    "type": "group",
                    "group_id": r.group_id,
                    "group_name": r.group_name,
                    "repo_id": r.repo_id,
                    "repo_name": r.repo_name,
                    "last_modified": timestamp_to_isoformat_timestr(r.last_modify),
                    "modifier_email": r.last_modifier,
                    "modifier_name": nickname_dict.get(r.last_modifier, ''),
                    "modifier_contact_email": contact_email_dict.get(r.last_modifier, ''),
                    "size": r.size,
                    "encrypted": r.encrypted,
                    "permission": r.permission,
                    "starred": r.repo_id in starred_repo_id_list,
                }
                repo_info_list.append(repo_info)

        if filter_by['public'] and request.user.permissions.can_view_org():
            public_repos = list_inner_pub_repos(request)

            # get repo id owner dict
            all_repo_owner = []
            repo_id_owner_dict = {}
            for repo in public_repos:
                repo_id = repo.repo_id
                if repo_id not in repo_id_owner_dict:
                    repo_owner = get_repo_owner(request, repo_id)
                    all_repo_owner.append(repo_owner)
                    repo_id_owner_dict[repo_id] = repo_owner

            # Reduce memcache fetch ops.
            owner_set = set(all_repo_owner)
            share_from_set = set([x.user for x in public_repos])
            modifiers_set = set([x.last_modifier for x in public_repos])
            for e in modifiers_set | share_from_set | owner_set:
                if e not in contact_email_dict:
                    contact_email_dict[e] = email2contact_email(e)
                if e not in nickname_dict:
                    nickname_dict[e] = email2nickname(e)

            for r in public_repos:
                repo_owner = repo_id_owner_dict[r.repo_id]
                repo_info = {
                    "type": "public",
                    "repo_id": r.repo_id,
                    "repo_name": r.repo_name,
                    "last_modified": timestamp_to_isoformat_timestr(r.last_modify),
                    "modifier_email": r.last_modifier,
                    "modifier_name": nickname_dict.get(r.last_modifier, ''),
                    "modifier_contact_email": contact_email_dict.get(r.last_modifier, ''),
                    "owner_email": repo_owner,
                    "owner_name": nickname_dict.get(repo_owner, ''),
                    "owner_contact_email": contact_email_dict.get(repo_owner, ''),
                    "size": r.size,
                    "encrypted": r.encrypted,
                    "permission": r.permission,
                    "starred": r.repo_id in starred_repo_id_list,
                }
                repo_info_list.append(repo_info)

        utc_dt = datetime.datetime.utcnow()
        timestamp = utc_dt.strftime('%Y-%m-%d %H:%M:%S')
        org_id = request.user.org.org_id if is_org_context(request) else -1
        try:
            send_message('seahub.stats', 'user-login\t%s\t%s\t%s' % (email, timestamp, org_id))
        except Exception as e:
            logger.error('Error when sending user-login message: %s' % str(e))

        return Response({'repos': repo_info_list})
Exemplo n.º 25
0
    def get(self, request, format=None):
        """ Only used for download dir when view dir share link from web.


        Permission checking:
        1. authenticated user OR anonymous user has passed email code check(if necessary);
        """

        # permission check
        if is_pro_version() and settings.ENABLE_SHARE_LINK_AUDIT:
            if not request.user.is_authenticated() and \
                not request.session.get('anonymous_email'):
                # if anonymous user has passed email code check,
                # then his/her email info will be in session.

                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # argument check
        share_link_token = request.GET.get('share_link_token', None)
        if not share_link_token:
            error_msg = 'share_link_token invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        req_path = request.GET.get('path', None)
        if not req_path:
            error_msg = 'path invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # recourse check
        fileshare = FileShare.objects.get_valid_dir_link_by_token(
            share_link_token)
        if not fileshare:
            error_msg = 'share_link_token %s not found.' % share_link_token
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        if req_path[-1] != '/':
            req_path += '/'

        if req_path == '/':
            real_path = fileshare.path
        else:
            real_path = posixpath.join(fileshare.path, req_path.lstrip('/'))

        if real_path[-1] != '/':
            real_path += '/'

        repo_id = fileshare.repo_id
        repo = seafile_api.get_repo(repo_id)
        if not repo:
            error_msg = 'Library %s not found.' % repo_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        dir_id = seafile_api.get_dir_id_by_path(repo_id, real_path)
        if not dir_id:
            error_msg = 'Folder %s not found.' % real_path
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        if not seafile_api.check_permission_by_path(repo_id, '/',
                                                    fileshare.username):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # get file server access token
        dir_name = repo.name if real_path == '/' else \
                os.path.basename(real_path.rstrip('/'))

        dir_size = seafile_api.get_dir_size(repo.store_id, repo.version,
                                            dir_id)
        if dir_size > seaserv.MAX_DOWNLOAD_DIR_SIZE:
            error_msg = _(
                'Unable to download directory "%s": size is too large.'
            ) % dir_name
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        try:
            seaserv.send_message(
                'seahub.stats', 'dir-download\t%s\t%s\t%s\t%s' %
                (repo_id, fileshare.username, dir_id, dir_size))
        except Exception as e:
            logger.error(e)

        is_windows = 0
        if is_windows_operating_system(request):
            is_windows = 1

        fake_obj_id = {
            'obj_id': dir_id,
            'dir_name': dir_name,
            'is_windows': is_windows
        }

        username = request.user.username
        try:
            zip_token = seafile_api.get_fileserver_access_token(
                repo_id,
                json.dumps(fake_obj_id),
                'download-dir',
                username,
                use_onetime=settings.FILESERVER_TOKEN_ONCE_ONLY)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        if not zip_token:
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        if request.session.get('anonymous_email'):
            request.user.username = request.session.get('anonymous_email')

        send_file_access_msg(request, repo, real_path, 'share-link')

        return Response({'zip_token': zip_token})
Exemplo n.º 26
0
    def get(self, request, format=None):
        """ Only used for download dir when view dir share link from web.


        Permission checking:
        1. authenticated user OR anonymous user has passed email code check(if necessary);
        """

        # permission check
        if is_pro_version() and settings.ENABLE_SHARE_LINK_AUDIT:
            if not request.user.is_authenticated() and \
                not request.session.get('anonymous_email'):
                # if anonymous user has passed email code check,
                # then his/her email info will be in session.

                error_msg = 'Permission denied.'
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # argument check
        share_link_token = request.GET.get('share_link_token', None)
        if not share_link_token:
            error_msg = 'share_link_token invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        req_path = request.GET.get('path', None)
        if not req_path:
            error_msg = 'path invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # recourse check
        fileshare = FileShare.objects.get_valid_dir_link_by_token(share_link_token)
        if not fileshare:
            error_msg = 'share_link_token %s not found.' % share_link_token
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        if req_path[-1] != '/':
            req_path += '/'

        if req_path == '/':
            real_path = fileshare.path
        else:
            real_path = posixpath.join(fileshare.path, req_path.lstrip('/'))

        if real_path[-1] != '/':
            real_path += '/'

        repo_id = fileshare.repo_id
        repo = seafile_api.get_repo(repo_id)
        if not repo:
            error_msg = 'Library %s not found.' % repo_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        dir_id = seafile_api.get_dir_id_by_path(repo_id, real_path)
        if not dir_id:
            error_msg = 'Folder %s not found.' % real_path
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # get file server access token
        dir_name = repo.name if real_path == '/' else \
                os.path.basename(real_path.rstrip('/'))

        dir_size = seafile_api.get_dir_size(
                repo.store_id, repo.version, dir_id)
        if dir_size > seaserv.MAX_DOWNLOAD_DIR_SIZE:
            error_msg = 'Unable to download directory "%s": size is too large.' % dir_name
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        try:
            seaserv.send_message('seahub.stats', 'dir-download\t%s\t%s\t%s\t%s' %
                                 (repo_id, fileshare.username, dir_id, dir_size))
        except Exception as e:
            logger.error(e)

        is_windows = 0
        if is_windows_operating_system(request):
            is_windows = 1

        fake_obj_id = {
            'obj_id': dir_id,
            'dir_name': dir_name,
            'is_windows': is_windows
        }

        username = request.user.username
        try:
            zip_token = seafile_api.get_fileserver_access_token(
                    repo_id, json.dumps(fake_obj_id), 'download-dir', username)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        if request.session.get('anonymous_email'):
            request.user.username = request.session.get('anonymous_email')

        send_file_access_msg(request, repo, real_path, 'share-link')

        return Response({'zip_token': zip_token})