mirror of
https://github.com/haiwen/seahub.git
synced 2025-08-01 23:38:37 +00:00
Merge branch 'feature/share_dir'
Conflicts: utils/__init__.py views.py
This commit is contained in:
commit
37eacd22c3
@ -896,10 +896,14 @@ textarea:-moz-placeholder {/* for FF */
|
||||
.repo-op .op-btn {
|
||||
*margin-left:5px;/* for ie 7*/
|
||||
}
|
||||
#upload-file {
|
||||
#upload-file{
|
||||
padding-left:19px;
|
||||
background-image:url('../img/upload.png?v=1');
|
||||
}
|
||||
#download-dir {
|
||||
padding-left:19px;
|
||||
background-image:url('../img/download-blue.png?t=1352500800');
|
||||
}
|
||||
#add-new-dir {
|
||||
padding-left:23px;
|
||||
background-image:url('../img/folder-add.png');
|
||||
@ -1364,7 +1368,8 @@ textarea:-moz-placeholder {/* for FF */
|
||||
color:#444;
|
||||
text-align:right;
|
||||
}
|
||||
#shared-link {
|
||||
#shared-link,
|
||||
#shared-link-text {
|
||||
border:0;
|
||||
}
|
||||
.file-op {
|
||||
|
BIN
media/img/download-blue.png
Normal file
BIN
media/img/download-blue.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 503 B After Width: | Height: | Size: 3.1 KiB |
@ -12,7 +12,7 @@ class AnonymousShare(models.Model):
|
||||
|
||||
class FileShare(models.Model):
|
||||
"""
|
||||
Model used for file share link.
|
||||
Model used for file or dir shared link.
|
||||
"""
|
||||
username = models.EmailField(max_length=255, db_index=True)
|
||||
repo_id = models.CharField(max_length=36, db_index=True)
|
||||
@ -20,3 +20,4 @@ class FileShare(models.Model):
|
||||
token = models.CharField(max_length=10, unique=True)
|
||||
ctime = models.DateTimeField(default=datetime.datetime.now)
|
||||
view_cnt = models.IntegerField(default=0)
|
||||
s_type = models.CharField(max_length=2, db_index=True, default='f') # `f` or `d`
|
||||
|
@ -80,18 +80,22 @@
|
||||
{% if fileshares %}
|
||||
<table class="sharelink-list">
|
||||
<tr>
|
||||
<th width="45%">{% trans "File"%}</th>
|
||||
<th width="45%">{% trans "File or Folder"%}</th>
|
||||
<th width="25%">{% trans "Library"%}</th>
|
||||
<th width="15%">{% trans "Visits"%}</th>
|
||||
<th width="15%">{% trans "Operations"%}</th>
|
||||
</tr>
|
||||
{% for fs in fileshares %}
|
||||
<tr>
|
||||
<td><a href="{{ SITE_ROOT }}repo/{{ fs.repo.id }}/files/?p={{ fs.path|urlencode }}">{{ fs.filename }}</a></td>
|
||||
{% if fs.s_type == 'f' %}
|
||||
<td><a href="{% url 'repo_view_file' fs.repo.id %}?p={{ fs.path|urlencode }}">{{ fs.filename }}</a></td>
|
||||
{% else %}
|
||||
<td><a href="{% url 'repo' fs.repo.id %}?p={{ fs.path|urlencode }}">{{ fs.filename }}</a></td>
|
||||
{% endif %}
|
||||
<td><a href="{{ SITE_ROOT }}repo/{{ fs.repo.id }}/">{{ fs.repo.name }}</a></td>
|
||||
<td>{{ fs.view_cnt }}</td>
|
||||
<td>
|
||||
<a href="#" class="op view-link" data="{{ fs.token }}">{% trans "View" %}</a>
|
||||
<a href="#" class="op view-link" data="{{ fs.shared_link }}">{% trans "View" %}</a>
|
||||
<a class="op" href="{% url 'remove_shared_link' %}?t={{ fs.token }}">{% trans "Remove"%}</a>
|
||||
</td>
|
||||
</tr>
|
||||
@ -173,8 +177,7 @@ $('.cancel-share').click(function() {
|
||||
});
|
||||
|
||||
$(".view-link").click(function() {
|
||||
var token = $(this).attr('data'),
|
||||
link = '{{ protocol }}://' + '{{ domain }}{{ SITE_ROOT }}f/' + token + '/';
|
||||
var link = $(this).attr('data');
|
||||
$('#link').before('<p class="hide">' + link + '</p>');
|
||||
$('#shared-link').val(link).css('width', $('#link').prev().width() + 2);
|
||||
$("#link").modal({appendTo:'#main'});
|
||||
|
@ -3,7 +3,8 @@ import os
|
||||
import simplejson as json
|
||||
from django.core.mail import send_mail
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponse, HttpResponseRedirect, Http404
|
||||
from django.http import HttpResponse, HttpResponseRedirect, Http404, \
|
||||
HttpResponseBadRequest
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import Context, loader, RequestContext
|
||||
from django.utils.translation import ugettext as _
|
||||
@ -25,12 +26,13 @@ from seahub.contacts.signals import mail_sended
|
||||
from seahub.share.models import FileShare
|
||||
from seahub.views import validate_owner, is_registered_user
|
||||
from seahub.utils import render_permission_error, string2list, render_error, \
|
||||
gen_token
|
||||
gen_token, gen_shared_link
|
||||
|
||||
try:
|
||||
from seahub.settings import CLOUD_MODE
|
||||
except ImportError:
|
||||
CLOUD_MODE = False
|
||||
from seahub.settings import SITE_ROOT
|
||||
|
||||
@login_required
|
||||
def share_repo(request):
|
||||
@ -176,7 +178,6 @@ def repo_remove_share(request):
|
||||
|
||||
next = request.META.get('HTTP_REFERER', None)
|
||||
if not next:
|
||||
from seahub.settings import SITE_ROOT
|
||||
next = SITE_ROOT
|
||||
|
||||
return HttpResponseRedirect(next)
|
||||
@ -233,13 +234,17 @@ def share_admin(request):
|
||||
# link.repo_name = repo.name
|
||||
# link.remain_time = anon_share_token_generator.get_remain_time(link.token)
|
||||
|
||||
# File shared links
|
||||
# Shared links
|
||||
fileshares = FileShare.objects.filter(username=username)
|
||||
p_fileshares = [] # personal file share
|
||||
for fs in fileshares:
|
||||
if is_personal_repo(fs.repo_id):
|
||||
# only list files in personal repos
|
||||
fs.filename = os.path.basename(fs.path)
|
||||
if is_personal_repo(fs.repo_id): # only list files in personal repos
|
||||
if fs.s_type == 'f':
|
||||
fs.filename = os.path.basename(fs.path)
|
||||
fs.shared_link = gen_shared_link(request, fs.token, 'f')
|
||||
else:
|
||||
fs.filename = os.path.basename(fs.path[:-1])
|
||||
fs.shared_link = gen_shared_link(request, fs.token, 'd')
|
||||
fs.repo = get_repo(fs.repo_id)
|
||||
p_fileshares.append(fs)
|
||||
|
||||
@ -248,8 +253,6 @@ def share_admin(request):
|
||||
"shared_repos": shared_repos,
|
||||
# "out_links": out_links,
|
||||
"fileshares": p_fileshares,
|
||||
"protocol": request.is_secure() and 'https' or 'http',
|
||||
"domain": RequestSite(request).domain,
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
@login_required
|
||||
@ -371,17 +374,32 @@ def remove_anonymous_share(request, token):
|
||||
@login_required
|
||||
def get_shared_link(request):
|
||||
"""
|
||||
Handle ajax request to generate file shared link.
|
||||
Handle ajax request to generate file or dir shared link.
|
||||
"""
|
||||
if not request.is_ajax():
|
||||
raise Http404
|
||||
|
||||
content_type = 'application/json; charset=utf-8'
|
||||
|
||||
repo_id = request.GET.get('repo_id')
|
||||
path = request.GET.get('p', '/')
|
||||
if path[-1] == '/':
|
||||
path = path[:-1]
|
||||
repo_id = request.GET.get('repo_id', '')
|
||||
share_type = request.GET.get('type', 'f') # `f` or `d`
|
||||
path = request.GET.get('p', '')
|
||||
if not (repo_id and path):
|
||||
err = _('Invalid arguments')
|
||||
data = json.dumps([{'error': err}])
|
||||
return HttpResponse(data, status=400, content_type=content_type)
|
||||
|
||||
if share_type == 'f':
|
||||
if path[-1] == '/': # cut out last '/' at end of path
|
||||
path = path[:-1]
|
||||
else:
|
||||
if path == '/': # can not share root dir
|
||||
err = _('Can not share root dir.')
|
||||
data = json.dumps([{'error': err}])
|
||||
return HttpResponse(data, status=400, content_type=content_type)
|
||||
else:
|
||||
if path[-1] != '/': # append '/' at end of path
|
||||
path += '/'
|
||||
|
||||
l = FileShare.objects.filter(repo_id=repo_id).filter(
|
||||
username=request.user.username).filter(path=path)
|
||||
@ -396,6 +414,7 @@ def get_shared_link(request):
|
||||
fs.repo_id = repo_id
|
||||
fs.path = path
|
||||
fs.token = token
|
||||
fs.s_type = 'f' if share_type == 'f' else 'd'
|
||||
|
||||
try:
|
||||
fs.save()
|
||||
@ -403,8 +422,10 @@ def get_shared_link(request):
|
||||
err = _('Failed to get the link, please retry it.')
|
||||
data = json.dumps([{'error': err}])
|
||||
return HttpResponse(data, status=500, content_type=content_type)
|
||||
|
||||
data = json.dumps([{'token': token}])
|
||||
|
||||
shared_link = gen_shared_link(request, token, fs.s_type)
|
||||
|
||||
data = json.dumps([{'token': token, 'shared_link': shared_link}])
|
||||
return HttpResponse(data, status=200, content_type=content_type)
|
||||
|
||||
@login_required
|
||||
|
@ -156,122 +156,9 @@ $('#view-original, #download').click(function() {
|
||||
$('#edit').click(function() {
|
||||
location.href = $(this).attr('data');
|
||||
});
|
||||
function showLink() {
|
||||
$('#get-shared-link').addClass('hide');
|
||||
$('#shared-link, #send-shared-link, #rm-shared-link').removeClass('hide');
|
||||
}
|
||||
function hideLink() {
|
||||
$('#shared-link, #send-shared-link, #rm-shared-link').addClass('hide');
|
||||
$('#get-shared-link').removeClass('hide');
|
||||
}
|
||||
function setLinkWidth() {
|
||||
var link = $('#shared-link');
|
||||
link.before('<p class="hide">' + link.val() + '</p>');
|
||||
link.css('width', link.prev().width() + 2);
|
||||
link.prev().remove();
|
||||
}
|
||||
if ($.trim($('#shared-link').val())) {
|
||||
setLinkWidth();
|
||||
}
|
||||
|
||||
{% if fileshare.token %}
|
||||
showLink();
|
||||
{% else %}
|
||||
hideLink();
|
||||
{% endif %}
|
||||
|
||||
$('#get-shared-link').click(function() {
|
||||
var url = $(this).attr('data');
|
||||
$.ajax({
|
||||
url: url,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
success: function(data) {
|
||||
if (data.length > 0) {
|
||||
var t = data[0]['token'];
|
||||
$('#rm-shared-link').attr('data', '{% url 'remove_shared_link' %}?t=' + t);
|
||||
$('#shared-link, input[name="file_shared_link"]').val('{{ protocol }}://{{ domain }}{{ SITE_ROOT }}f/' + t + '/');
|
||||
setLinkWidth();
|
||||
showLink();
|
||||
}
|
||||
},
|
||||
error: function(xhr, ajaxOptions, thrownError) {
|
||||
var jsonVal = jQuery.parseJSON(xhr.responseText);
|
||||
feedback(jsonVal[0]['error'], 'error');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#rm-shared-link').click(function() {
|
||||
var url = $(this).attr('data');
|
||||
$.ajax({
|
||||
url: url,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
success: function(data) {
|
||||
hideLink();
|
||||
$('#shared-link').val('');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var share_list = [];
|
||||
{% for contact in contacts %}
|
||||
share_list.push({value:'{{ contact.contact_email }}', label:'{{ contact.contact_email }}'});
|
||||
{% endfor %}
|
||||
$('#send-shared-link').click(function() {
|
||||
$("#link-send-form").modal({appendTo: "#main", focus: false});
|
||||
$('#simplemodal-container').css('height', 'auto');
|
||||
addAutocomplete('#link-send-input', '#link-send-form', share_list);
|
||||
});
|
||||
|
||||
$("#link-send-form").submit(function(event) {
|
||||
var form = $(this),
|
||||
file_shared_link = form.children('input[name="file_shared_link"]').val(),
|
||||
email = $.trim(form.children('textarea[name="email"]').val()),
|
||||
submit_btn = form.children('input[type="submit"]');
|
||||
|
||||
if (!email) {
|
||||
apply_form_error('link-send-form', '{% trans "Please input at least an email." %}');
|
||||
return false;
|
||||
}
|
||||
|
||||
disable(submit_btn);
|
||||
$('#link-send-form .error').addClass('hide');
|
||||
$('#sending').removeClass('hide');
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "{% url 'send_shared_link' %}",
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
beforeSend: prepareCSRFToken,
|
||||
data: {file_shared_link: file_shared_link, email: email},
|
||||
success: function(data) {
|
||||
$.modal.close();
|
||||
feedback('{% trans "Successfully sent." %}', "success");
|
||||
},
|
||||
error: function(data, textStatus, jqXHR) {
|
||||
$('#sending').addClass('hide');
|
||||
enable(submit_btn);
|
||||
var errors = $.parseJSON(data.responseText);
|
||||
$.each(errors, function(index, value) {
|
||||
if (index == 'error') {
|
||||
apply_form_error('link-send-form', value);
|
||||
} else {
|
||||
apply_form_error('link-send-form', value[0]);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
$('#shared-link').click(function() {
|
||||
$(this).select();
|
||||
});
|
||||
//share link
|
||||
{% include "snippets/shared_link_js.html" %}
|
||||
|
||||
//star
|
||||
$('#star').click(function() {
|
||||
|
@ -17,10 +17,18 @@
|
||||
<div class="w100 ovhd">
|
||||
<h2 class="fleft">{{repo.props.name}}</h2>
|
||||
<div class="fright">
|
||||
{% if path != '/' %}
|
||||
<input id="shared-link" class="hide" type="text" readonly="readonly" value="{{ dir_shared_link }}" />
|
||||
<button data="{% url 'get_shared_link' %}?repo_id={{ repo.id }}&p={{ path|urlencode }}&type=d" id="get-shared-link">{% trans "Share link"%}</button>
|
||||
<button id="send-shared-link" class="hide">{% trans "Send"%}</button>
|
||||
<button data="{% url 'remove_shared_link' %}?t={{ fileshare.token }}" id="rm-shared-link" class="hide">{% trans "Delete"%}</button>
|
||||
{% endif %}
|
||||
{% if path == '/' %}
|
||||
<button id="repo-download-btn">{% trans "Download"%}</button>
|
||||
{% if user_perm == 'rw' %}
|
||||
<button id="recycle-btn" data="{% url 'repo_recycle_view' repo.id %}">{% trans "Trash"%}</button>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if user_perm == 'r' %}
|
||||
@ -80,13 +88,16 @@
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% if user_perm == 'rw' %}
|
||||
<div class="repo-op fright">
|
||||
{% if user_perm and path != '/' %}
|
||||
<button data="{% url 'repo_download_dir' repo.id %}?p={{ path|urlencode }}" id="download-dir" class="op-btn">{% trans "Download"%}</button>
|
||||
{% endif %}
|
||||
{% if user_perm == 'rw' %}
|
||||
<button data="{{ SITE_ROOT }}repo/upload_file/{{repo.id}}/?p={{ path|urlencode }}" id="upload-file" class="op-btn">{% trans "Upload"%}</button>
|
||||
<button id="add-new-dir" class="op-btn">{% trans "New Directory"%}</button>
|
||||
<button id="add-new-file" class="op-btn">{% trans "New File"%}</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<!-- /.repo-file-list-topbar -->
|
||||
<table class="repo-file-list">
|
||||
@ -119,7 +130,8 @@
|
||||
{% if user_perm %}
|
||||
<div class="repo-file-op vh">
|
||||
<div class="displayed-op">
|
||||
<a class="op" href="{{ SITE_ROOT }}repo/download_dir/{{ repo.id }}/?parent={{ path|urlencode }}&dirname={{ dirent.obj_name|urlencode }}">{% trans 'Download' %}</a>
|
||||
<a class="op" href="{% url 'repo_download_dir' repo.id %}?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}">{% trans 'Download' %}</a>
|
||||
<a class="op file-share" href="#" data-name="{{ dirent.obj_name }}" data-link="{{ dirent.sharelink }}" data-token="{{ dirent.sharetoken }}" data-type="d">{% trans "Share" %}</a>
|
||||
</div>
|
||||
{% if user_perm == 'rw' %}
|
||||
<img src="{{ MEDIA_URL }}img/dropdown-arrow.png" title="{% trans 'More operations'%}" alt="{% trans 'More operations'%}" class="more-op-icon" data="no-popup" />
|
||||
@ -298,15 +310,16 @@
|
||||
|
||||
<div id="file-share" class="hide">
|
||||
<h3>{% trans 'Share' %} <span class="op-target"></span></h3>
|
||||
<p>{% trans 'Link: ' %}<input type="text" readonly="readonly" id="shared-link" /></p>
|
||||
<p>{% trans 'Link: ' %}<input type="text" readonly="readonly" id="shared-link-text" /></p>
|
||||
<button id="send-link">{% trans 'Send' %}</button>
|
||||
<form id="link-send-form" class="hide">
|
||||
<label>{% trans "Send to:"%}</label><br />
|
||||
<textarea id="link-send-input" name="email" placeholder="{% trans "Emails, Seperated by ','"%}"></textarea><br />
|
||||
<input type="hidden" name="file_shared_link" value="" />
|
||||
<input type="submit" value="{% trans "Submit"%}" class="submit" />
|
||||
<p class="error hide"></p>
|
||||
<p id="sending" class="hide">{% trans "Sending..."%}</p>
|
||||
<form id="link-send-form" action="" method="post" class="hide">
|
||||
<h3>Send Link</h3>
|
||||
<label>{% trans "Send to:"%}</label><br />
|
||||
<textarea id="link-send-input" name="email" placeholder="{% trans "Emails, Seperated by ','"%}"></textarea><br />
|
||||
<input type="hidden" name="file_shared_link" value="{{ dir_shared_link }}" />
|
||||
<input type="submit" value="{% trans "Submit"%}" class="submit" />
|
||||
<p class="error hide"></p>
|
||||
<p id="sending" class="hide">{% trans "Sending..."%}</p>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@ -602,7 +615,7 @@ $('#add-new-file-form').submit(function() {
|
||||
$('#add-new-dir-form').submit(function() {
|
||||
var new_dir = $(this).find('input[name="new_dir_name"]').val();
|
||||
if (!$.trim(new_dir)) {
|
||||
apply_form_error('add-new-dir-form', "{% trans "Directory name can't be empty" %}");
|
||||
apply_form_error('add-new-dir-form', "{% trans "Directory name can not be empty" %}");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -755,24 +768,31 @@ $('.file-share').click(function() {
|
||||
var filename = $(this).data('name');
|
||||
function showPopup(link) {
|
||||
$('#file-share .op-target').html(trimFilename(filename, 30));
|
||||
$('#shared-link, #link-send-form input[name="file_shared_link"]').val(link);
|
||||
$('#shared-link-text, #link-send-form input[name="file_shared_link"]').val(link);
|
||||
$('#main').append('<p id="linkwidth" class="hide">' + link + '</p>');
|
||||
$('#shared-link').css({'width':$('#linkwidth').width() + 2});
|
||||
$('#file-share').modal({'focus':false}); // in ff: if 'focus' is true, 'shared-link' gets the focus
|
||||
$('#shared-link-text').css({'width':$('#linkwidth').width() + 2});
|
||||
$('#file-share').modal({'focus':false}); // in ff: if 'focus' is true, 'shared-link-text' gets the focus
|
||||
$('#linkwidth').remove();
|
||||
$('#simplemodal-container').css({'width':'auto', 'height':'auto'});
|
||||
}
|
||||
if ($(this).data('link')) {
|
||||
showPopup($(this).data('link'));
|
||||
} else {
|
||||
var aj_url = '';
|
||||
if ($(this).data('type') == 'd') {
|
||||
aj_url = '{% url 'get_shared_link' %}?repo_id={{ repo.id }}&p={{ path|urlencode }}' + e(filename) + '&type=d';
|
||||
} else {
|
||||
aj_url = '{% url 'get_shared_link' %}?repo_id={{ repo.id }}&p={{ path|urlencode }}' + e(filename);
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: '{% url 'get_shared_link' %}?repo_id={{ repo.id }}&p={{ path|urlencode }}' + e(filename),
|
||||
url: aj_url,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
success: function(data) {
|
||||
if (data.length > 0) {
|
||||
showPopup('{{ protocol }}://{{ domain }}{{ SITE_ROOT }}f/' + data[0]['token'] + '/');
|
||||
showPopup(data[0]['shared_link']);
|
||||
}
|
||||
},
|
||||
error: function(xhr, ajaxOptions, thrownError) {
|
||||
@ -839,9 +859,15 @@ $("#link-send-form").submit(function() {
|
||||
});
|
||||
return false;
|
||||
});
|
||||
$('#shared-link').click(function() { $(this).select(); });
|
||||
$('#shared-link-text').click(function() { $(this).select(); });
|
||||
|
||||
$('#download-dir').click(function() {
|
||||
location.href = $(this).attr('data');
|
||||
});
|
||||
{% include "snippets/shared_link_js.html" %}
|
||||
{% include "snippets/list_commit_detail.html" %}
|
||||
{% include "snippets/bottom_bar.html" %}
|
||||
|
||||
</script>
|
||||
{% include 'snippets/file_upload_progress_js.html' %}
|
||||
{% endblock %}
|
||||
|
@ -13,7 +13,20 @@
|
||||
<h2 id="view-hd">{{ file_name }}</h2>
|
||||
<div id="file">
|
||||
<div id="file-op">
|
||||
{% if zipped %}
|
||||
<p class="path fleft">
|
||||
{% trans "Current path: "%}
|
||||
{% for name, link in zipped %}
|
||||
{% if not forloop.last %}
|
||||
<a href="{{ SITE_ROOT }}d/{{ token }}/?p={{ link|urlencode }}">{{ name }}</a> /
|
||||
{% else %}
|
||||
{{ name }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% else %}
|
||||
<p class="fleft">{% trans "Shared by: " %}{{ username|email2nickname }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% if filetype == 'Text' or filetype == 'Image' or filetype == 'SVG' or filetype == 'Markdown' %}
|
||||
<button data="{{ SITE_ROOT }}repo/{{ repo.id }}/{{ obj_id }}/?file_name={{ file_name }}&op=view&t={{ shared_token }}" id="view-original">{% trans "Raw" %}</button>
|
||||
|
117
templates/snippets/shared_link_js.html
Normal file
117
templates/snippets/shared_link_js.html
Normal file
@ -0,0 +1,117 @@
|
||||
{% load i18n %}
|
||||
{% load url from future %}
|
||||
function showLink() {
|
||||
$('#get-shared-link').addClass('hide');
|
||||
$('#shared-link, #send-shared-link, #rm-shared-link').removeClass('hide');
|
||||
}
|
||||
function hideLink() {
|
||||
$('#shared-link, #send-shared-link, #rm-shared-link').addClass('hide');
|
||||
$('#get-shared-link').removeClass('hide');
|
||||
}
|
||||
function setLinkWidth() {
|
||||
var link = $('#shared-link');
|
||||
link.before('<p class="hide">' + link.val() + '</p>');
|
||||
link.css('width', link.prev().width() + 2);
|
||||
link.prev().remove();
|
||||
}
|
||||
if ($.trim($('#shared-link').val())) {
|
||||
setLinkWidth();
|
||||
}
|
||||
{% if fileshare.token %}
|
||||
showLink();
|
||||
{% else %}
|
||||
hideLink();
|
||||
{% endif %}
|
||||
|
||||
$('#get-shared-link').click(function() {
|
||||
var url = $(this).attr('data');
|
||||
$.ajax({
|
||||
url: url,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
success: function(data) {
|
||||
if (data.length > 0) {
|
||||
var t = data[0]['token'];
|
||||
$('#rm-shared-link').attr('data', '{% url 'remove_shared_link' %}?t=' + t);
|
||||
$('#shared-link, input[name="file_shared_link"]').val(data[0]['shared_link']);
|
||||
setLinkWidth();
|
||||
showLink();
|
||||
}
|
||||
},
|
||||
error: function(xhr, ajaxOptions, thrownError) {
|
||||
var jsonVal = jQuery.parseJSON(xhr.responseText);
|
||||
feedback(jsonVal[0]['error'], 'error');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#rm-shared-link').click(function() {
|
||||
var url = $(this).attr('data');
|
||||
$.ajax({
|
||||
url: url,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
success: function(data) {
|
||||
hideLink();
|
||||
$('#shared-link').val('');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var share_list = [];
|
||||
{% for contact in contacts %}
|
||||
share_list.push({value:'{{ contact.contact_email }}', label:'{{ contact.contact_email }}'});
|
||||
{% endfor %}
|
||||
$('#send-shared-link').click(function() {
|
||||
$("#link-send-form").modal({appendTo: "#main", focus: false});
|
||||
$('#simplemodal-container').css('height', 'auto');
|
||||
addAutocomplete('#link-send-input', '#link-send-form', share_list);
|
||||
});
|
||||
|
||||
$("#link-send-form").submit(function(event) {
|
||||
var form = $(this),
|
||||
file_shared_link = form.children('input[name="file_shared_link"]').val(),
|
||||
email = $.trim(form.children('textarea[name="email"]').val()),
|
||||
submit_btn = form.children('input[type="submit"]');
|
||||
|
||||
if (!email) {
|
||||
apply_form_error('link-send-form', '{% trans "Please input at least an email." %}');
|
||||
return false;
|
||||
}
|
||||
|
||||
disable(submit_btn);
|
||||
$('#link-send-form .error').addClass('hide');
|
||||
$('#sending').removeClass('hide');
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "{% url 'send_shared_link' %}",
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
beforeSend: prepareCSRFToken,
|
||||
data: {file_shared_link: file_shared_link, email: email},
|
||||
success: function(data) {
|
||||
$.modal.close();
|
||||
feedback('{% trans "Successfully sent." %}', "success");
|
||||
},
|
||||
error: function(data, textStatus, jqXHR) {
|
||||
$('#sending').addClass('hide');
|
||||
enable(submit_btn);
|
||||
var errors = $.parseJSON(data.responseText);
|
||||
$.each(errors, function(index, value) {
|
||||
if (index == 'error') {
|
||||
apply_form_error('link-send-form', value);
|
||||
} else {
|
||||
apply_form_error('link-send-form', value[0]);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
$('#shared-link').click(function() {
|
||||
$(this).select();
|
||||
});
|
157
templates/view_shared_dir.html
Normal file
157
templates/view_shared_dir.html
Normal file
@ -0,0 +1,157 @@
|
||||
{% extends base_template %}
|
||||
|
||||
{% load seahub_tags i18n %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block info_bar_message %}
|
||||
{% endblock %}
|
||||
|
||||
{% block main_panel %}
|
||||
<h2 id="view-hd">{{ dir_name }}</h2>
|
||||
<div>
|
||||
<p>{% trans "Shared by: " %}{{ username|email2nickname }}</p>
|
||||
</div>
|
||||
|
||||
<div class="repo-file-list-outer-container">
|
||||
<div class="repo-file-list-inner-container">
|
||||
<div class="repo-file-list-topbar ovhd">
|
||||
<p class="path fleft">
|
||||
{% trans "Current path: "%}
|
||||
{% for name, link in zipped %}
|
||||
{% if not forloop.last %}
|
||||
<a href="{{ SITE_ROOT }}d/{{ token }}/?p={{ link|urlencode }}">{{ name }}</a> /
|
||||
{% else %}
|
||||
{{ name }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
<div class="repo-op fright">
|
||||
<button data="{% url 'repo_download_dir' repo.id %}?p={{ path|urlencode }}&t={{ token }}" id="download-dir" class="op-btn">{% trans "Download"%}</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- /.repo-file-list-topbar -->
|
||||
<table class="repo-file-list">
|
||||
<tr>
|
||||
<th width="3%"></th>
|
||||
<th width="5%"></th>
|
||||
<th width="53%">{% trans "Name"%}</th>
|
||||
<th width="10%">{% trans "Size"%}</th>
|
||||
<th width="29%">{% trans "Operations"%}</th>
|
||||
</tr>
|
||||
|
||||
{% for dirent in dir_list %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="icon-container"><img src="{{ MEDIA_URL }}img/folder-icon-24.png" alt="{% trans "Directory icon"%}" /></td>
|
||||
<td>
|
||||
<a href="{{ SITE_ROOT }}d/{{ token }}/?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}">{{ dirent.obj_name }}</a>
|
||||
</td>
|
||||
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="repo-file-op vh">
|
||||
<div class="displayed-op">
|
||||
<a class="op" href="{% url 'repo_download_dir' repo.id %}?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}&t={{token}}">{% trans 'Download' %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
{% for dirent in file_list %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="icon-container"><img src="{{ MEDIA_URL }}img/file/{{ dirent.obj_name|file_icon_filter }}" alt="{% trans "File"%}" /></td>
|
||||
<td>
|
||||
<a class="op" href="{{ SITE_ROOT }}d/{{ token }}/files/?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}">{{ dirent.props.obj_name }}</a>
|
||||
</td>
|
||||
|
||||
<td>{{ dirent.file_size|filesizeformat }}</td>
|
||||
<td>
|
||||
<div class="repo-file-op vh">
|
||||
<div class="displayed-op">
|
||||
<a class="op" href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/{{ dirent.props.obj_id }}/?file_name={{ dirent.props.obj_name }}&op=download">{% trans "Download"%}</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<!-- /.repo-file-list -->
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_script %}
|
||||
<script type="text/javascript">
|
||||
var popup_tr = ''; // the tr which the shown popup belongs to
|
||||
var no_file_op_popup = true;
|
||||
$("tr:gt(0)").unbind().hover( // remove previously binded hover handler at first
|
||||
function() {
|
||||
if (no_file_op_popup) {
|
||||
$(this).addClass('hl').find('.repo-file-op').removeClass('vh');
|
||||
}
|
||||
},
|
||||
function() {
|
||||
if (no_file_op_popup) {
|
||||
$(this).removeClass('hl').find('.repo-file-op').addClass('vh');
|
||||
}
|
||||
}
|
||||
);
|
||||
$('#main-panel').removeClass('ovhd');
|
||||
$('.more-op-icon').click(function(e) {
|
||||
var hidden_op = $(this).next();
|
||||
if ($(this).attr('data')) { // no popup
|
||||
hidden_op.css({'left': $(this).position().left + $(this).width() + 5});
|
||||
if ($(this).offset().top + hidden_op.height() <= $('#main').offset().top + $('#main').height()) {
|
||||
hidden_op.css('top', 6);
|
||||
} else {
|
||||
hidden_op.css('bottom', 2);
|
||||
}
|
||||
hidden_op.removeClass('hide');
|
||||
$(this).attr('data','');
|
||||
no_file_op_popup = false;
|
||||
popup_tr = $(this).parents('tr');
|
||||
} else {
|
||||
hidden_op.addClass('hide');
|
||||
$(this).attr('data','no-popup');
|
||||
no_file_op_popup = true;
|
||||
popup_tr = '';
|
||||
}
|
||||
});
|
||||
$(document).click(function(e) {
|
||||
var target = e.target || event.srcElement;
|
||||
if (!no_file_op_popup &&
|
||||
!$('.more-op-icon, .hidden-op').is(target) &&
|
||||
!$('.hidden-op').find('*').is(target)) {
|
||||
$('.hidden-op').addClass('hide');
|
||||
$('.more-op-icon').attr('data', 'no-popup');
|
||||
no_file_op_popup = true;
|
||||
|
||||
if (!popup_tr.find('*').is(target)) {
|
||||
popup_tr.removeClass('hl').find('.repo-file-op').addClass('vh'); // clicked place: the first tr, place out of the table
|
||||
$('tr:gt(0)').each(function() { // when other tr is clicked
|
||||
if ($(this).find('*').is(target)) {
|
||||
$(this).addClass('hl').find('.repo-file-op').removeClass('vh');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('.hidden-op li').hover(
|
||||
function() {
|
||||
$(this).css('background', '#eee');
|
||||
},
|
||||
function() {
|
||||
$(this).css('background', '#fff');
|
||||
}
|
||||
);
|
||||
|
||||
$('#download-dir').click(function() {
|
||||
location.href = $(this).attr('data');
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
@ -16,7 +16,7 @@ from service import get_repos, get_repo, get_commits, get_branches, remove_repo,
|
||||
list_personal_shared_repos, is_personal_repo, list_inner_pub_repos, \
|
||||
is_org_repo_owner, get_org_repo_owner, is_org_repo, get_file_size,\
|
||||
list_personal_repos_by_owner, get_repo_token_nonnull, get_repo_owner, \
|
||||
server_repo_size
|
||||
server_repo_size, get_file_id_by_path
|
||||
|
||||
from service import get_binding_peerids, is_valid_filename, check_permission,\
|
||||
is_passwd_set
|
||||
|
@ -669,6 +669,13 @@ def get_file_size(file_id):
|
||||
fs = 0
|
||||
return fs
|
||||
|
||||
def get_file_id_by_path(repo_id, path):
|
||||
try:
|
||||
ret = seafserv_threaded_rpc.get_file_id_by_path(repo_id, path)
|
||||
except SearpcError, e:
|
||||
ret = ''
|
||||
return ret
|
||||
|
||||
def get_related_users_by_repo(repo_id):
|
||||
"""Give a repo id, returns a list of users of:
|
||||
- the repo owner
|
||||
|
6
urls.py
6
urls.py
@ -57,7 +57,9 @@ urlpatterns = patterns('',
|
||||
(r'^repo/(?P<repo_id>[-0-9a-f]{36})/file/edit/$', file_edit),
|
||||
url(r'^repo/(?P<repo_id>[-0-9a-f]{36})/(?P<obj_id>[^/]+)/$', repo_access_file, name='repo_access_file'),
|
||||
|
||||
url(r'^f/(?P<token>[^/]+)/$', view_shared_file, name='view_shared_file'),
|
||||
url(r'^f/(?P<token>[a-f0-9]{10})/$', view_shared_file, name='view_shared_file'),
|
||||
url(r'^d/(?P<token>[a-f0-9]{10})/$', view_shared_dir, name='view_shared_dir'),
|
||||
url(r'^d/(?P<token>[a-f0-9]{10})/files/$', view_file_via_shared_dir, name='view_file_via_shared_dir'),
|
||||
(r'^file_upload_progress_page/$', file_upload_progress_page),
|
||||
(r'^publicrepo/create/$', public_repo_create),
|
||||
(r'^events/$', events),
|
||||
@ -77,7 +79,7 @@ urlpatterns = patterns('',
|
||||
url(r'^useradmin/password/reset/(?P<user_id>[^/]+)/$', user_reset, name='user_reset'),
|
||||
|
||||
### Apps ###
|
||||
(r'^api/', include('api.urls')),
|
||||
# (r'^api/', include('api.urls')),
|
||||
(r'^api2/', include('api2.urls')),
|
||||
(r'^avatar/', include('avatar.urls')),
|
||||
(r'^notification/', include('notifications.urls')),
|
||||
|
@ -7,6 +7,7 @@ import stat
|
||||
import urllib2
|
||||
import json
|
||||
|
||||
from django.contrib.sites.models import RequestSite
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
from django.utils.hashcompat import sha_constructor
|
||||
@ -701,3 +702,13 @@ def calc_file_path_hash(path, bits=12):
|
||||
path_hash = md5_constructor(urllib2.quote(path)).hexdigest()[:bits]
|
||||
|
||||
return path_hash
|
||||
|
||||
def gen_shared_link(request, token, s_type):
|
||||
http_or_https = request.is_secure() and 'https' or 'http'
|
||||
domain = RequestSite(request).domain
|
||||
|
||||
if s_type == 'f':
|
||||
return '%s://%s%sf/%s/' % (http_or_https, domain, settings.SITE_ROOT, token)
|
||||
else:
|
||||
return '%s://%s%sd/%s/' % (http_or_https, domain, settings.SITE_ROOT, token)
|
||||
|
||||
|
192
views.py
192
views.py
@ -44,7 +44,7 @@ from seaserv import ccnet_rpc, ccnet_threaded_rpc, get_repos, get_emailusers, \
|
||||
list_inner_pub_repos, get_org_groups_by_repo, is_org_repo_owner, \
|
||||
get_org_repo_owner, is_passwd_set, get_file_size, check_quota, \
|
||||
get_related_users_by_repo, get_related_users_by_org_repo, HtmlDiff, \
|
||||
get_session_info, get_group_repoids, get_repo_owner
|
||||
get_session_info, get_group_repoids, get_repo_owner, get_file_id_by_path
|
||||
from pysearpc import SearpcError
|
||||
|
||||
from signals import repo_created, repo_deleted
|
||||
@ -64,7 +64,7 @@ from forms import AddUserForm, RepoCreateForm, RepoNewDirForm, RepoNewFileForm,\
|
||||
FileCommentForm, RepoRenameFileForm, RepoPassowrdForm, SharedRepoCreateForm,\
|
||||
SetUserQuotaForm
|
||||
from utils import render_permission_error, render_error, list_to_string, \
|
||||
get_httpserver_root, get_ccnetapplet_root, \
|
||||
get_httpserver_root, get_ccnetapplet_root, gen_shared_link, \
|
||||
calculate_repo_last_modify, valid_previewed_file, \
|
||||
check_filename_with_rename, get_accessible_repos, EMPTY_SHA1, \
|
||||
get_file_revision_id_size, get_ccnet_server_addr_port, \
|
||||
@ -165,7 +165,7 @@ def get_repo_dirents(request, repo_id, commit, path):
|
||||
# return render_error(self.request, e.msg)
|
||||
|
||||
org_id = -1
|
||||
if request.user.org:
|
||||
if hasattr(request.user, 'org') and request.user.org:
|
||||
org_id = request.user.org['org_id']
|
||||
starred_files = get_dir_starred_files(request.user.username, repo_id, path, org_id)
|
||||
|
||||
@ -177,20 +177,27 @@ def get_repo_dirents(request, repo_id, commit, path):
|
||||
|
||||
for dirent in dirs:
|
||||
dirent.last_modified = last_modified_info.get(dirent.obj_name, 0)
|
||||
|
||||
dirent.sharelink = ''
|
||||
if stat.S_ISDIR(dirent.props.mode):
|
||||
dpath = os.path.join(path, dirent.obj_name)
|
||||
if dpath[-1] != '/':
|
||||
dpath += '/'
|
||||
for share in fileshares:
|
||||
if dpath == share.path:
|
||||
dirent.sharelink = gen_shared_link(request, share.token, 'd')
|
||||
dirent.sharetoken = share.token
|
||||
break
|
||||
dir_list.append(dirent)
|
||||
else:
|
||||
file_list.append(dirent)
|
||||
dirent.file_size = get_file_size(dirent.obj_id)
|
||||
dirent.starred = False
|
||||
dirent.sharelink = ''
|
||||
fpath = os.path.join(path, dirent.obj_name)
|
||||
if fpath in starred_files:
|
||||
dirent.starred = True
|
||||
for share in fileshares:
|
||||
if fpath == share.path:
|
||||
dirent.sharelink = '%s://%s%sf/%s/' % (http_or_https, domain, settings.SITE_ROOT, share.token)
|
||||
dirent.sharelink = gen_shared_link(request, share.token, 'f')
|
||||
dirent.sharetoken = share.token
|
||||
break
|
||||
dir_list.sort(lambda x, y : cmp(x.obj_name.lower(),
|
||||
@ -346,6 +353,26 @@ class RepoView(LoginRequiredMixin, CtxSwitchRequiredMixin, RepoMixin,
|
||||
return gen_file_upload_url(token, 'update')
|
||||
else:
|
||||
return ''
|
||||
|
||||
def get_fileshare(self, repo_id, user, path):
|
||||
if path == '/': # no shared link for root dir
|
||||
return None
|
||||
|
||||
l = FileShare.objects.filter(repo_id=repo_id).filter(\
|
||||
username=user).filter(path=path)
|
||||
fileshare = l[0] if len(l) > 0 else None
|
||||
return fileshare
|
||||
|
||||
def get_shared_link(self, fileshare):
|
||||
# dir shared link
|
||||
http_or_https = self.request.is_secure() and 'https' or 'http'
|
||||
domain = RequestSite(self.request).domain
|
||||
|
||||
if fileshare:
|
||||
dir_shared_link = gen_shared_link(self.request, fileshare.token, 'd')
|
||||
else:
|
||||
dir_shared_link = ''
|
||||
return dir_shared_link
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs['repo'] = self.repo
|
||||
@ -379,6 +406,9 @@ class RepoView(LoginRequiredMixin, CtxSwitchRequiredMixin, RepoMixin,
|
||||
kwargs['protocol'] = self.protocol
|
||||
kwargs['domain'] = self.domain
|
||||
kwargs['contacts'] = self.contacts
|
||||
kwargs['fileshare'] = self.get_fileshare(\
|
||||
self.repo_id, self.request.user.username, self.path)
|
||||
kwargs['dir_shared_link'] = self.get_shared_link(kwargs['fileshare'])
|
||||
|
||||
return kwargs
|
||||
|
||||
@ -1297,13 +1327,12 @@ def repo_view_file(request, repo_id):
|
||||
http_or_https = request.is_secure() and 'https' or 'http'
|
||||
domain = RequestSite(request).domain
|
||||
if fileshare:
|
||||
file_shared_link = '%s://%s%sf/%s/' % (http_or_https, domain, settings.SITE_ROOT, fileshare.token)
|
||||
file_shared_link = gen_shared_link(request, fileshare.token, 'f')
|
||||
else:
|
||||
file_shared_link = ''
|
||||
|
||||
# my constacts
|
||||
contacts = Contact.objects.filter(user_email=request.user.username)
|
||||
|
||||
|
||||
# Get groups this repo is shared.
|
||||
if request.user.org:
|
||||
@ -2416,7 +2445,7 @@ def view_shared_file(request, token):
|
||||
path = fileshare.path
|
||||
|
||||
http_server_root = get_httpserver_root()
|
||||
if path[-1] == '/':
|
||||
if path[-1] == '/': # Normalize file path
|
||||
path = path[:-1]
|
||||
filename = os.path.basename(path)
|
||||
quote_filename = urllib2.quote(filename.encode('utf-8'))
|
||||
@ -2472,7 +2501,113 @@ def view_shared_file(request, token):
|
||||
'DOCUMENT_CONVERTOR_ROOT': DOCUMENT_CONVERTOR_ROOT,
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
def view_shared_dir(request, token):
|
||||
assert token is not None # Checked by URLconf
|
||||
|
||||
try:
|
||||
fileshare = FileShare.objects.get(token=token)
|
||||
except FileShare.DoesNotExist:
|
||||
raise Http404
|
||||
|
||||
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
|
||||
|
||||
repo = get_repo(repo_id)
|
||||
if not repo:
|
||||
raise Http404
|
||||
|
||||
dir_name = os.path.basename(path[:-1])
|
||||
current_commit = get_commits(repo_id, 0, 1)[0]
|
||||
file_list, dir_list = get_repo_dirents(request, repo_id, current_commit,
|
||||
path)
|
||||
zipped = gen_path_link(path, '')
|
||||
|
||||
if path == fileshare.path: # When user view the shared dir..
|
||||
# increase shared link view_cnt,
|
||||
fileshare = FileShare.objects.get(token=token)
|
||||
fileshare.view_cnt = F('view_cnt') + 1
|
||||
fileshare.save()
|
||||
|
||||
return render_to_response('view_shared_dir.html', {
|
||||
'repo': repo,
|
||||
'token': token,
|
||||
'path': path,
|
||||
'username': username,
|
||||
'dir_name': dir_name,
|
||||
'file_list': file_list,
|
||||
'dir_list': dir_list,
|
||||
'zipped': zipped,
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
def view_file_via_shared_dir(request, token):
|
||||
assert token is not None # Checked by URLconf
|
||||
|
||||
try:
|
||||
fileshare = FileShare.objects.get(token=token)
|
||||
except FileShare.DoesNotExist:
|
||||
raise Http404
|
||||
|
||||
username = fileshare.username
|
||||
repo_id = fileshare.repo_id
|
||||
path = request.GET.get('p', '')
|
||||
if not path:
|
||||
raise Http404
|
||||
|
||||
if not path.startswith(fileshare.path): # Can not view upper dir of shared dir
|
||||
raise Http404
|
||||
|
||||
repo = get_repo(repo_id)
|
||||
if not repo:
|
||||
raise Http404
|
||||
|
||||
file_name = os.path.basename(path)
|
||||
quote_filename = urllib2.quote(file_name.encode('utf-8'))
|
||||
file_id = get_file_id_by_path(repo_id, path)
|
||||
if not file_id:
|
||||
return render_error(request, _(u'File not exists'))
|
||||
|
||||
access_token = seafserv_rpc.web_get_access_token(repo.id, file_id,
|
||||
'view', '')
|
||||
filetype, fileext = valid_previewed_file(file_name)
|
||||
# Raw path
|
||||
raw_path = gen_file_get_url(access_token, quote_filename)
|
||||
# get file content
|
||||
err = ''
|
||||
file_content = ''
|
||||
swf_exists = False
|
||||
if filetype == 'Text' or filetype == 'Markdown' or filetype == 'Sf':
|
||||
err, file_content, encoding = repo_file_get(raw_path)
|
||||
elif filetype == 'Document' or filetype == 'PDF':
|
||||
err, swf_exists = flash_prepare(raw_path, obj_id, fileext)
|
||||
|
||||
zipped = gen_path_link(path, '')
|
||||
|
||||
return render_to_response('shared_file_view.html', {
|
||||
'repo': repo,
|
||||
'obj_id': file_id,
|
||||
'path': path,
|
||||
'file_name': file_name,
|
||||
'shared_token': token,
|
||||
'access_token': access_token,
|
||||
'filetype': filetype,
|
||||
'fileext': fileext,
|
||||
'raw_path': raw_path,
|
||||
'username': username,
|
||||
'err': err,
|
||||
'file_content': file_content,
|
||||
'swf_exists': swf_exists,
|
||||
'DOCUMENT_CONVERTOR_ROOT': DOCUMENT_CONVERTOR_ROOT,
|
||||
'zipped': zipped,
|
||||
'token': token,
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
def flash_prepare(raw_path, obj_id, doctype):
|
||||
curl = DOCUMENT_CONVERTOR_ROOT + 'convert'
|
||||
data = {'doctype': doctype,
|
||||
@ -2653,22 +2788,34 @@ def repo_star_file(request, repo_id):
|
||||
unstar_file(request.user.username, repo_id, path)
|
||||
return HttpResponse(json.dumps({'success':True}), content_type=content_type)
|
||||
|
||||
@login_required
|
||||
def repo_download_dir(request, repo_id):
|
||||
repo = get_repo(repo_id)
|
||||
if not repo:
|
||||
return render_error(request, _(u'Library not exists'))
|
||||
|
||||
try:
|
||||
parent_dir = request.GET['parent']
|
||||
dirname = request.GET['dirname']
|
||||
except KeyError:
|
||||
return render_error(request, _(u'Invalid arguments'))
|
||||
path = request.GET.get('p', '/')
|
||||
if path[-1] != '/': # Normalize dir path
|
||||
path += '/'
|
||||
|
||||
path = os.path.join(parent_dir, dirname.rstrip('/'))
|
||||
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 = False
|
||||
fileshare_token = request.GET.get('t', '')
|
||||
if fileshare_token: # download dir from dir shared link
|
||||
try:
|
||||
fileshare = FileShare.objects.get(token=fileshare_token)
|
||||
except FileShare.DoesNotExist:
|
||||
raise Http404
|
||||
|
||||
permission = get_user_permission(request, repo_id)
|
||||
if permission:
|
||||
# Can not download upper dir of shared dir.
|
||||
allow_download = True if path.startswith(fileshare.path) else False
|
||||
else:
|
||||
allow_download = True if get_user_permission(request, repo_id) else False
|
||||
|
||||
if allow_download:
|
||||
dir_id = seafserv_threaded_rpc.get_dirid_by_path (repo.head_cmmt_id,
|
||||
path.encode('utf-8'))
|
||||
token = seafserv_rpc.web_get_access_token(repo_id,
|
||||
@ -2676,14 +2823,9 @@ def repo_download_dir(request, repo_id):
|
||||
'download-dir',
|
||||
request.user.username)
|
||||
else:
|
||||
return render_permission_error(request, _(u'Unable to access file'))
|
||||
|
||||
if len(path) > 1:
|
||||
filename = os.path.basename(path)
|
||||
else:
|
||||
filename = repo.name
|
||||
url = gen_file_get_url(token, filename)
|
||||
return render_error(request, _(u'Unable to download "%s"') % dirname )
|
||||
|
||||
url = gen_file_get_url(token, dirname)
|
||||
return redirect(url)
|
||||
|
||||
def events(request):
|
||||
|
Loading…
Reference in New Issue
Block a user