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
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 []
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
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)
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
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
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))
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
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
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
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)
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
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
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
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))
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)
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)
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)
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)
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))
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})
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))
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))
def list_dir_by_commit_and_path(commit, path): return seafile_api.list_dir_by_commit_and_path(commit.id, path)
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)
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 []
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))
def list_dir_by_commit_and_path(commit, path): return seafile_api.list_dir_by_commit_and_path(commit.id, path)
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})