diff --git a/seahub/share/models.py b/seahub/share/models.py index 5ce2c890c5..61fda4aa6c 100644 --- a/seahub/share/models.py +++ b/seahub/share/models.py @@ -140,7 +140,7 @@ class FileShare(models.Model): return True if self.s_type == 'f' else False def is_dir_share_link(self): - return False if self.is_file_link() else True + return False if self.is_file_share_link() else True def is_encrypted(self): return True if self.password is not None else False diff --git a/seahub/templates/shared_file_view.html b/seahub/templates/shared_file_view.html index 506dcfccde..85680ee4b3 100644 --- a/seahub/templates/shared_file_view.html +++ b/seahub/templates/shared_file_view.html @@ -33,7 +33,7 @@ {% endif %} {% endif %} {% if not traffic_over_limit %} - {% trans "Download" %} ({{file_size|filesizeformat}}) + {% trans "Download" %} ({{file_size|filesizeformat}}) {% endif %} {% include 'snippets/file_content_html.html' %} diff --git a/seahub/templates/view_shared_dir.html b/seahub/templates/view_shared_dir.html index 0728595996..9995b14584 100644 --- a/seahub/templates/view_shared_dir.html +++ b/seahub/templates/view_shared_dir.html @@ -6,6 +6,7 @@ {% block main_panel %}

{{ dir_name }}

{% trans "Shared by: " %}{{ username|email2nickname }}

+
@@ -13,14 +14,14 @@ {% trans "Current path: "%} {% for name, link in zipped %} {% if not forloop.last %} - {{ name }} / + {{ name }} / {% else %} {{ name }} {% endif %} {% endfor %}

{% if not traffic_over_limit %} - {% trans "ZIP"%} + {% trans "ZIP"%} {% endif %}
@@ -35,13 +36,13 @@ diff --git a/seahub/views/__init__.py b/seahub/views/__init__.py index c2b1345506..6c855e519b 100644 --- a/seahub/views/__init__.py +++ b/seahub/views/__init__.py @@ -1810,6 +1810,7 @@ def i18n(request): res.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang, max_age=30*24*60*60) return res +@login_required def repo_download_dir(request, repo_id): repo = get_repo(repo_id) if not repo: @@ -1827,30 +1828,8 @@ def repo_download_dir(request, repo_id): else: dirname = repo.name - allow_download = False - fileshare_token = request.GET.get('t', '') - from_shared_link = False - shared_by = None - if fileshare_token: # download dir from dir shared link - try: - fileshare = FileShare.objects.get(token=fileshare_token) - except FileShare.DoesNotExist: - raise Http404 - - # Can not download upper dir of shared dir. - allow_download = True if path.startswith(fileshare.path) else False - from_shared_link = True - shared_by = fileshare.username - else: - allow_download = True if check_repo_access_permission( - repo_id, request.user) else False - - if from_shared_link: - # check whether owner's traffic over the limit - if user_traffic_over_limit(fileshare.username): - return render_permission_error(request, - _(u'Unable to access file: share link traffic is used up.')) - + allow_download = True if check_repo_access_permission( + repo_id, request.user) else False if allow_download: dir_id = seafserv_threaded_rpc.get_dirid_by_path (repo.id, repo.head_cmmt_id, @@ -1871,16 +1850,9 @@ def repo_download_dir(request, repo_id): 'download-dir', request.user.username) - if from_shared_link: - try: - send_message('seahub.stats', 'dir-download\t%s\t%s\t%s\t%s' % - (repo_id, shared_by, dir_id, total_size)) - except Exception, e: - logger.error('Error when sending dir-download message: %s' % str(e)) else: return render_error(request, _(u'Unable to download "%s"') % dirname ) - url = gen_file_get_url(token, dirname) return redirect(url) diff --git a/seahub/views/file.py b/seahub/views/file.py index e9216399b7..3e96f6595f 100644 --- a/seahub/views/file.py +++ b/seahub/views/file.py @@ -631,17 +631,20 @@ def _download_file_from_share_link(request, fileshare): repo = get_repo(fileshare.repo_id) if not repo: raise Http404 - share_path = fileshare.path # path for dir share or file share - req_path = request.GET.get('p', '') # path for download file - if req_path: - if not req_path.startswith(share_path): - # permission check + + # Construct real file path if download file in shared dir, otherwise, just + # use path in DB. + if isinstance(fileshare, FileShare) and fileshare.is_dir_share_link(): + req_path = request.GET.get('p', '') + if not req_path: messages.error(request, _(u'Unable to download file, invalid file path')) return HttpResponseRedirect(next) + real_path = posixpath.join(fileshare.path, req_path.lstrip('/')) + else: + real_path = fileshare.path - path = req_path if req_path else share_path - filename = os.path.basename(path) - obj_id = seafile_api.get_file_id_by_path(repo.id, path) + filename = os.path.basename(real_path) + obj_id = seafile_api.get_file_id_by_path(repo.id, real_path) if not obj_id: messages.error(request, _(u'Unable to download file, wrong file path')) return HttpResponseRedirect(next) @@ -651,7 +654,7 @@ def _download_file_from_share_link(request, fileshare): messages.error(request, _(u'Unable to download file, share link traffic is used up.')) return HttpResponseRedirect(next) - send_file_download_msg(request, repo, path, 'share-link') + send_file_download_msg(request, repo, real_path, 'share-link') try: file_size = seafile_api.get_file_size(repo.store_id, repo.version, obj_id) @@ -845,19 +848,27 @@ def view_file_via_shared_dir(request, token): if not repo: raise Http404 - path = request.GET.get('p', '').rstrip('/') - if not path: + # Get file path from frontend, and construct request file path + # with fileshare.path to real path, used to fetch file content by RPC. + req_path = request.GET.get('p', '').rstrip('/') + if not req_path: raise Http404 - if not path.startswith(fileshare.path): # Can not view upper dir of shared dir - raise Http404 - zipped = gen_path_link(path, repo.name) - obj_id = seafile_api.get_file_id_by_path(repo_id, path) + real_path = posixpath.join(fileshare.path, req_path.lstrip('/')) + + # generate dir navigator + # generate dir navigator + if fileshare.path == '/': + zipped = gen_path_link(req_path, repo.name) + else: + zipped = gen_path_link(req_path, os.path.basename(fileshare.path[:-1])) + + obj_id = seafile_api.get_file_id_by_path(repo_id, real_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) + filename = os.path.basename(req_path) filetype, fileext = get_file_type_and_ext(filename) access_token = seafile_api.get_fileserver_access_token(repo.id, obj_id, 'view', '', use_onetime=False) @@ -887,7 +898,7 @@ def view_file_via_shared_dir(request, token): 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) + parent_dir = os.path.dirname(req_path) dirs = seafile_api.list_dir_by_commit_and_path(current_commit.repo_id, current_commit.id, parent_dir) if not dirs: @@ -922,7 +933,8 @@ def view_file_via_shared_dir(request, token): return render_to_response('shared_file_view.html', { 'repo': repo, 'obj_id': obj_id, - 'path': path, + 'from_shared_dir': True, + 'path': req_path, 'file_name': filename, 'file_size': file_size, 'shared_token': token, diff --git a/seahub/views/repo.py b/seahub/views/repo.py index dcfb17a942..05a7777aab 100644 --- a/seahub/views/repo.py +++ b/seahub/views/repo.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import os +import posixpath import logging from django.core.urlresolvers import reverse @@ -34,7 +35,7 @@ from seahub.utils import gen_file_upload_url, is_org_context, \ from seahub.settings import ENABLE_SUB_LIBRARY, FORCE_SERVER_CRYPTO, \ ENABLE_UPLOAD_FOLDER, \ ENABLE_THUMBNAIL, THUMBNAIL_ROOT, THUMBNAIL_DEFAULT_SIZE, PREVIEW_DEFAULT_SIZE - +from seahub.utils import gen_file_get_url from seahub.utils.file_types import IMAGE from seahub.thumbnail.utils import get_thumbnail_src, allow_generate_thumbnail @@ -359,6 +360,43 @@ def repo_history_view(request, repo_id): }, context_instance=RequestContext(request)) ########## shared dir/uploadlink +def _download_dir_from_share_link(request, fileshare, repo, real_path): + # check whether owner's traffic over the limit + if user_traffic_over_limit(fileshare.username): + return render_error( + request, _(u'Unable to access file: share link traffic is used up.')) + + shared_by = fileshare.username + if fileshare.path == '/': + dirname = repo.name + else: + dirname = os.path.basename(real_path.rstrip('/')) + + dir_id = seafile_api.get_dir_id_by_path(repo.id, real_path) + + try: + total_size = seaserv.seafserv_threaded_rpc.get_dir_size( + repo.store_id, repo.version, dir_id) + except Exception as e: + logger.error(str(e)) + return render_error(request, _(u'Internal Error')) + + if total_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: + return render_error(request, _(u'Unable to download directory "%s": size is too large.') % dirname) + + token = seafile_api.get_fileserver_access_token(repo.id, + dir_id, + 'download-dir', + request.user.username) + + try: + seaserv.send_message('seahub.stats', 'dir-download\t%s\t%s\t%s\t%s' % + (repo.id, shared_by, dir_id, total_size)) + except Exception as e: + logger.error('Error when sending dir-download message: %s' % str(e)) + + return HttpResponseRedirect(gen_file_get_url(token, dirname)) + def view_shared_dir(request, token): assert token is not None # Checked by URLconf @@ -387,13 +425,19 @@ def view_shared_dir(request, token): username = fileshare.username repo_id = fileshare.repo_id - path = request.GET.get('p', '') - path = fileshare.path if not path else path - if path[-1] != '/': # Normalize dir path - path += '/' - if not path.startswith(fileshare.path): - path = fileshare.path # Can not view upper dir of shared dir + # Get path from frontend, use '/' if missing, and construct request path + # with fileshare.path to real path, used to fetch dirents by RPC. + req_path = request.GET.get('p', '/') + 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] != '/': # Normalize dir path + real_path += '/' repo = get_repo(repo_id) if not repo: @@ -403,17 +447,28 @@ def view_shared_dir(request, token): if not seafile_api.get_dir_id_by_path(repo.id, fileshare.path): return render_error(request, _('"%s" does not exist.') % fileshare.path) - if path == '/': + # download shared dir + if request.GET.get('dl', '') == '1': + return _download_dir_from_share_link(request, fileshare, repo, + real_path) + + if fileshare.path == '/': + # use repo name as dir name if share whole library dir_name = repo.name else: - dir_name = os.path.basename(path[:-1]) + dir_name = os.path.basename(real_path[:-1]) current_commit = seaserv.get_commits(repo_id, 0, 1)[0] file_list, dir_list, dirent_more = get_repo_dirents(request, repo, - current_commit, path) - zipped = gen_path_link(path, repo.name) + current_commit, real_path) - if path == fileshare.path: # When user view the shared dir.. + # generate dir navigator + if fileshare.path == '/': + zipped = gen_path_link(req_path, repo.name) + else: + zipped = gen_path_link(req_path, os.path.basename(fileshare.path[:-1])) + + if req_path == '/': # When user view the root of shared dir.. # increase shared link view_cnt, fileshare = FileShare.objects.get(token=token) fileshare.view_cnt = F('view_cnt') + 1 @@ -430,7 +485,7 @@ def view_shared_dir(request, token): return render_to_response('view_shared_dir.html', { 'repo': repo, 'token': token, - 'path': path, + 'path': req_path, 'username': username, 'dir_name': dir_name, 'file_list': file_list, diff --git a/tests/seahub/views/test_file.py b/tests/seahub/views/test_shared_file.py similarity index 90% rename from tests/seahub/views/test_file.py rename to tests/seahub/views/test_shared_file.py index 30c2167d89..2178ff9e22 100644 --- a/tests/seahub/views/test_file.py +++ b/tests/seahub/views/test_shared_file.py @@ -1,3 +1,4 @@ +import os from django.core.urlresolvers import reverse from django.test import TestCase @@ -24,21 +25,19 @@ class SharedFileTest(TestCase, Fixtures): resp = self.client.get(reverse('view_shared_file', args=[self.fs.token])) self.assertEqual(200, resp.status_code) self.assertTemplateUsed(resp, 'shared_file_view.html') - self.assertContains(resp, self.file) - dl_url_param = '?p=%s&dl=1' % self.file - self.assertContains(resp, dl_url_param) + self.assertContains(resp, os.path.basename(self.file)) + dl_url_tag = '' + self.assertContains(resp, dl_url_tag) def test_can_download(self): - dl_url = reverse('view_shared_file', args=[self.fs.token]) + \ - '?p=%s&dl=1' % self.file + dl_url = reverse('view_shared_file', args=[self.fs.token]) + '?dl=1' resp = self.client.get(dl_url) self.assertEqual(302, resp.status_code) assert '8082/files/' in resp.get('location') def test_can_view_raw(self): - dl_url = reverse('view_shared_file', args=[self.fs.token]) + \ - '?p=%s&raw=1' % self.file + dl_url = reverse('view_shared_file', args=[self.fs.token]) + '?raw=1' resp = self.client.get(dl_url) self.assertEqual(302, resp.status_code) assert '8082/files/' in resp.get('location') @@ -65,10 +64,10 @@ class FileViaSharedDirTest(TestCase, Fixtures): ) self.assertEqual(200, resp.status_code) self.assertTemplateUsed(resp, 'shared_file_view.html') - self.assertContains(resp, self.file) - dl_url_param = '?p=%s&dl=1' % self.file - self.assertContains(resp, dl_url_param) + self.assertContains(resp, os.path.basename(self.file)) + dl_url_tag = '' % self.file + self.assertContains(resp, dl_url_tag) def test_can_download(self): dl_url = reverse('view_file_via_shared_dir', args=[self.fs.token]) + \
{% trans - {{ dirent.obj_name }} + {{ dirent.obj_name }} {% if not traffic_over_limit %} - + {% endif %} @@ -62,7 +63,7 @@ {% endif %} - {{ dirent.props.obj_name }} + {{ dirent.props.obj_name }} {{ dirent.file_size|filesizeformat }}