Beispiel #1
0
def check_filename_with_rename(repo_id, parent_dir, filename):
    cmmts = get_commits(repo_id, 0, 1)
    latest_commit = cmmts[0] if cmmts else None
    if not latest_commit:
        return ''
    # TODO: what if parrent_dir does not exist?
    dirents = seafile_api.list_dir_by_commit_and_path(repo_id, latest_commit.id,
                                                      parent_dir.encode('utf-8'))

    def no_duplicate(name):
        for dirent in dirents:
            if dirent.obj_name == name:
                return False
        return True

    def make_new_name(filename, i):
        base, ext = os.path.splitext(filename)
        if ext:
            new_base = "%s (%d)" % (base, i)
            return new_base + ext
        else:
            return "%s (%d)" % (filename, i)

    if no_duplicate(filename):
        return filename
    else:
        i = 1
        while True:
            new_name = make_new_name (filename, i)
            if no_duplicate(new_name):
                return new_name
            else:
                i += 1
Beispiel #2
0
def list_dir_by_path(cmmt, path):
    if cmmt.root_id == EMPTY_SHA1:
        return []
    else:
        dirs = seafile_api.list_dir_by_commit_and_path(cmmt.repo_id, cmmt.id,
                                                       path)
        return dirs if dirs else []
Beispiel #3
0
def check_filename_with_rename(repo_id, parent_dir, filename):
    cmmts = get_commits(repo_id, 0, 1)
    latest_commit = cmmts[0] if cmmts else None
    if not latest_commit:
        return ''
    # TODO: what if parrent_dir does not exist?
    dirents = seafile_api.list_dir_by_commit_and_path(
        repo_id, latest_commit.id, parent_dir.encode('utf-8'))

    def no_duplicate(name):
        for dirent in dirents:
            if dirent.obj_name == name:
                return False
        return True

    def make_new_name(filename, i):
        base, ext = os.path.splitext(filename)
        if ext:
            new_base = "%s (%d)" % (base, i)
            return new_base + ext
        else:
            return "%s (%d)" % (filename, i)

    if no_duplicate(filename):
        return filename
    else:
        i = 1
        while True:
            new_name = make_new_name(filename, i)
            if no_duplicate(new_name):
                return new_name
            else:
                i += 1
Beispiel #4
0
def check_filename_with_rename(repo_id, parent_dir, obj_name):
    cmmts = seafile_api.get_commit_list(repo_id, 0, 1)
    latest_commit = cmmts[0] if cmmts else None
    if not latest_commit:
        return ''
    # TODO: what if parrent_dir does not exist?
    dirents = seafile_api.list_dir_by_commit_and_path(
        repo_id, latest_commit.id, parent_dir.encode('utf-8'))

    exist_obj_names = [dirent.obj_name for dirent in dirents]
    return get_no_duplicate_obj_name(obj_name, exist_obj_names)
Beispiel #5
0
    def check_has_subdir(repo):
        latest_commit = seaserv.get_commits(repo.id, 0, 1)[0]
        if not latest_commit:
            return False
        if latest_commit.root_id == EMPTY_SHA1:
            return False

        try:
            dirs = seafile_api.list_dir_by_commit_and_path(latest_commit.id, '/')
        except Exception, e:
            logger.error(e)
            return False
Beispiel #6
0
    def check_has_subdir(repo):
        latest_commit = seaserv.get_commits(repo.id, 0, 1)[0]
        if not latest_commit:
            return False
        if latest_commit.root_id == EMPTY_SHA1:
            return False

        try:
            dirs = seafile_api.list_dir_by_commit_and_path(
                latest_commit.id, '/')
        except Exception, e:
            logger.error(e)
            return False
Beispiel #7
0
def render_dir_recycle_dir(request, repo_id, commit_id, dir_path, referer):
    basedir = request.GET.get('base', '')
    path = request.GET.get('p', '')
    if not basedir or not path:
        return render_dir_recycle_root(request, repo_id, dir_path)

    if basedir[0] != '/':
        basedir = '/' + basedir
    if path[-1] != '/':
        path += '/'

    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    try:
        commit = seafserv_threaded_rpc.get_commit(repo.id, repo.version,
                                                  commit_id)
    except SearpcError as e:
        logger.error(e)
        referer = request.META.get('HTTP_REFERER', None)
        next = settings.SITE_ROOT if referer is None else referer
        return HttpResponseRedirect(next)

    if not commit:
        raise Http404

    zipped = gen_path_link(path, '')
    dir_entries = seafile_api.list_dir_by_commit_and_path(
        commit.repo_id, commit.id, basedir + path, -1, -1)
    for dirent in dir_entries:
        if stat.S_ISDIR(dirent.mode):
            dirent.is_dir = True
        else:
            dirent.is_dir = False

    return render_to_response(
        'repo_dir_recycle_view.html', {
            'show_recycle_root': False,
            'repo': repo,
            'repo_dir_name': os.path.basename(dir_path.rstrip('/')),
            'zipped': zipped,
            'dir_entries': dir_entries,
            'commit_id': commit_id,
            'basedir': basedir,
            'path': path,
            'dir_path': dir_path,
            'referer': referer,
        },
        context_instance=RequestContext(request))
Beispiel #8
0
def get_file_revision_id_size(commit_id, path):
    """Given a commit and a file path in that commit, return the seafile id
    and size of the file blob

    """
    dirname = os.path.dirname(path)
    filename = os.path.basename(path)
    seafdir = seafile_api.list_dir_by_commit_and_path(commit_id, dirname)
    for dirent in seafdir:
        if dirent.obj_name == filename:
            file_size = seafserv_threaded_rpc.get_file_size(dirent.obj_id)
            return dirent.obj_id, file_size

    return None, None
Beispiel #9
0
def get_file_revision_id_size (commit_id, path):
    """Given a commit and a file path in that commit, return the seafile id
    and size of the file blob

    """
    dirname  = os.path.dirname(path)
    filename = os.path.basename(path)
    seafdir = seafile_api.list_dir_by_commit_and_path (commit_id, dirname)
    for dirent in seafdir:
        if dirent.obj_name == filename:
            file_size = seafserv_threaded_rpc.get_file_size(dirent.obj_id)
            return dirent.obj_id, file_size

    return None, None
Beispiel #10
0
def get_file_revision_id_size(repo_id, commit_id, path):
    """Given a commit and a file path in that commit, return the seafile id
    and size of the file blob

    """
    repo = seafile_api.get_repo(repo_id)
    dirname = os.path.dirname(path)
    filename = os.path.basename(path)
    seafdir = seafile_api.list_dir_by_commit_and_path(repo_id, commit_id, dirname)
    for dirent in seafdir:
        if dirent.obj_name == filename:
            file_size = seafile_api.get_file_size(repo.store_id, repo.version, dirent.obj_id)
            return dirent.obj_id, file_size

    return None, None
Beispiel #11
0
def get_repo_dirents(repo, commit, path, offset=-1, limit=-1):
    dir_list = []
    file_list = []
    dirent_more = False
    if commit.root_id == EMPTY_SHA1:
        return ([], []) if limit == -1 else ([], [], False)
    else:
            if limit == -1:
                dirs = seafile_api.list_dir_by_commit_and_path(commit.repo_id, commit.id, path, offset, limit)
            else:
                dirs = seafile_api.list_dir_by_commit_and_path(commit.repo_id, commit.id, path, offset, limit + 1)
                if len(dirs) == limit + 1:
                    dirs = dirs[:limit]
                    dirent_more = True
    for dirent in dirs:
        file_list.append(dirent)
    dir_list.sort(lambda x, y : cmp(x.obj_name.lower(),
                                        y.obj_name.lower()))
    file_list.sort(lambda x, y : cmp(x.obj_name.lower(),
                                         y.obj_name.lower()))
    if limit == -1:
        return (file_list, dir_list)
    else:
        return (file_list, dir_list, dirent_more)
Beispiel #12
0
def get_wiki_dirent(repo_id, page_name):
    file_name = page_name_to_file_name(page_name)
    repo = seaserv.get_repo(repo_id)
    if not repo:
        raise WikiDoesNotExist
    cmmt = seaserv.get_commits(repo.id, 0, 1)[0]
    if cmmt is None:
        raise WikiPageMissing
    dirs = seafile_api.list_dir_by_commit_and_path(cmmt.repo_id, cmmt.id, "/")
    if dirs:
        for e in dirs:
            if stat.S_ISDIR(e.mode):
                continue    # skip directories
            if normalize_page_name(file_name) == normalize_page_name(e.obj_name):
                return e
    raise WikiPageMissing
Beispiel #13
0
def get_file_revision_id_size(repo_id, commit_id, path):
    """Given a commit and a file path in that commit, return the seafile id
    and size of the file blob

    """
    repo = seafile_api.get_repo(repo_id)
    dirname  = os.path.dirname(path)
    filename = os.path.basename(path)
    seafdir = seafile_api.list_dir_by_commit_and_path(repo_id, commit_id, dirname)
    for dirent in seafdir:
        if dirent.obj_name == filename:
            file_size = seafile_api.get_file_size(repo.store_id, repo.version,
                                                  dirent.obj_id)
            return dirent.obj_id, file_size

    return None, None
Beispiel #14
0
def get_wiki_dirent(repo_id, page_name):
    file_name = page_name_to_file_name(page_name)
    repo = seaserv.get_repo(repo_id)
    if not repo:
        raise WikiDoesNotExist
    cmmt = seaserv.get_commits(repo.id, 0, 1)[0]
    if cmmt is None:
        raise WikiPageMissing
    dirs = seafile_api.list_dir_by_commit_and_path(cmmt.repo_id, cmmt.id, "/")
    if dirs:
        for e in dirs:
            if stat.S_ISDIR(e.mode):
                continue  # skip directories
            if normalize_page_name(file_name) == normalize_page_name(e.obj_name):
                return e
    raise WikiPageMissing
Beispiel #15
0
def render_dir_recycle_dir(request, repo_id, commit_id, dir_path):
    basedir = request.GET.get('base', '')
    path = request.GET.get('p', '')
    if not basedir or not path:
        return render_dir_recycle_root(request, repo_id, dir_path)

    if basedir[0] != '/':
        basedir = '/' + basedir
    if path[-1] != '/':
        path += '/'

    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    try :
        commit = seafserv_threaded_rpc.get_commit(repo.id, repo.version, commit_id)
    except SearpcError as e:
        logger.error(e)
        referer = request.META.get('HTTP_REFERER', None)
        next = settings.SITE_ROOT if referer is None else referer
        return HttpResponseRedirect(next)

    if not commit:
        raise Http404

    zipped = gen_path_link(path, '')
    dir_entries = seafile_api.list_dir_by_commit_and_path(commit.repo_id,
                                                   commit.id, basedir+path,
                                                   -1, -1)
    for dirent in dir_entries:
        if stat.S_ISDIR(dirent.mode):
            dirent.is_dir = True
        else:
            dirent.is_dir = False

    return render_to_response('repo_dir_recycle_view.html', {
            'show_recycle_root': False,
            'repo': repo,
            'repo_dir_name': os.path.basename(dir_path.rstrip('/')),
            'zipped': zipped,
            'dir_entries': dir_entries,
            'commit_id': commit_id,
            'basedir': basedir,
            'path': path,
            'dir_path': dir_path,
            }, context_instance=RequestContext(request))
Beispiel #16
0
def list_dir_by_path(cmmt, path):
    if cmmt.root_id == EMPTY_SHA1:
        return []
    else:
        return seafile_api.list_dir_by_commit_and_path(cmmt.id, path)
Beispiel #17
0
    def get(self, request, token):
        """ Get dirents of shared download 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)

        obj_path = sharelink.path
        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)

        req_path = request.GET.get('path', '/')

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

        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)

        try:
            current_commit = seafile_api.get_commit_list(repo_id, 0, 1)[0]
            dirent_list = seafile_api.list_dir_by_commit_and_path(
                repo_id, current_commit.id, real_path, -1, -1)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        result = []
        for dirent in dirent_list:
            dirent_info = {}
            dirent_info['obj_name'] = dirent.obj_name
            dirent_info['path'] = posixpath.join(req_path, dirent.obj_name)
            dirent_info['size'] = dirent.size
            dirent_info['last_modified'] = timestamp_to_isoformat_timestr(
                dirent.mtime)
            if stat.S_ISDIR(dirent.mode):
                dirent_info['is_dir'] = True
            else:
                dirent_info['is_dir'] = False

            result.append(dirent_info)

        return Response(result)
Beispiel #18
0
def get_repo_dirents(request, repo, commit, path, offset=-1, limit=-1):
    """List repo dirents based on commit id and path. Use ``offset`` and
    ``limit`` to do paginating.

    Returns: A tupple of (file_list, dir_list, dirent_more)

    TODO: Some unrelated parts(file sharing, stars, modified info, etc) need
    to be pulled out to multiple functions.
    """

    dir_list = []
    file_list = []
    dirent_more = False
    if commit.root_id == EMPTY_SHA1:
        return ([], [], False) if limit == -1 else ([], [], False)
    else:
        try:
            dirs = seafile_api.list_dir_by_commit_and_path(commit.repo_id,
                                                           commit.id, path,
                                                           offset, limit)
            if not dirs:
                return ([], [], False)
        except SearpcError as e:
            logger.error(e)
            return ([], [], False)

        if limit != -1 and limit == len(dirs):
            dirent_more = True

        username = request.user.username
        starred_files = get_dir_starred_files(username, repo.id, path)
        fileshares = FileShare.objects.filter(repo_id=repo.id).filter(username=username)
        uploadlinks = UploadLinkShare.objects.filter(repo_id=repo.id).filter(username=username)


        view_dir_base = reverse("view_common_lib_dir", args=[repo.id, ''])
        dl_dir_base = reverse('repo_download_dir', args=[repo.id])
        file_history_base = reverse('file_revisions', args=[repo.id])
        for dirent in dirs:
            dirent.last_modified = dirent.mtime
            dirent.sharelink = ''
            dirent.uploadlink = ''
            if stat.S_ISDIR(dirent.props.mode):
                dpath = posixpath.join(path, dirent.obj_name)
                if dpath[-1] != '/':
                    dpath += '/'
                for share in fileshares:
                    if dpath == share.path:
                        dirent.sharelink = gen_dir_share_link(share.token)
                        dirent.sharetoken = share.token
                        break
                for link in uploadlinks:
                    if dpath == link.path:
                        dirent.uploadlink = gen_shared_upload_link(link.token)
                        dirent.uploadtoken = link.token
                        break
                p_dpath = posixpath.join(path, dirent.obj_name)
                dirent.view_link = view_dir_base + '?p=' + urlquote(p_dpath)
                dirent.dl_link = dl_dir_base + '?p=' + urlquote(p_dpath)
                dir_list.append(dirent)
            else:
                file_list.append(dirent)
                if repo.version == 0:
                    dirent.file_size = get_file_size(repo.store_id, repo.version, dirent.obj_id)
                else:
                    dirent.file_size = dirent.size
                dirent.starred = False
                fpath = posixpath.join(path, dirent.obj_name)
                p_fpath = posixpath.join(path, dirent.obj_name)
                dirent.view_link = reverse('view_lib_file', args=[repo.id, p_fpath])
                dirent.dl_link = get_file_download_link(repo.id, dirent.obj_id,
                                                        p_fpath)
                dirent.history_link = file_history_base + '?p=' + urlquote(p_fpath)
                if fpath in starred_files:
                    dirent.starred = True
                for share in fileshares:
                    if fpath == share.path:
                        dirent.sharelink = gen_file_share_link(share.token)
                        dirent.sharetoken = share.token
                        break

        return (file_list, dir_list, dirent_more)
Beispiel #19
0
def test_file_property_and_dir_listing():

    t_repo_version = 1
    t_repo_id = api.create_repo('test_file_property_and_dir_listing',
                                '',
                                USER,
                                passwd=None)

    create_the_file()

    api.post_file(t_repo_id, file_path, '/', file_name, USER)
    api.post_dir(t_repo_id, '/', dir_name, USER)
    api.post_file(t_repo_id, file_path, '/' + dir_name, file_name, USER)

    #test is_valid_filename
    t_valid_file_name = 'valid_filename'
    t_invalid_file_name = '/invalid_filename'
    assert api.is_valid_filename(t_repo_id, t_valid_file_name)
    assert api.is_valid_filename(t_repo_id, t_invalid_file_name) == 0

    #test get_file_id_by_path
    t_file_id = api.get_file_id_by_path(t_repo_id, '/test.txt')
    assert t_file_id

    #test get_dir_id_by_path
    t_dir_id = api.get_dir_id_by_path(t_repo_id, '/test_dir')
    assert t_dir_id

    #test get_file_size
    t_file_size = len(file_content)
    assert t_file_size == api.get_file_size(t_repo_id, t_repo_version,
                                            t_file_id)

    #test get_dir_size
    t_dir_size = len(file_content)
    assert t_dir_size == api.get_dir_size(t_repo_id, t_repo_version, t_dir_id)

    #test get_file_count_info_by_path
    t_file_count_info = api.get_file_count_info_by_path(t_repo_id, '/')
    assert t_file_count_info.file_count == 2
    assert t_file_count_info.dir_count == 1
    assert t_file_count_info.size == t_file_size + t_dir_size

    #test get_file_id_by_commit_and_path
    t_file_id_tmp = t_file_id
    t_repo = api.get_repo(t_repo_id)
    assert t_repo
    t_commit_id = t_repo.head_cmmt_id
    t_file_id = api.get_file_id_by_commit_and_path(t_repo_id, t_commit_id,
                                                   '/test.txt')

    assert t_file_id == t_file_id_tmp

    #test get_dirent_by_path
    std_file_mode = 0100000 | 0644
    t_dirent_obj = api.get_dirent_by_path(t_repo_id, '/test.txt')
    assert t_dirent_obj
    assert t_dirent_obj.obj_id == t_file_id
    assert t_dirent_obj.obj_name == 'test.txt'
    assert t_dirent_obj.mode == std_file_mode
    assert t_dirent_obj.version == t_repo_version
    assert t_dirent_obj.size == t_file_size
    assert t_dirent_obj.modifier == USER

    #test list_file_by_file_id
    t_block_list = api.list_file_by_file_id(t_repo_id, t_file_id)
    assert t_block_list

    #test list_blocks_by_file_id
    t_block_list = api.list_blocks_by_file_id(t_repo_id, t_file_id)
    assert t_block_list

    #test list_dir_by_dir_id
    t_dir_list = api.list_dir_by_dir_id(t_repo_id, t_dir_id)
    assert len(t_dir_list) == 1

    #test list_dir_by_path
    t_dir_list = api.list_dir_by_path(t_repo_id, '/test_dir')
    assert len(t_dir_list) == 1

    #test get_dir_id_by_commit_and_path
    t_dir_id = api.get_dir_id_by_commit_and_path(t_repo_id, t_commit_id,
                                                 '/test_dir')
    assert t_dir_id

    #test list_dir_by_commit_and_path
    t_dir_list = api.list_dir_by_commit_and_path(t_repo_id, t_commit_id,
                                                 '/test_dir')
    assert len(t_dir_list) == 1

    #test list_dir_with_perm
    t_dir_list = api.list_dir_with_perm(t_repo_id, '/test_dir', t_dir_id, USER)
    assert len(t_dir_list) == 1

    #test mkdir_with_parent
    api.mkdir_with_parents(t_repo_id, '/test_dir', 'test_subdir', USER)
    t_dir_id = api.get_dir_id_by_path(t_repo_id, '/test_dir/test_subdir')
    assert t_dir_id

    #test get_total_storage
    t_total_size = api.get_total_storage()
    t_repo_size = api.get_repo_size(t_repo_id)
    assert t_total_size == t_repo_size

    #get_total_file_number
    time.sleep(1)
    assert api.get_total_file_number() == 2

    api.remove_repo(t_repo_id)
Beispiel #20
0
def view_file(request, repo_id):
    """
    Steps to view file:
    1. Get repo id and file path.
    2. Check user's permission.
    3. Check whether this file can be viewed online.
    4.1 Get file content if file is text file.
    4.2 Prepare flash if file is document.
    4.3 Prepare or use pdfjs if file is pdf.
    4.4 Other file return it's raw path.
    """
    username = request.user.username
    # check arguments
    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    path = request.GET.get('p', '/').rstrip('/')
    obj_id = get_file_id_by_path(repo_id, path)
    if not obj_id:
        return render_error(request, _(u'File does not exist'))

    # construct some varibles
    u_filename = os.path.basename(path)
    current_commit = get_commits(repo_id, 0, 1)[0]

    # Check whether user has permission to view file and get file raw path,
    # render error page if permission deny.
    raw_path, inner_path, user_perm = get_file_view_path_and_perm(request,
                                                                  repo_id,
                                                                  obj_id, path)
    if not user_perm:
        return render_permission_error(request, _(u'Unable to view file'))

    # check if the user is the owner or not, for 'private share'
    if is_org_context(request):
        repo_owner = seafile_api.get_org_repo_owner(repo.id)
        is_repo_owner = True if repo_owner == username else False
    else:
        is_repo_owner = seafile_api.is_repo_owner(username, repo.id)

    # get file type and extension
    filetype, fileext = get_file_type_and_ext(u_filename)

    img_prev = None
    img_next = None
    ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '',
                'file_encoding_list': [], 'html_exists': False,
                'filetype': filetype}

    fsize = get_file_size(repo.store_id, repo.version, obj_id)

    exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, 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)
            if filetype == MARKDOWN:
                c = ret_dict['file_content']
                ret_dict['file_content'] = convert_md_link(c, repo_id, username)
        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 fsize == 0:
                ret_dict['err'] = _(u'Invalid file format.')
        elif filetype == PDF:
            handle_pdf(inner_path, obj_id, fileext, ret_dict)
        elif filetype == IMAGE:
            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(u_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])
        else:
            pass

    # generate file path navigator
    zipped = gen_path_link(path, repo.name)

    # file shared link
    l = FileShare.objects.filter(repo_id=repo_id).filter(
        username=username).filter(path=path)
    fileshare = l[0] if len(l) > 0 else None
    http_or_https = request.is_secure() and 'https' or 'http'
    domain = RequestSite(request).domain
    if fileshare:
        file_shared_link = gen_file_share_link(fileshare.token)
    else:
        file_shared_link = ''

    for g in request.user.joined_groups:
        g.avatar = grp_avatar(g.id, 20)

    """List repo groups"""
    # Get groups this repo is shared.    
    if request.user.org:
        org_id = request.user.org.org_id
        repo_shared_groups = get_org_groups_by_repo(org_id, repo_id)
    else:
        repo_shared_groups = get_shared_groups_by_repo(repo_id)
    # Filter out groups that user in joined.
    groups = [x for x in repo_shared_groups if is_group_user(x.id, username)]
    if len(groups) > 1:
        ctx = {}
        ctx['groups'] = groups
        repogrp_str = render_to_string("snippets/repo_group_list.html", ctx)
    else:
        repogrp_str = ''

    file_path_hash = hashlib.md5(urllib2.quote(path.encode('utf-8'))).hexdigest()[:12]

    # fetch file contributors and latest contributor
    contributors, last_modified, last_commit_id = \
        FileContributors.objects.get_file_contributors(
        repo_id, path.encode('utf-8'), file_path_hash, obj_id)
    latest_contributor = contributors[0] if contributors else None

    # check whether file is starred
    is_starred = False
    org_id = -1
    if request.user.org:
        org_id = request.user.org.org_id
    is_starred = is_file_starred(username, repo.id, path.encode('utf-8'), org_id)

    template = 'view_file_%s.html' % ret_dict['filetype'].lower()

    return render_to_response(template, {
            'repo': repo,
            'is_repo_owner': is_repo_owner,
            'obj_id': obj_id,
            'filename': u_filename,
            'path': path,
            'zipped': zipped,
            'current_commit': current_commit,
            'fileext': fileext,
            'raw_path': raw_path,
            'fileshare': fileshare,
            'protocol': http_or_https,
            'domain': domain,
            'file_shared_link': file_shared_link,
            'err': ret_dict['err'],
            'file_content': ret_dict['file_content'],
            'file_enc': ret_dict['file_enc'],
            'encoding': ret_dict['encoding'],
            'file_encoding_list': ret_dict['file_encoding_list'],
            'html_exists': ret_dict['html_exists'],
            'html_detail': ret_dict.get('html_detail', {}),
            'filetype': ret_dict['filetype'],
            'groups': groups,
            'use_pdfjs': USE_PDFJS,
            'contributors': contributors,
            'latest_contributor': latest_contributor,
            'last_modified': last_modified,
            'last_commit_id': last_commit_id,
            'repo_group_str': repogrp_str,
            'is_starred': is_starred,
            'user_perm': user_perm,
            'img_prev': img_prev,
            'img_next': img_next,
            'highlight_keyword': settings.HIGHLIGHT_KEYWORD,
            }, context_instance=RequestContext(request))
Beispiel #21
0
    def get(self, request, token):
        """ Only used for get dirents in a folder share link.

        Permission checking:
        1, If enable SHARE_LINK_LOGIN_REQUIRED, user must have been authenticated.
        2, If enable ENABLE_SHARE_LINK_AUDIT, user must have been authenticated, or have been audited.
        3, If share link is encrypted, share link password must have been checked.
        """

        # argument check
        thumbnail_size = request.GET.get('thumbnail_size', 48)
        try:
            thumbnail_size = int(thumbnail_size)
        except ValueError:
            error_msg = 'thumbnail_size invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # permission check

        # check if login required
        if SHARE_LINK_LOGIN_REQUIRED and \
                not request.user.is_authenticated():
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # check share link audit
        if is_pro_version() and ENABLE_SHARE_LINK_AUDIT and \
                not request.user.is_authenticated() and \
                not request.session.get('anonymous_email'):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # resource check
        try:
            share_link = 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)

        # check share link password
        if share_link.is_encrypted() and not check_share_link_access(request, token):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if share_link.s_type != 'd':
            error_msg = 'Share link %s is not a folder share link.' % token
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        repo_id = share_link.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)

        share_link_path = share_link.path
        request_path = request.GET.get('path', '/')
        if request_path == '/':
            path = share_link_path
        else:
            path = posixpath.join(share_link_path, request_path.strip('/'))

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

        try:
            current_commit = seafile_api.get_commit_list(repo_id, 0, 1)[0]
            dirent_list = seafile_api.list_dir_by_commit_and_path(repo_id,
                    current_commit.id, path, -1, -1)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        result = []
        for dirent in dirent_list:

            # don't return parent folder(share link path) info to user
            # so use request_path here
            dirent_path = posixpath.join(request_path, dirent.obj_name)

            dirent_info = {}
            dirent_info['size'] = dirent.size
            dirent_info['last_modified'] = timestamp_to_isoformat_timestr(dirent.mtime)

            if stat.S_ISDIR(dirent.mode):
                dirent_info['is_dir'] = True
                dirent_info['folder_path'] = normalize_dir_path(dirent_path)
                dirent_info['folder_name'] = dirent.obj_name
            else:
                dirent_info['is_dir'] = False
                dirent_info['file_path'] = normalize_file_path(dirent_path)
                dirent_info['file_name'] = dirent.obj_name

                file_type, file_ext = get_file_type_and_ext(dirent.obj_name)
                if file_type in (IMAGE, XMIND) or \
                        file_type == VIDEO and ENABLE_VIDEO_THUMBNAIL:

                    if os.path.exists(os.path.join(THUMBNAIL_ROOT, str(thumbnail_size), dirent.obj_id)):
                        req_image_path = posixpath.join(request_path, dirent.obj_name)
                        src = get_share_link_thumbnail_src(token, thumbnail_size, req_image_path)
                        dirent_info['encoded_thumbnail_src'] = urlquote(src)

            result.append(dirent_info)

        return Response({'dirent_list': result})
Beispiel #22
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))
Beispiel #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))
Beispiel #24
0
def list_dir_by_commit_and_path(commit, path):
    return seafile_api.list_dir_by_commit_and_path(commit.id, path)
Beispiel #25
0
def get_repo_dirents(request, repo, commit, path, offset=-1, limit=-1):
    """List repo dirents based on commit id and path. Use ``offset`` and
    ``limit`` to do paginating.

    Returns: A tupple of (file_list, dir_list, dirent_more)

    TODO: Some unrelated parts(file sharing, stars, modified info, etc) need
    to be pulled out to multiple functions.
    """

    dir_list = []
    file_list = []
    dirent_more = False
    if commit.root_id == EMPTY_SHA1:
        return ([], [], False) if limit == -1 else ([], [], False)
    else:
        try:
            dirs = seafile_api.list_dir_by_commit_and_path(
                commit.repo_id, commit.id, path, offset, limit)
            if not dirs:
                return ([], [], False)
        except SearpcError as e:
            logger.error(e)
            return ([], [], False)

        if limit != -1 and limit == len(dirs):
            dirent_more = True

        username = request.user.username
        starred_files = get_dir_starred_files(username, repo.id, path)
        fileshares = FileShare.objects.filter(repo_id=repo.id).filter(
            username=username)
        uploadlinks = UploadLinkShare.objects.filter(repo_id=repo.id).filter(
            username=username)

        view_dir_base = reverse("view_common_lib_dir", args=[repo.id, ''])
        dl_dir_base = reverse('repo_download_dir', args=[repo.id])
        file_history_base = reverse('file_revisions', args=[repo.id])
        for dirent in dirs:
            dirent.last_modified = dirent.mtime
            dirent.sharelink = ''
            dirent.uploadlink = ''
            if stat.S_ISDIR(dirent.props.mode):
                dpath = posixpath.join(path, dirent.obj_name)
                if dpath[-1] != '/':
                    dpath += '/'
                for share in fileshares:
                    if dpath == share.path:
                        dirent.sharelink = gen_dir_share_link(share.token)
                        dirent.sharetoken = share.token
                        break
                for link in uploadlinks:
                    if dpath == link.path:
                        dirent.uploadlink = gen_shared_upload_link(link.token)
                        dirent.uploadtoken = link.token
                        break
                p_dpath = posixpath.join(path, dirent.obj_name)
                dirent.view_link = view_dir_base + '?p=' + urlquote(p_dpath)
                dirent.dl_link = dl_dir_base + '?p=' + urlquote(p_dpath)
                dir_list.append(dirent)
            else:
                file_list.append(dirent)
                if repo.version == 0:
                    dirent.file_size = get_file_size(repo.store_id,
                                                     repo.version,
                                                     dirent.obj_id)
                else:
                    dirent.file_size = dirent.size
                dirent.starred = False
                fpath = posixpath.join(path, dirent.obj_name)
                p_fpath = posixpath.join(path, dirent.obj_name)
                dirent.view_link = reverse('view_lib_file',
                                           args=[repo.id, p_fpath])
                dirent.dl_link = get_file_download_link(
                    repo.id, dirent.obj_id, p_fpath)
                dirent.history_link = file_history_base + '?p=' + urlquote(
                    p_fpath)
                if fpath in starred_files:
                    dirent.starred = True
                for share in fileshares:
                    if fpath == share.path:
                        dirent.sharelink = gen_file_share_link(share.token)
                        dirent.sharetoken = share.token
                        break

        return (file_list, dir_list, dirent_more)
Beispiel #26
0
def list_dir_by_path(cmmt, path):
    if cmmt.root_id == EMPTY_SHA1:
        return []
    else:
        dirs = seafile_api.list_dir_by_commit_and_path(cmmt.repo_id, cmmt.id, path)
        return dirs if dirs else []
Beispiel #27
0
def view_file(request, repo_id):
    """
    Steps to view file:
    1. Get repo id and file path.
    2. Check user's permission.
    3. Check whether this file can be viewed online.
    4.1 Get file content if file is text file.
    4.2 Prepare flash if file is document.
    4.3 Prepare or use pdfjs if file is pdf.
    4.4 Other file return it's raw path.
    """
    username = request.user.username
    # check arguments
    repo = get_repo(repo_id)
    if not repo:
        raise Http404

    path = request.GET.get('p', '/').rstrip('/')
    obj_id = get_file_id_by_path(repo_id, path)
    if not obj_id:
        return render_error(request, _(u'File does not exist'))

    # construct some varibles
    u_filename = os.path.basename(path)
    current_commit = get_commits(repo_id, 0, 1)[0]

    # Check whether user has permission to view file and get file raw path,
    # render error page if permission deny.
    raw_path, inner_path, user_perm = get_file_view_path_and_perm(
        request, repo_id, obj_id, path)
    if not user_perm:
        return render_permission_error(request, _(u'Unable to view file'))

    # check if the user is the owner or not, for 'private share'
    if is_org_context(request):
        repo_owner = seafile_api.get_org_repo_owner(repo.id)
        is_repo_owner = True if repo_owner == username else False
    else:
        is_repo_owner = seafile_api.is_repo_owner(username, repo.id)

    # get file type and extension
    filetype, fileext = get_file_type_and_ext(u_filename)

    img_prev = None
    img_next = None
    ret_dict = {
        'err': '',
        'file_content': '',
        'encoding': '',
        'file_enc': '',
        'file_encoding_list': [],
        'html_exists': False,
        'filetype': filetype
    }

    fsize = get_file_size(repo.store_id, repo.version, obj_id)

    exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, 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)
            if filetype == MARKDOWN:
                c = ret_dict['file_content']
                ret_dict['file_content'] = convert_md_link(
                    c, repo_id, username)
        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 fsize == 0:
                ret_dict['err'] = _(u'Invalid file format.')
        elif filetype == PDF:
            handle_pdf(inner_path, obj_id, fileext, ret_dict)
        elif filetype == IMAGE:
            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(u_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])
        else:
            pass

    # generate file path navigator
    zipped = gen_path_link(path, repo.name)

    # file shared link
    l = FileShare.objects.filter(repo_id=repo_id).filter(
        username=username).filter(path=path)
    fileshare = l[0] if len(l) > 0 else None
    http_or_https = request.is_secure() and 'https' or 'http'
    domain = RequestSite(request).domain
    if fileshare:
        file_shared_link = gen_file_share_link(fileshare.token)
    else:
        file_shared_link = ''

    for g in request.user.joined_groups:
        g.avatar = grp_avatar(g.id, 20)
    """List repo groups"""
    # Get groups this repo is shared.
    if request.user.org:
        org_id = request.user.org.org_id
        repo_shared_groups = get_org_groups_by_repo(org_id, repo_id)
    else:
        repo_shared_groups = get_shared_groups_by_repo(repo_id)
    # Filter out groups that user in joined.
    groups = [x for x in repo_shared_groups if is_group_user(x.id, username)]
    if len(groups) > 1:
        ctx = {}
        ctx['groups'] = groups
        repogrp_str = render_to_string("snippets/repo_group_list.html", ctx)
    else:
        repogrp_str = ''

    file_path_hash = hashlib.md5(urllib2.quote(
        path.encode('utf-8'))).hexdigest()[:12]

    # fetch file contributors and latest contributor
    contributors, last_modified, last_commit_id = \
        FileContributors.objects.get_file_contributors(
        repo_id, path.encode('utf-8'), file_path_hash, obj_id)
    latest_contributor = contributors[0] if contributors else None

    # check whether file is starred
    is_starred = False
    org_id = -1
    if request.user.org:
        org_id = request.user.org.org_id
    is_starred = is_file_starred(username, repo.id, path.encode('utf-8'),
                                 org_id)

    template = 'view_file_%s.html' % ret_dict['filetype'].lower()

    return render_to_response(
        template, {
            'repo': repo,
            'is_repo_owner': is_repo_owner,
            'obj_id': obj_id,
            'filename': u_filename,
            'path': path,
            'zipped': zipped,
            'current_commit': current_commit,
            'fileext': fileext,
            'raw_path': raw_path,
            'fileshare': fileshare,
            'protocol': http_or_https,
            'domain': domain,
            'file_shared_link': file_shared_link,
            'err': ret_dict['err'],
            'file_content': ret_dict['file_content'],
            'file_enc': ret_dict['file_enc'],
            'encoding': ret_dict['encoding'],
            'file_encoding_list': ret_dict['file_encoding_list'],
            'html_exists': ret_dict['html_exists'],
            'html_detail': ret_dict.get('html_detail', {}),
            'filetype': ret_dict['filetype'],
            'groups': groups,
            'use_pdfjs': USE_PDFJS,
            'contributors': contributors,
            'latest_contributor': latest_contributor,
            'last_modified': last_modified,
            'last_commit_id': last_commit_id,
            'repo_group_str': repogrp_str,
            'is_starred': is_starred,
            'user_perm': user_perm,
            'img_prev': img_prev,
            'img_next': img_next,
            'highlight_keyword': settings.HIGHLIGHT_KEYWORD,
        },
        context_instance=RequestContext(request))
Beispiel #28
0
def list_dir_by_commit_and_path(commit, path):
    return seafile_api.list_dir_by_commit_and_path(commit.id, path)
Beispiel #29
0
    def get(self, request, token):
        """ Only used for get dirents in a folder share link.

        Permission checking:
        1, If enable SHARE_LINK_LOGIN_REQUIRED, user must have been authenticated.
        2, If enable ENABLE_SHARE_LINK_AUDIT, user must have been authenticated, or have been audited.
        3, If share link is encrypted, share link password must have been checked.
        """

        # argument check
        thumbnail_size = request.GET.get('thumbnail_size', 48)
        try:
            thumbnail_size = int(thumbnail_size)
        except ValueError:
            error_msg = 'thumbnail_size invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # permission check

        # check if login required
        if SHARE_LINK_LOGIN_REQUIRED and \
                not request.user.is_authenticated():
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # check share link audit
        if is_pro_version() and ENABLE_SHARE_LINK_AUDIT and \
                not request.user.is_authenticated() and \
                not request.session.get('anonymous_email'):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # resource check
        try:
            share_link= 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)

        # check share link password
        if share_link.is_encrypted() and not check_share_link_access(request, token):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if share_link.s_type != 'd':
            error_msg = 'Share link %s is not a folder share link.' % token
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        repo_id = share_link.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)

        share_link_path = share_link.path
        request_path = request.GET.get('path', '/')
        if request_path == '/':
            path = share_link_path
        else:
            path = posixpath.join(share_link_path, request_path.strip('/'))

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

        try:
            current_commit = seafile_api.get_commit_list(repo_id, 0, 1)[0]
            dirent_list = seafile_api.list_dir_by_commit_and_path(repo_id,
                    current_commit.id, path, -1, -1)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        result = []
        for dirent in dirent_list:

            # don't return parent folder(share link path) info to user
            # so use request_path here
            dirent_path = posixpath.join(request_path, dirent.obj_name)

            dirent_info = {}
            dirent_info['size'] = dirent.size
            dirent_info['last_modified'] = timestamp_to_isoformat_timestr(dirent.mtime)

            if stat.S_ISDIR(dirent.mode):
                dirent_info['is_dir'] = True
                dirent_info['folder_path'] = normalize_dir_path(dirent_path)
                dirent_info['folder_name'] = dirent.obj_name
            else:
                dirent_info['is_dir'] = False
                dirent_info['file_path'] = normalize_file_path(dirent_path)
                dirent_info['file_name'] = dirent.obj_name

                file_type, file_ext = get_file_type_and_ext(dirent.obj_name)
                if file_type in (IMAGE, XMIND) or \
                        file_type == VIDEO and ENABLE_VIDEO_THUMBNAIL:

                    if os.path.exists(os.path.join(THUMBNAIL_ROOT, str(thumbnail_size), dirent.obj_id)):
                        req_image_path = posixpath.join(request_path, dirent.obj_name)
                        src = get_share_link_thumbnail_src(token, thumbnail_size, req_image_path)
                        dirent_info['encoded_thumbnail_src'] = urlquote(src)

            result.append(dirent_info)

        return Response({'dirent_list': result})