diff --git a/media/css/mobile.css b/media/css/mobile.css
index 99369d3b35..967eb4d780 100644
--- a/media/css/mobile.css
+++ b/media/css/mobile.css
@@ -1195,6 +1195,7 @@ textarea:-moz-placeholder {/* for FF */
}
/*repo-share-form*/
#link-send-input,
+#upload-link-send-input,
#email_or_group,
#share-link,
#added-member-name,
@@ -1426,10 +1427,13 @@ textarea:-moz-placeholder {/* for FF */
text-align:right;
}
#shared-link,
-#shared-link-text {
+#shared-upload-link,
+#shared-link-text,
+#shared-upload-link-text {
border:0;
}
-#shared-link-text {
+#shared-link-text,
+#shared-upload-link-text {
vertical-align:middle; /*for ie 7*/
}
.file-op {
diff --git a/media/css/seahub.css b/media/css/seahub.css
index 9714669e8d..0e9fd4e0e3 100644
--- a/media/css/seahub.css
+++ b/media/css/seahub.css
@@ -1542,6 +1542,7 @@ textarea:-moz-placeholder {/* for FF */
}
/*repo-share-form*/
#link-send-input,
+#upload-link-send-input,
#email_or_group,
#share-link,
#added-member-name {
@@ -1623,7 +1624,7 @@ textarea:-moz-placeholder {/* for FF */
left:365px;
top:50px;
z-index:10;
- padding:15px;;
+ padding:15px;
min-height:130px;
border:1px solid #ddd;
background:#fff;
@@ -1944,10 +1945,13 @@ textarea:-moz-placeholder {/* for FF */
text-align:right;
}
#shared-link,
-#shared-link-text {
+#shared-upload-link,
+#shared-link-text,
+#shared-upload-link-text {
border:0;
}
-#shared-link-text {
+#shared-link-text,
+#shared-upload-link-text {
background:transparent;
height:auto;
}
diff --git a/seahub/share/forms.py b/seahub/share/forms.py
index c7a093748a..fc4aeddf27 100644
--- a/seahub/share/forms.py
+++ b/seahub/share/forms.py
@@ -21,3 +21,12 @@ class FileLinkShareForm(forms.Form):
})
file_shared_link = forms.CharField()
+class UploadLinkShareForm(forms.Form):
+ """
+ Form for sharing upload link to emails.
+ """
+ email = forms.CharField(max_length=512, error_messages={
+ 'required': _("Email is required"),
+ 'max_length': _("Email is not longer than 512 characters"),
+ })
+ shared_upload_link = forms.CharField()
diff --git a/seahub/share/models.py b/seahub/share/models.py
index 1d26f49c79..9c59a461ae 100644
--- a/seahub/share/models.py
+++ b/seahub/share/models.py
@@ -25,6 +25,16 @@ class FileShare(models.Model):
view_cnt = models.IntegerField(default=0)
s_type = models.CharField(max_length=2, db_index=True, default='f') # `f` or `d`
+class UploadLinkShare(models.Model):
+ """
+ Model used for shared upload link.
+ """
+ username = LowerCaseCharField(max_length=255, db_index=True)
+ repo_id = models.CharField(max_length=36, db_index=True)
+ path = models.TextField()
+ token = models.CharField(max_length=10, unique=True)
+ ctime = models.DateTimeField(default=datetime.datetime.now)
+ view_cnt = models.IntegerField(default=0)
class PrivateFileDirShareManager(models.Manager):
def add_private_file_share(self, from_user, to_user, repo_id, path, perm):
diff --git a/seahub/share/templates/repo/priv_shared_files.html b/seahub/share/templates/repo/priv_shared_files.html
index e8bec38a02..8f86f217c5 100644
--- a/seahub/share/templates/repo/priv_shared_files.html
+++ b/seahub/share/templates/repo/priv_shared_files.html
@@ -6,13 +6,7 @@
{% block nav_share_class %}class="cur"{% endblock %}
{% block title_panel %}
-
+{% include "repo/tabnav.html" with cur="private" %}
{% endblock %}
{% block main_panel %}
diff --git a/seahub/share/templates/repo/share_out_repos.html b/seahub/share/templates/repo/share_out_repos.html
index 6b552aec95..5441584556 100644
--- a/seahub/share/templates/repo/share_out_repos.html
+++ b/seahub/share/templates/repo/share_out_repos.html
@@ -6,13 +6,7 @@
{% block nav_share_class %}class="cur"{% endblock %}
{% block title_panel %}
-
+{% include "repo/tabnav.html" with cur="library" %}
{% endblock %}
{% block main_panel %}
diff --git a/seahub/share/templates/repo/shared_links.html b/seahub/share/templates/repo/shared_links.html
index fd2eb8b845..87488e11ab 100644
--- a/seahub/share/templates/repo/shared_links.html
+++ b/seahub/share/templates/repo/shared_links.html
@@ -6,13 +6,7 @@
{% block nav_share_class %}class="cur"{% endblock %}
{% block title_panel %}
-
+{% include "repo/tabnav.html" with cur="links" %}
{% endblock %}
{% block main_panel %}
diff --git a/seahub/share/templates/repo/shared_upload_links.html b/seahub/share/templates/repo/shared_upload_links.html
new file mode 100644
index 0000000000..5c0df4d27f
--- /dev/null
+++ b/seahub/share/templates/repo/shared_upload_links.html
@@ -0,0 +1,61 @@
+{% extends base_template %}
+{% load seahub_tags i18n %}
+{% load url from future %}
+
+{% block sub_title %}{% trans "Share" %} - {% endblock %}
+{% block nav_share_class %}class="cur"{% endblock %}
+
+{% block title_panel %}
+{% include "repo/tabnav.html" with cur="upload" %}
+{% endblock %}
+
+{% block main_panel %}
+{% if uploadlinks %}
+
+
+{% else %}
+
+
{% trans "You don't have any shared upload link"%}
+
{% trans "You can share a folder with other users so that they can upload files to your folder." %}
+
+{% endif %}
+
+{% endblock %}
+
+{% block extra_script %}
+
+{% endblock %}
diff --git a/seahub/share/templates/repo/tabnav.html b/seahub/share/templates/repo/tabnav.html
new file mode 100644
index 0000000000..e6bc7eedc3
--- /dev/null
+++ b/seahub/share/templates/repo/tabnav.html
@@ -0,0 +1,10 @@
+{% load i18n %}
+
+
diff --git a/seahub/share/urls.py b/seahub/share/urls.py
index 21a0b21806..4534866339 100644
--- a/seahub/share/urls.py
+++ b/seahub/share/urls.py
@@ -5,6 +5,7 @@ from views import *
urlpatterns = patterns('',
url(r'^$', list_share_out_repos, name='share_admin'),
url(r'^links/$', list_shared_links, name='list_shared_links'),
+ url(r'^upload_links/$', list_shared_upload_links, name='list_shared_upload_links'),
url(r'^files/$', list_priv_shared_files, name='list_priv_shared_files'),
url(r'^add/$', share_repo, name='share_repo'),
@@ -15,6 +16,10 @@ urlpatterns = patterns('',
url(r'^link/send/$', send_shared_link, name='send_shared_link'),
url(r'^link/save/$', save_shared_link, name='save_shared_link'),
+ url(r'^upload_link/get/$', get_shared_upload_link, name='get_shared_upload_link'),
+ url(r'^upload_link/remove/$', remove_shared_upload_link, name='remove_shared_upload_link'),
+ url(r'^upload_link/send/$', send_shared_upload_link, name='send_shared_upload_link'),
+
url(r'^permission_admin/$', share_permission_admin, name='share_permission_admin'),
diff --git a/seahub/share/views.py b/seahub/share/views.py
index 7f190c95bf..d754d4a07a 100644
--- a/seahub/share/views.py
+++ b/seahub/share/views.py
@@ -23,8 +23,8 @@ from seaserv import seafserv_threaded_rpc, ccnet_rpc, \
del_org_group_repo, list_share_repos, get_group_repos_by_owner, \
list_inner_pub_repos_by_owner, remove_share
-from forms import RepoShareForm, FileLinkShareForm
-from models import AnonymousShare, FileShare, PrivateFileDirShare
+from forms import RepoShareForm, FileLinkShareForm, UploadLinkShareForm
+from models import AnonymousShare, FileShare, PrivateFileDirShare, UploadLinkShare
from signals import share_repo_to_user_successful
from settings import ANONYMOUS_SHARE_COOKIE_TIMEOUT
from tokens import anon_share_token_generator
@@ -35,8 +35,8 @@ from seahub.contacts.signals import mail_sended
from seahub.signals import share_file_to_user_successful
from seahub.views import validate_owner, is_registered_user
from seahub.utils import render_permission_error, string2list, render_error, \
- gen_token, gen_shared_link, gen_dir_share_link, gen_file_share_link, \
- IS_EMAIL_CONFIGURED, check_filename_with_rename
+ gen_token, gen_shared_link, gen_shared_upload_link, gen_dir_share_link, \
+ gen_file_share_link, IS_EMAIL_CONFIGURED, check_filename_with_rename
try:
from seahub.settings import CLOUD_MODE
@@ -399,6 +399,32 @@ def list_shared_links(request):
"fileshares": p_fileshares,
}, context_instance=RequestContext(request))
+@login_required
+def list_shared_upload_links(request):
+ """List upload links, and remove invalid links(dir is deleted or moved).
+ """
+ username = request.user.username
+
+ uploadlinks = UploadLinkShare.objects.filter(username=username)
+ p_uploadlinks = []
+ for link in uploadlinks:
+ if is_personal_repo(link.repo_id):
+ r = seafile_api.get_repo(link.repo_id)
+ if not r:
+ link.delete()
+ continue
+ if seafile_api.get_dir_id_by_path(r.id, link.path) is None:
+ link.delete()
+ continue
+ link.filename = os.path.basename(link.path.rstrip('/'))
+ link.shared_link = gen_shared_upload_link(link.token)
+ link.repo = r
+ p_uploadlinks.append(link)
+
+ return render_to_response('repo/shared_upload_links.html', {
+ "uploadlinks": p_uploadlinks,
+ }, context_instance=RequestContext(request))
+
@login_required
def list_priv_shared_files(request):
"""List private shared files.
@@ -629,6 +655,39 @@ def remove_shared_link(request):
result = {'error': _(u"The link doesn't exist")}
return HttpResponse(json.dumps(result), status=400, content_type=content_type)
+@login_required
+def remove_shared_upload_link(request):
+ """
+ Handle request to remove shared upload link.
+ """
+ token = request.GET.get('t')
+
+ if not request.is_ajax():
+ UploadLinkShare.objects.filter(token=token).delete()
+ next = request.META.get('HTTP_REFERER', None)
+ if not next:
+ next = reverse('share_admin')
+
+ messages.success(request, _(u'Removed successfully'))
+
+ return HttpResponseRedirect(next)
+
+ content_type = 'application/json; charset=utf-8'
+ result = {}
+
+ if not token:
+ result = {'error': _(u"Argument missing")}
+ return HttpResponse(json.dumps(result), status=400, content_type=content_type)
+
+ try:
+ upload_link = UploadLinkShare.objects.get(token=token)
+ upload_link.delete()
+ result = {'success': True}
+ return HttpResponse(json.dumps(result), content_type=content_type)
+ except:
+ result = {'error': _(u"The link doesn't exist")}
+ return HttpResponse(json.dumps(result), status=400, content_type=content_type)
+
@login_required
def send_shared_link(request):
"""
@@ -845,3 +904,102 @@ def user_share_list(request, id_or_email):
'add_to_contacts': add_to_contacts,
}, context_instance=RequestContext(request))
+@login_required
+def get_shared_upload_link(request):
+ """
+ Handle ajax request to generate dir upload 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 not (repo_id and path):
+ err = _('Invalid arguments')
+ data = json.dumps({'error': err})
+ return HttpResponse(data, status=400, content_type=content_type)
+
+ if path == '/': # can not share root dir
+ err = _('You cannot share the library in this way.')
+ 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 = UploadLinkShare.objects.filter(repo_id=repo_id).filter(
+ username=request.user.username).filter(path=path)
+ if len(l) > 0:
+ upload_link = l[0]
+ token = upload_link.token
+ else:
+ token = gen_token(max_length=10)
+
+ upload_link = UploadLinkShare()
+ upload_link.username = request.user.username
+ upload_link.repo_id = repo_id
+ upload_link.path = path
+ upload_link.token = token
+
+ try:
+ upload_link.save()
+ except IntegrityError, e:
+ err = _('Failed to get the link, please retry later.')
+ data = json.dumps({'error': err})
+ return HttpResponse(data, status=500, content_type=content_type)
+
+ shared_upload_link = gen_shared_upload_link(token)
+
+ data = json.dumps({'token': token, 'shared_upload_link': shared_upload_link})
+ return HttpResponse(data, status=200, content_type=content_type)
+
+@login_required
+def send_shared_upload_link(request):
+ """
+ Handle ajax post request to send shared upload link.
+ """
+ if not request.is_ajax() and not request.method == 'POST':
+ raise Http404
+
+ content_type = 'application/json; charset=utf-8'
+
+ if not IS_EMAIL_CONFIGURED:
+ data = json.dumps({'error':_(u'Sending shared upload link failed. Email service is not properly configured, please contact administrator.')})
+ return HttpResponse(data, status=500, content_type=content_type)
+
+ from seahub.settings import SITE_NAME
+
+ form = UploadLinkShareForm(request.POST)
+ if form.is_valid():
+ email = form.cleaned_data['email']
+ shared_upload_link = form.cleaned_data['shared_upload_link']
+
+ t = loader.get_template('shared_upload_link_email.html')
+ to_email_list = string2list(email)
+ for to_email in to_email_list:
+ # Add email to contacts.
+ mail_sended.send(sender=None, user=request.user.username,
+ email=to_email)
+
+ c = {
+ 'email': request.user.username,
+ 'to_email': to_email,
+ 'shared_upload_link': shared_upload_link,
+ 'site_name': SITE_NAME,
+ }
+
+ try:
+ send_mail(_(u'Your friend shared a upload link to you on Seafile'),
+ t.render(Context(c)), None, [to_email],
+ fail_silently=False)
+ except Exception, e:
+ logger.error(str(e))
+ data = json.dumps({'error':_(u'Internal server error. Send failed.')})
+ return HttpResponse(data, status=500, content_type=content_type)
+
+ data = json.dumps({"msg": _(u'Successfully sent.')})
+ return HttpResponse(data, status=200, content_type=content_type)
+ else:
+ return HttpResponseBadRequest(json.dumps(form.errors),
+ content_type=content_type)
diff --git a/seahub/templates/repo.html b/seahub/templates/repo.html
index 63e32a90ad..8a70f2e9e3 100644
--- a/seahub/templates/repo.html
+++ b/seahub/templates/repo.html
@@ -831,11 +831,11 @@ $('#add-new-file').click(function () {
// share current dir
$('#share-cur-dir').click(function() {
- var op = $(this), name, aj_url, type;
+ var op = $(this), name, aj_urls, type;
name = $('#cur-dir-name').html();
- aj_url = op.data('url');
+ aj_urls = { 'link': op.data('url'), 'upload-link': op.data('upload-url') };
type = 'd';
- showSharePopup(op, name, aj_url, type, cur_path);
+ showSharePopup(op, name, aj_urls, type, cur_path);
});
//select all or not
@@ -1388,17 +1388,20 @@ $('.file-star', context).click(function() {
//share
$('.file-share, .dir-share', context).click(function() {
- var op = $(this), name, aj_url, type;
+ var op = $(this), name, aj_urls, type;
name = op.parents('tr').attr('data-name');
- aj_url = '{% url 'get_shared_link' %}?repo_id={{ repo.id }}&p=' + e(cur_path) + e(name);
+ aj_urls = {
+ 'link': '{% url 'get_shared_link' %}?repo_id={{ repo.id }}&p=' + e(cur_path) + e(name),
+ 'upload-link': '{% url 'get_shared_upload_link' %}?repo_id={{ repo.id }}&p=' + e(cur_path) + e(name)
+ };
if (op.hasClass('dir-share')) {
- aj_url += '&type=d';
+ aj_urls['link'] += '&type=d';
type = 'd';
} else {
type = 'f';
}
- showSharePopup(op, name, aj_url, type, cur_path);
+ showSharePopup(op, name, aj_urls, type, cur_path);
return false;
});
diff --git a/seahub/templates/shared_upload_link_email.html b/seahub/templates/shared_upload_link_email.html
new file mode 100644
index 0000000000..227f095382
--- /dev/null
+++ b/seahub/templates/shared_upload_link_email.html
@@ -0,0 +1,11 @@
+{% load i18n %}{% autoescape off %}
+{% blocktrans %}You're receiving this e-mail because {{ email }} is sharing an upload link to you on {{ site_name }}.{% endblocktrans%}
+
+{% trans "Please go to the following page and upload your file:" %}
+{{ shared_upload_link }}
+
+{% trans "Thanks for using our site!" %}
+
+{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
+
+{% endautoescape %}
diff --git a/seahub/templates/snippets/file_share_popup.html b/seahub/templates/snippets/file_share_popup.html
index f84377614c..21d84cb1a4 100644
--- a/seahub/templates/snippets/file_share_popup.html
+++ b/seahub/templates/snippets/file_share_popup.html
@@ -4,6 +4,7 @@
+
+
+
+
{% trans 'Upload Link: ' %}
+
+
+
+
+
+
+
{% if ENABLE_SUB_LIBRARY and not repo.is_virtual and is_repo_owner %}

diff --git a/seahub/templates/snippets/repo_dir_data.html b/seahub/templates/snippets/repo_dir_data.html
index 25e8096eab..6118ae559e 100644
--- a/seahub/templates/snippets/repo_dir_data.html
+++ b/seahub/templates/snippets/repo_dir_data.html
@@ -22,7 +22,7 @@
{% if path != '/' %}
{% if not repo.encrypted %}
-
+
{% endif %}
{% endif %}
diff --git a/seahub/templates/snippets/repo_dirents.html b/seahub/templates/snippets/repo_dirents.html
index 8ac4608a51..30f8bc82b5 100644
--- a/seahub/templates/snippets/repo_dirents.html
+++ b/seahub/templates/snippets/repo_dirents.html
@@ -23,7 +23,7 @@
{% if user_perm == 'rw' %}
diff --git a/seahub/templates/snippets/shared_link_js.html b/seahub/templates/snippets/shared_link_js.html
index a2f4fb84db..1a133d88fb 100644
--- a/seahub/templates/snippets/shared_link_js.html
+++ b/seahub/templates/snippets/shared_link_js.html
@@ -8,7 +8,7 @@ share_list.push({value: contact_email, label: contact_email});
contacts.push({value:contact_email, avatar:'{% avatar contact.contact_email 16 %}'});
{% endfor %}
-function showSharePopup(op, name, aj_url, type, cur_path) {
+function showSharePopup(op, name, aj_urls, type, cur_path) {
var path;
if (op.attr('id') == 'share-cur-dir') {
path = cur_path.substr(0, cur_path.length - 1); // rm the last '/' as seafile_api treats '/xx' and '/xx/' as different
@@ -24,6 +24,7 @@ function showSharePopup(op, name, aj_url, type, cur_path) {
$('#private-share-tab, #private-share').remove();
} else {
$('#syncable-share-tab, #syncable-share').remove();
+ $('#upload-link-tab').remove();
}
$("#file-share-tabs").tabs();
@@ -40,9 +41,28 @@ function showSharePopup(op, name, aj_url, type, cur_path) {
$('#gen-link-btn').removeClass('hide');
$('#share-link-body').addClass('hide');
}
- $('#gen-link-btn').data('url', aj_url).data('obj', op);
+ $('#gen-link-btn').data('url', aj_urls['link']).data('obj', op);
$('#rm-shared-link').data('obj', op);
+ // share upload link
+ // files can only be uploaded to directory
+ if (type == 'd') {
+ if (op.data('upload-link')) {
+ $('#gen-upload-link-btn').addClass('hide');
+ $('#share-upload-link-body').removeClass('hide');
+ var link = op.data('upload-link');
+ $('#shared-upload-link-text, #upload-link-send-form input[name="shared_upload_link"]').val(link);
+ $('#main').append('' + link + '
');
+ $('#shared-upload-link-text').css({'width':$('#linkwidth').width() + 25});
+ $('#linkwidth').remove();
+ } else {
+ $('#gen-upload-link-btn').removeClass('hide');
+ $('#share-upload-link-body').addClass('hide');
+ }
+ $('#gen-upload-link-btn').data('url', aj_urls['upload-link']).data('obj', op);
+ $('#rm-shared-upload-link').data('obj', op);
+ }
+
// 'private share' for file
if ($('#private-share').length == 1) {
$('#private-share-tab a').click(function() {
@@ -221,3 +241,120 @@ $('#rm-shared-link').click(function() {
}
});
});
+
+$('#shared-upload-link-text').click(function() {
+ $(this).select();
+});
+
+$('#send-upload-link').click(function() {
+ $(this).addClass('hide');
+ $('#rm-shared-upload-link').addClass('hide');
+ var input = $('#upload-link-send-input');
+ input.css({'width': $('#upload-link-share').width() - parseInt(input.css('padding-left')) - parseInt(input.css('padding-right')) - parseInt(input.css('border-left-width')) - parseInt(input.css('border-right-width'))});
+ $('#upload-link-send-form').removeClass('hide');
+ addAutocomplete('#upload-link-send-input', '#upload-link-send-form', share_list);
+});
+
+$("#upload-link-send-form .cancel").click(function() {
+ $('#upload-link-send-form, #send-upload-link, #rm-shared-upload-link').toggleClass('hide');
+});
+
+$("#upload-link-send-form").submit(function(event) {
+ var form = $(this),
+ shared_upload_link = form.children('input[name="shared_upload_link"]').val(),
+ email = $.trim(form.children('textarea[name="email"]').val()),
+ submit_btn = form.children('input[type="submit"]');
+
+ if (!email) {
+ apply_form_error('upload-link-send-form', '{% trans "Please input at least an email." %}');
+ return false;
+ }
+
+ disable(submit_btn);
+ $('#upload-link-send-form .error').addClass('hide');
+ $('#upload-sending').removeClass('hide');
+
+ $.ajax({
+ type: "POST",
+ url: "{% url 'send_shared_upload_link' %}",
+ dataType: 'json',
+ cache: false,
+ beforeSend: prepareCSRFToken,
+ data: {shared_upload_link: shared_upload_link, email: email},
+ success: function(data) {
+ $.modal.close();
+ feedback(data['msg'], "success");
+ },
+ error: function(xhr, textStatus, errorThrown) {
+ $('#upload-sending').addClass('hide');
+ enable(submit_btn);
+ var err_str = '';
+ if (xhr.responseText) {
+ var err = jQuery.parseJSON(xhr.responseText);
+ if (err.error) {
+ err_str = err.error;
+ } else {
+ for (var i in err) {
+ err_str += err[i];
+ }
+ }
+ } else {
+ err_str = '{% trans "Failed. Please check the network." %}';
+ }
+ apply_form_error('upload-link-send-form', err_str);
+ }
+ });
+ return false;
+});
+
+$('#gen-upload-link-btn').click(function() {
+ var gen_upload_link_btn = $(this),
+ obj = gen_upload_link_btn.data('obj');
+
+ $.ajax({
+ url: gen_upload_link_btn.data('url'),
+ dataType: 'json',
+ cache: false,
+ success: function(data) {
+ var upload_link = data['shared_upload_link'];
+ gen_upload_link_btn.addClass('hide');
+ $('#shared-upload-link-text, #upload-link-send-form input[name="shared_upload_link"]').val(upload_link);
+ $('#main').append('' + upload_link + '
');
+ $('#shared-upload-link-text').css({'width':$('#linkwidth').width() + 25});
+ $('#linkwidth').remove();
+ $('#share-upload-link-body').removeClass('hide');
+ obj.data('upload-link', upload_link).data('upload-token', data['token']);
+ },
+ error: function(xhr, textStatus, errorThrown) {
+ if (xhr.responseText) {
+ feedback(jQuery.parseJSON(xhr.responseText).error, 'error');
+ } else {
+ feedback("{% trans "Failed. Please check the network." %}", 'error');
+ }
+ }
+ });
+ return false;
+});
+
+$('#rm-shared-upload-link').click(function() {
+ var obj = $(this).data('obj'),
+ token = obj.data('upload-token');
+
+ $.ajax({
+ url: '{% url 'remove_shared_upload_link' %}?t=' + token,
+ dataType: 'json',
+ cache: false,
+ success: function(data) {
+ $('#share-upload-link-body').addClass('hide');
+ $('#gen-upload-link-btn').removeClass('hide');
+ obj.data('upload-link', '').data('upload-token', '');
+ },
+ error: function(xhr, textStatus, errorThrown) {
+ if (xhr.responseText) {
+ feedback(jQuery.parseJSON(xhr.responseText).error, 'error');
+ } else {
+ feedback("{% trans "Failed. Please check the network." %}", 'error');
+ }
+ }
+ });
+});
diff --git a/seahub/templates/view_file_base.html b/seahub/templates/view_file_base.html
index e28e0ddd54..7a87f1287b 100644
--- a/seahub/templates/view_file_base.html
+++ b/seahub/templates/view_file_base.html
@@ -97,9 +97,9 @@
+
+
+
+
+
+
+{% endblock %}
diff --git a/seahub/urls.py b/seahub/urls.py
index 24ef3b84bb..bef15d14db 100644
--- a/seahub/urls.py
+++ b/seahub/urls.py
@@ -92,6 +92,7 @@ urlpatterns = patterns('',
url(r'^f/(?P[a-f0-9]{10})/$', view_shared_file, name='view_shared_file'),
url(r'^d/(?P[a-f0-9]{10})/$', view_shared_dir, name='view_shared_dir'),
url(r'^d/(?P[a-f0-9]{10})/files/$', view_file_via_shared_dir, name='view_file_via_shared_dir'),
+ url(r'^u/d/(?P[a-f0-9]{10})/$', view_shared_upload_dir, name='view_shared_upload_dir'),
### Misc ###
(r'^file_upload_progress_page/$', file_upload_progress_page),
diff --git a/seahub/utils/__init__.py b/seahub/utils/__init__.py
index d8c32a829d..37078e233e 100644
--- a/seahub/utils/__init__.py
+++ b/seahub/utils/__init__.py
@@ -835,6 +835,13 @@ def gen_shared_link(token, s_type):
else:
return '%s/d/%s/' % (service_url, token)
+def gen_shared_upload_link(token):
+ service_url = get_service_url()
+ assert service_url is not None
+
+ service_url = service_url.rstrip('/')
+ return '%s/u/d/%s/' % (service_url, token)
+
def show_delete_days(request):
if request.method == 'GET':
days_str = request.GET.get('days', '')
diff --git a/seahub/views/__init__.py b/seahub/views/__init__.py
index 2ea3154aaf..b7d38d23d8 100644
--- a/seahub/views/__init__.py
+++ b/seahub/views/__init__.py
@@ -44,7 +44,8 @@ from seaserv import ccnet_rpc, ccnet_threaded_rpc, get_repos, get_emailusers, \
set_repo_history_limit, \
get_commit, MAX_DOWNLOAD_DIR_SIZE, CALC_SHARE_USAGE, count_emailusers, \
count_inner_pub_repos, unset_inner_pub_repo, get_user_quota_usage, \
- get_user_share_usage, send_message
+ get_user_share_usage, send_message, \
+ MAX_UPLOAD_FILE_SIZE
from seaserv import seafile_api
from pysearpc import SearpcError
@@ -63,13 +64,13 @@ from seahub.group.signals import grpmsg_added
from seahub.notifications.models import UserNotification
from seahub.options.models import UserOptions, CryptoOptionNotSetError
from seahub.profile.models import Profile
-from seahub.share.models import FileShare, PrivateFileDirShare
+from seahub.share.models import FileShare, PrivateFileDirShare, UploadLinkShare
from seahub.forms import AddUserForm, RepoCreateForm, \
RepoPassowrdForm, SharedRepoCreateForm,\
SetUserQuotaForm, RepoSettingForm
from seahub.signals import repo_created, repo_deleted
from seahub.utils import render_permission_error, render_error, list_to_string, \
- get_httpserver_root, get_ccnetapplet_root, \
+ get_httpserver_root, get_ccnetapplet_root, gen_shared_upload_link, \
gen_dir_share_link, gen_file_share_link, get_repo_last_modify, \
calculate_repos_last_modify, get_file_type_and_ext, get_user_repos, \
EMPTY_SHA1, normalize_file_path, \
@@ -221,10 +222,12 @@ def get_repo_dirents(request, repo_id, commit, path, offset=-1, limit=-1):
last_modified_info = get_dir_files_last_modified(repo_id, path)
fileshares = FileShare.objects.filter(repo_id=repo_id).filter(username=request.user.username)
+ uploadlinks = UploadLinkShare.objects.filter(repo_id=repo_id).filter(username=request.user.username)
for dirent in dirs:
dirent.last_modified = last_modified_info.get(dirent.obj_name, 0)
dirent.sharelink = ''
+ dirent.uploadlink = ''
if stat.S_ISDIR(dirent.props.mode):
dpath = os.path.join(path, dirent.obj_name)
if dpath[-1] != '/':
@@ -234,6 +237,11 @@ def get_repo_dirents(request, repo_id, commit, path, offset=-1, limit=-1):
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
dir_list.append(dirent)
else:
file_list.append(dirent)
@@ -1676,7 +1684,45 @@ def view_shared_dir(request, token):
'dir_list': dir_list,
'zipped': zipped,
}, context_instance=RequestContext(request))
-
+
+def view_shared_upload_dir(request, token):
+ assert token is not None # Checked by URLconf
+
+ try:
+ uploadlink = UploadLinkShare.objects.get(token=token)
+ except UploadLinkShare.DoesNotExist:
+ raise Http404
+
+ username = uploadlink.username
+ repo_id = uploadlink.repo_id
+ path = uploadlink.path
+ dir_name = os.path.basename(path[:-1])
+
+ repo = get_repo(repo_id)
+ if not repo:
+ raise Http404
+
+ uploadlink.view_cnt = F('view_cnt') + 1
+ uploadlink.save()
+
+ max_upload_file_size = MAX_UPLOAD_FILE_SIZE
+ no_quota = True if seaserv.check_quota(repo_id) < 0 else False
+
+ token = seafile_api.get_httpserver_access_token(repo_id, 'dummy',
+ 'upload', request.user.username)
+ ajax_upload_url = gen_file_upload_url(token, 'upload-api').replace('api', 'aj')
+
+ return render_to_response('view_shared_upload_dir.html', {
+ 'repo': repo,
+ 'token': token,
+ 'path': path,
+ 'username': username,
+ 'dir_name': dir_name,
+ 'max_upload_file_size': max_upload_file_size,
+ 'no_quota': no_quota,
+ 'ajax_upload_url': ajax_upload_url
+ }, context_instance=RequestContext(request))
+
def demo(request):
"""
Login as demo account.
diff --git a/seahub/views/ajax.py b/seahub/views/ajax.py
index 2f4ca9af08..e639db603d 100644
--- a/seahub/views/ajax.py
+++ b/seahub/views/ajax.py
@@ -20,7 +20,8 @@ from seahub.contacts.models import Contact
from seahub.forms import RepoNewDirentForm, RepoRenameDirentForm
from seahub.options.models import UserOptions, CryptoOptionNotSetError
from seahub.views import get_repo_dirents
-from seahub.views.repo import get_nav_path, get_fileshare, get_dir_share_link
+from seahub.views.repo import get_nav_path, get_fileshare, get_dir_share_link, \
+ get_uploadlink, get_dir_shared_upload_link
import seahub.settings as settings
from seahub.utils import check_filename_with_rename, EMPTY_SHA1, gen_block_get_url
from seahub.utils.star import star_file, unstar_file
@@ -229,6 +230,8 @@ def list_dir(request, repo_id):
zipped = get_nav_path(path, repo.name)
fileshare = get_fileshare(repo.id, username, path)
dir_shared_link = get_dir_share_link(fileshare)
+ uploadlink = get_uploadlink(repo.id, username, path)
+ dir_shared_upload_link = get_dir_shared_upload_link(uploadlink)
ctx = {
'repo': repo,
@@ -238,6 +241,8 @@ def list_dir(request, repo_id):
'server_crypto': server_crypto,
'fileshare': fileshare,
'dir_shared_link': dir_shared_link,
+ 'uploadlink': uploadlink,
+ 'dir_shared_upload_link': dir_shared_upload_link,
'dir_list': dir_list,
'file_list': file_list,
'dirent_more': dirent_more,
diff --git a/seahub/views/repo.py b/seahub/views/repo.py
index 6344b84d6c..da7efb881f 100644
--- a/seahub/views/repo.py
+++ b/seahub/views/repo.py
@@ -15,12 +15,12 @@ from seahub.auth.decorators import login_required
from seahub.contacts.models import Contact
from seahub.forms import RepoPassowrdForm
from seahub.options.models import UserOptions, CryptoOptionNotSetError
-from seahub.share.models import FileShare
+from seahub.share.models import FileShare, PrivateFileDirShare, UploadLinkShare
from seahub.views import gen_path_link, get_user_permission, get_repo_dirents, \
get_unencry_rw_repos_by_user
from seahub.utils import get_ccnetapplet_root, gen_file_upload_url, \
- get_httpserver_root, gen_dir_share_link
+ get_httpserver_root, gen_dir_share_link, gen_shared_upload_link
from seahub.settings import ENABLE_SUB_LIBRARY
# Get an instance of a logger
@@ -169,6 +169,22 @@ def get_dir_share_link(fileshare):
dir_shared_link = ''
return dir_shared_link
+def get_uploadlink(repo_id, username, path):
+ if path == '/': # no shared upload link for root dir
+ return None
+
+ l = UploadLinkShare.objects.filter(repo_id=repo_id).filter(
+ username=username).filter(path=path)
+ return l[0] if len(l) > 0 else None
+
+def get_dir_shared_upload_link(uploadlink):
+ # dir shared upload link
+ if uploadlink:
+ dir_shared_upload_link = gen_shared_upload_link(uploadlink.token)
+ else:
+ dir_shared_upload_link = ''
+ return dir_shared_upload_link
+
def render_repo(request, repo):
"""Steps to show repo page:
If user has permission to view repo
@@ -245,6 +261,8 @@ def render_repo(request, repo):
ajax_update_url = get_ajax_update_url(request, repo.id)
fileshare = get_fileshare(repo.id, username, path)
dir_shared_link = get_dir_share_link(fileshare)
+ uploadlink = get_uploadlink(repo.id, username, path)
+ dir_shared_upload_link = get_dir_shared_upload_link(uploadlink)
return render_to_response('repo.html', {
'repo': repo,
@@ -276,6 +294,8 @@ def render_repo(request, repo):
'contacts': contacts,
'fileshare': fileshare,
'dir_shared_link': dir_shared_link,
+ 'uploadlink': uploadlink,
+ 'dir_shared_upload_link': dir_shared_upload_link,
'search_repo_id': search_repo_id,
'ENABLE_SUB_LIBRARY': ENABLE_SUB_LIBRARY,
'server_crypto': server_crypto,