def repo_download_dir(request, repo_id): repo = get_repo(repo_id) if not repo: return render_error(request, _('Library does not exist')) path = request.GET.get('p', '/') if path[-1] != '/': # Normalize dir path path += '/' if not seafile_api.get_dir_id_by_path(repo.id, path): return render_error(request, _('"%s" does not exist.') % path) if len(path) > 1: dirname = os.path.basename(path.rstrip('/')) # Here use `rstrip` to cut out last '/' in path else: dirname = repo.name allow_download = parse_repo_perm(check_folder_permission( request, repo_id, '/')).can_download if allow_download: dir_id = seafile_api.get_dir_id_by_commit_and_path(repo.id, repo.head_cmmt_id, path) try: total_size = seafile_api.get_dir_size(repo.store_id, repo.version, dir_id) except Exception as e: logger.error(str(e)) return render_error(request, _('Internal Server Error')) if total_size > MAX_DOWNLOAD_DIR_SIZE: return render_error(request, _('Unable to download directory "%s": size is too large.') % dirname) is_windows = 0 if is_windows_operating_system(request): is_windows = 1 fake_obj_id = { 'obj_id': dir_id, 'dir_name': dirname, 'is_windows': is_windows } token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-dir', request.user.username) if not token: return render_error(request, _('Internal Server Error')) else: return render_error(request, _('Unable to download "%s"') % dirname ) url = gen_file_get_url(token, dirname) from seahub.views.file import send_file_access_msg send_file_access_msg(request, repo, path, 'web') return redirect(url)
def repo_download_dir(request, repo_id): repo = get_repo(repo_id) if not repo: return render_error(request, _(u'Library does not exist')) path = request.GET.get('p', '/') if path[-1] != '/': # Normalize dir path path += '/' if not seafile_api.get_dir_id_by_path(repo.id, path): return render_error(request, _('"%s" does not exist.') % path) if len(path) > 1: dirname = os.path.basename(path.rstrip('/')) # Here use `rstrip` to cut out last '/' in path else: dirname = repo.name allow_download = True if check_folder_permission(request, repo_id, '/') else False if allow_download: dir_id = seafile_api.get_dir_id_by_commit_and_path(repo.id, repo.head_cmmt_id, path) try: total_size = seafile_api.get_dir_size(repo.store_id, repo.version, dir_id) except Exception, e: logger.error(str(e)) return render_error(request, _(u'Internal Error')) if total_size > MAX_DOWNLOAD_DIR_SIZE: return render_error(request, _(u'Unable to download directory "%s": size is too large.') % dirname) is_windows = 0 if is_windows_operating_system(request): is_windows = 1 fake_obj_id = { 'obj_id': dir_id, 'dir_name': dirname, 'is_windows': is_windows } token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-dir', request.user.username)
def get(self, request, token): """ Get FileServer download url of the shared file/dir. Permission checking: 1. only admin can perform this action. """ try: sharelink = FileShare.objects.get(token=token) except FileShare.DoesNotExist: error_msg = 'Share link %s not found.' % token return api_error(status.HTTP_404_NOT_FOUND, error_msg) repo_id = sharelink.repo_id repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) result = {} obj_path = sharelink.path if sharelink.s_type == 'f': # download shared file obj_id = seafile_api.get_file_id_by_path(repo_id, obj_path) if not obj_id: error_msg = 'File not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: # `username` parameter only used for encrypted repo download_token = seafile_api.get_fileserver_access_token( repo_id, obj_id, 'download-link', sharelink.username, use_onetime=False) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not download_token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) obj_name = os.path.basename(obj_path.rstrip('/')) result['download_link'] = gen_file_get_url(download_token, obj_name) else: # download (sub) file/folder in shared dir obj_id = seafile_api.get_dir_id_by_path(repo_id, obj_path) if not obj_id: error_msg = 'Folder not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) download_type = request.GET.get('type', None) if not download_type or download_type not in ('file', 'folder'): error_msg = 'type invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) req_path = request.GET.get('path', None) if not req_path: error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if req_path == '/': real_path = obj_path else: real_path = posixpath.join(obj_path, req_path.strip('/')) if download_type == 'file': # download sub file in shared dir real_obj_id = seafile_api.get_file_id_by_path( repo_id, real_path) if not real_obj_id: error_msg = 'File not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: download_token = seafile_api.get_fileserver_access_token( repo_id, real_obj_id, 'download-link', sharelink.username, use_onetime=False) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not download_token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) file_name = os.path.basename(real_path.rstrip('/')) result['download_link'] = gen_file_get_url( download_token, file_name) else: # download sub folder in shared dir if real_path[-1] != '/': real_path += '/' real_obj_id = seafile_api.get_dir_id_by_path( repo_id, real_path) if not real_obj_id: error_msg = 'Folder %s not found.' % req_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) dir_name = repo.name if real_path == '/' else \ os.path.basename(real_path.rstrip('/')) dir_size = seafile_api.get_dir_size(repo.store_id, repo.version, real_obj_id) if dir_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: error_msg = 'Unable to download directory "%s": size is too large.' % dir_name return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # get file server access token is_windows = 0 if is_windows_operating_system(request): is_windows = 1 fake_obj_id = { 'obj_id': real_obj_id, 'dir_name': dir_name, 'is_windows': is_windows } try: zip_token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-dir-link', sharelink.username, use_onetime=False) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) result['download_link'] = gen_dir_zip_download_url(zip_token) return Response(result)
def get(self, request, format=None): """ Only used for download dir when view dir share link from web. Permission checking: 1. authenticated user OR anonymous user has passed email code check(if necessary); """ # permission check if is_pro_version() and settings.ENABLE_SHARE_LINK_AUDIT: if not request.user.is_authenticated() and \ not request.session.get('anonymous_email'): # if anonymous user has passed email code check, # then his/her email info will be in session. error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # argument check share_link_token = request.GET.get('share_link_token', None) if not share_link_token: error_msg = 'share_link_token invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) req_path = request.GET.get('path', None) if not req_path: error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # recourse check fileshare = FileShare.objects.get_valid_dir_link_by_token( share_link_token) if not fileshare: error_msg = 'share_link_token %s not found.' % share_link_token return api_error(status.HTTP_404_NOT_FOUND, error_msg) if req_path[-1] != '/': req_path += '/' if req_path == '/': real_path = fileshare.path else: real_path = posixpath.join(fileshare.path, req_path.lstrip('/')) if real_path[-1] != '/': real_path += '/' repo_id = fileshare.repo_id repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) dir_id = seafile_api.get_dir_id_by_path(repo_id, real_path) if not dir_id: error_msg = 'Folder %s not found.' % real_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not seafile_api.check_permission_by_path(repo_id, '/', fileshare.username): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # get file server access token dir_name = repo.name if real_path == '/' else \ os.path.basename(real_path.rstrip('/')) dir_size = seafile_api.get_dir_size(repo.store_id, repo.version, dir_id) if dir_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: error_msg = _( 'Unable to download directory "%s": size is too large.' ) % dir_name return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: seaserv.send_message( 'seahub.stats', 'dir-download\t%s\t%s\t%s\t%s' % (repo_id, fileshare.username, dir_id, dir_size)) except Exception as e: logger.error(e) is_windows = 0 if is_windows_operating_system(request): is_windows = 1 fake_obj_id = { 'obj_id': dir_id, 'dir_name': dir_name, 'is_windows': is_windows } username = request.user.username try: zip_token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-dir', username, use_onetime=settings.FILESERVER_TOKEN_ONCE_ONLY) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not zip_token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if request.session.get('anonymous_email'): request.user.username = request.session.get('anonymous_email') send_file_access_msg(request, repo, real_path, 'share-link') return Response({'zip_token': zip_token})
def get(self, request, repo_id, format=None): """ Deprecated. Sometimes when user download too many files in one request, Nginx will return 414-Request-URI Too Large error. So, use the following POST request instead. Put all parameters in request body. """ # argument check parent_dir = request.GET.get('parent_dir', None) if not parent_dir: error_msg = 'parent_dir invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) dirent_name_list = request.GET.getlist('dirents', None) if not dirent_name_list: error_msg = 'dirents invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if len(dirent_name_list) == 1: download_type = 'download-dir' elif len(dirent_name_list) > 1: download_type = 'download-multi' else: error_msg = 'dirents invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # recourse check 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) if not seafile_api.get_dir_id_by_path(repo_id, parent_dir): error_msg = 'Folder %s not found.' % parent_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check repo_folder_permission = check_folder_permission( request, repo_id, parent_dir) if not repo_folder_permission: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # get file server access token is_windows = 0 if is_windows_operating_system(request): is_windows = 1 if download_type == 'download-dir': dir_name = dirent_name_list[0].strip('/') full_dir_path = posixpath.join(parent_dir, dir_name) dir_id = seafile_api.get_dir_id_by_path(repo_id, full_dir_path) if not dir_id: error_msg = 'Folder %s not found.' % full_dir_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not json.loads(seafile_api.is_dir_downloadable(repo_id, json.dumps([full_dir_path]), \ request.user.username, repo_folder_permission))['is_downloadable']: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) fake_obj_id = { 'obj_id': dir_id, 'dir_name': dir_name, 'is_windows': is_windows } if download_type == 'download-multi': dirent_list = [] full_dirent_path_list = [] for dirent_name in dirent_name_list: dirent_name = dirent_name.strip('/') dirent_list.append(dirent_name) full_dirent_path = posixpath.join(parent_dir, dirent_name) current_dirent = seafile_api.get_dirent_by_path( repo_id, full_dirent_path) if not current_dirent: continue full_dirent_path_list.append(full_dirent_path) if not json.loads(seafile_api.is_dir_downloadable(repo_id, json.dumps(full_dirent_path_list), \ request.user.username, repo_folder_permission))['is_downloadable']: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) fake_obj_id = { 'parent_dir': parent_dir, 'file_list': dirent_list, 'is_windows': is_windows } username = request.user.username try: zip_token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), download_type, username, use_onetime=settings.FILESERVER_TOKEN_ONCE_ONLY) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not zip_token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if len(dirent_name_list) > 10: send_file_access_msg(request, repo, parent_dir, 'web') else: for dirent_name in dirent_name_list: full_dirent_path = posixpath.join(parent_dir, dirent_name) send_file_access_msg(request, repo, full_dirent_path, 'web') return Response({'zip_token': zip_token})
def post(self, request, repo_id, format=None): """ Get file server token for download-dir and download-multi. Permission checking: 1. user with 'r' or 'rw' permission; """ # argument check parent_dir = request.data.get('parent_dir', None) if not parent_dir: error_msg = 'parent_dir invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) dirent_name_list = request.data.getlist('dirents', None) if not dirent_name_list: error_msg = 'dirents invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if len(dirent_name_list) == 1: download_type = 'download-dir' elif len(dirent_name_list) > 1: download_type = 'download-multi' else: error_msg = 'dirents invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # recourse check 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) if not seafile_api.get_dir_id_by_path(repo_id, parent_dir): error_msg = 'Folder %s not found.' % parent_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check repo_folder_permission = check_folder_permission( request, repo_id, parent_dir) if parse_repo_perm(repo_folder_permission).can_download is False: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # get file server access token is_windows = 0 if is_windows_operating_system(request): is_windows = 1 if download_type == 'download-dir': dir_name = dirent_name_list[0].strip('/') full_dir_path = posixpath.join(parent_dir, dir_name) dir_id = seafile_api.get_dir_id_by_path(repo_id, full_dir_path) if not dir_id: error_msg = 'Folder %s not found.' % full_dir_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not json.loads(seafile_api.is_dir_downloadable(repo_id, json.dumps([full_dir_path]), \ request.user.username, repo_folder_permission))['is_downloadable']: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) dir_size = seafile_api.get_dir_size(repo.store_id, repo.version, dir_id) if dir_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: error_msg = 'Unable to download directory "%s": size is too large.' % dir_name return api_error(status.HTTP_400_BAD_REQUEST, error_msg) fake_obj_id = { 'obj_id': dir_id, 'dir_name': dir_name, 'is_windows': is_windows } if download_type == 'download-multi': dirent_list = [] total_size = 0 full_dirent_path_list = [] for dirent_name in dirent_name_list: dirent_name = dirent_name.strip('/') dirent_list.append(dirent_name) full_dirent_path = posixpath.join(parent_dir, dirent_name) current_dirent = seafile_api.get_dirent_by_path( repo_id, full_dirent_path) if not current_dirent: continue if stat.S_ISDIR(current_dirent.mode): total_size += seafile_api.get_dir_size( repo.store_id, repo.version, current_dirent.obj_id) else: total_size += current_dirent.size full_dirent_path_list.append(full_dirent_path) if not json.loads(seafile_api.is_dir_downloadable(repo_id, json.dumps(full_dirent_path_list), \ request.user.username, repo_folder_permission))['is_downloadable']: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if total_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: error_msg = _('Total size exceeds limit.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) fake_obj_id = { 'parent_dir': parent_dir, 'file_list': dirent_list, 'is_windows': is_windows } username = request.user.username try: zip_token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), download_type, username, use_onetime=settings.FILESERVER_TOKEN_ONCE_ONLY) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not zip_token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if len(dirent_name_list) > 10: send_file_access_msg(request, repo, parent_dir, 'web') else: for dirent_name in dirent_name_list: full_dirent_path = posixpath.join(parent_dir, dirent_name) send_file_access_msg(request, repo, full_dirent_path, 'web') return Response({'zip_token': zip_token})
def post(self, request, format=None): """ Only used for download 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 share_link_token = request.data.get('token', None) if not share_link_token: error_msg = 'share_link_token invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) parent_dir = request.data.get('parent_dir', '/') if not parent_dir: error_msg = 'parent_dir invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) dirent_name_list = request.data.get('dirents', None) if not dirent_name_list: error_msg = 'dirent_name invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check try: share_link= FileShare.objects.get(token=share_link_token) except FileShare.DoesNotExist: error_msg = 'Share link %s not found.' % share_link_token return api_error(status.HTTP_404_NOT_FOUND, error_msg) if share_link.s_type != 'd': error_msg = 'Share link %s is not a folder share link.' % 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) full_parent_dir = posixpath.join(normalize_dir_path(share_link.path), parent_dir.strip('/')) full_parent_dir = normalize_dir_path(full_parent_dir) dir_id = seafile_api.get_dir_id_by_path(repo_id, full_parent_dir) if not dir_id: error_msg = 'Folder %s not found.' % parent_dir return api_error(status.HTTP_404_NOT_FOUND, 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) # check share link password if share_link.is_encrypted() and not check_share_link_access(request, share_link_token): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check if has download permission for share link creator if not parse_repo_perm(seafile_api.check_permission_by_path( repo_id, full_parent_dir, share_link.username)).can_download: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check if share link has download permission if not share_link.get_permissions()['can_download']: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # get file server access token is_windows = 0 if is_windows_operating_system(request): is_windows = 1 dirent_list = [] total_size = 0 for dirent_name in dirent_name_list: dirent_name = dirent_name.strip('/') full_dirent_path = posixpath.join(full_parent_dir, dirent_name) current_dirent = seafile_api.get_dirent_by_path(repo_id, full_dirent_path) if not current_dirent: continue if stat.S_ISDIR(current_dirent.mode): total_size += seafile_api.get_dir_size(repo.store_id, repo.version, current_dirent.obj_id) else: total_size += current_dirent.size dirent_list.append(dirent_name) if total_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: error_msg = _('Total size exceeds limit.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not dirent_list: error_msg = 'No valid dirent.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) fake_obj_id = { 'parent_dir': full_parent_dir, 'file_list': dirent_list, 'is_windows': is_windows } try: zip_token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-multi', '', use_onetime=settings.FILESERVER_TOKEN_ONCE_ONLY) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not zip_token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return Response({'zip_token': zip_token})
def get(self, request, format=None): """ Only used for download dir when view dir share link from web. Permission checking: 1. authenticated user OR anonymous user has passed email code check(if necessary); """ # permission check if is_pro_version() and settings.ENABLE_SHARE_LINK_AUDIT: if not request.user.is_authenticated() and \ not request.session.get('anonymous_email'): # if anonymous user has passed email code check, # then his/her email info will be in session. error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # argument check share_link_token = request.GET.get('share_link_token', None) if not share_link_token: error_msg = 'share_link_token invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) req_path = request.GET.get('path', None) if not req_path: error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # recourse check fileshare = FileShare.objects.get_valid_dir_link_by_token(share_link_token) if not fileshare: error_msg = 'share_link_token %s not found.' % share_link_token return api_error(status.HTTP_404_NOT_FOUND, error_msg) if req_path[-1] != '/': req_path += '/' if req_path == '/': real_path = fileshare.path else: real_path = posixpath.join(fileshare.path, req_path.lstrip('/')) if real_path[-1] != '/': real_path += '/' repo_id = fileshare.repo_id repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) dir_id = seafile_api.get_dir_id_by_path(repo_id, real_path) if not dir_id: error_msg = 'Folder %s not found.' % real_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # get file server access token dir_name = repo.name if real_path == '/' else \ os.path.basename(real_path.rstrip('/')) dir_size = seafile_api.get_dir_size( repo.store_id, repo.version, dir_id) if dir_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: error_msg = 'Unable to download directory "%s": size is too large.' % dir_name return api_error(status.HTTP_400_BAD_REQUEST, error_msg) is_windows = 0 if is_windows_operating_system(request): is_windows = 1 fake_obj_id = { 'obj_id': dir_id, 'dir_name': dir_name, 'is_windows': is_windows } username = request.user.username try: zip_token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-dir', username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if request.session.get('anonymous_email'): request.user.username = request.session.get('anonymous_email') send_file_access_msg(request, repo, real_path, 'share-link') return Response({'zip_token': zip_token})
def get(self, request, repo_id, format=None): """ Get file server token for download-dir and download-multi. Permission checking: 1. user with 'r' or 'rw' permission; """ # argument check parent_dir = request.GET.get('parent_dir', None) if not parent_dir: error_msg = 'parent_dir invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) dirent_name_list = request.GET.getlist('dirents', None) if not dirent_name_list: error_msg = 'dirents invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if len(dirent_name_list) == 1: download_type = 'download-dir' elif len(dirent_name_list) > 1: download_type = 'download-multi' else: error_msg = 'dirents invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # recourse check 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) if not seafile_api.get_dir_id_by_path(repo_id, parent_dir): error_msg = 'Folder %s not found.' % parent_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if not check_folder_permission(request, repo_id, parent_dir): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # get file server access token is_windows = 0 if is_windows_operating_system(request): is_windows = 1 if download_type == 'download-dir': dir_name = dirent_name_list[0].strip('/') full_dir_path = posixpath.join(parent_dir, dir_name) dir_id = seafile_api.get_dir_id_by_path(repo_id, full_dir_path) if not dir_id: error_msg = 'Folder %s not found.' % full_dir_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) dir_size = seafile_api.get_dir_size( repo.store_id, repo.version, dir_id) if dir_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: error_msg = 'Unable to download directory "%s": size is too large.' % dir_name return api_error(status.HTTP_400_BAD_REQUEST, error_msg) fake_obj_id = { 'obj_id': dir_id, 'dir_name': dir_name, 'is_windows': is_windows } if download_type == 'download-multi': dirent_list = [] total_size = 0 for dirent_name in dirent_name_list: dirent_name = dirent_name.strip('/') dirent_list.append(dirent_name) full_dirent_path = posixpath.join(parent_dir, dirent_name) current_dirent = seafile_api.get_dirent_by_path(repo_id, full_dirent_path) if not current_dirent: continue if stat.S_ISDIR(current_dirent.mode): total_size += seafile_api.get_dir_size(repo.store_id, repo.version, current_dirent.obj_id) else: total_size += current_dirent.size if total_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: error_msg = _('Total size exceeds limit.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) fake_obj_id = { 'parent_dir': parent_dir, 'file_list': dirent_list, 'is_windows': is_windows } username = request.user.username try: zip_token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), download_type, username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if len(dirent_name_list) > 10: send_file_access_msg(request, repo, parent_dir, 'web') else: for dirent_name in dirent_name_list: full_dirent_path = posixpath.join(parent_dir, dirent_name) send_file_access_msg(request, repo, full_dirent_path, 'web') return Response({'zip_token': zip_token})