1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-06-02 12:06:20 +00:00
seahub/views.py

2663 lines
91 KiB
Python
Raw Normal View History

# encoding: utf-8
import settings
import os
import stat
2012-05-30 06:11:33 +00:00
import simplejson as json
2012-07-02 14:45:21 +00:00
import re
import tempfile
2012-06-20 11:39:21 +00:00
import sys
2012-07-23 14:44:09 +00:00
import urllib
2012-07-02 14:45:21 +00:00
import urllib2
from urllib import quote
2012-08-15 02:58:08 +00:00
from django.core.cache import cache
from django.core.urlresolvers import reverse
2012-06-20 11:39:21 +00:00
from django.core.mail import send_mail
2012-06-12 02:13:14 +00:00
from django.contrib import messages
2012-06-20 11:39:21 +00:00
from django.contrib.sites.models import Site, RequestSite
from django.db import IntegrityError
from django.db.models import F
2012-07-30 02:25:46 +00:00
from django.http import HttpResponse, HttpResponseBadRequest, Http404, \
2012-08-15 02:58:08 +00:00
HttpResponseRedirect
2012-04-20 05:34:52 +00:00
from django.shortcuts import render_to_response, redirect
2012-06-20 11:39:21 +00:00
from django.template import Context, loader, RequestContext
2012-09-14 14:15:14 +00:00
from django.template.loader import render_to_string
2012-08-26 03:48:43 +00:00
from django.utils.hashcompat import md5_constructor
2012-11-05 03:55:02 +00:00
from django.utils.translation import ugettext as _
from django.views.decorators.csrf import csrf_protect
from django.views.generic.base import TemplateView, TemplateResponseMixin
from django.views.generic.edit import BaseFormView, FormMixin
from auth.decorators import login_required
2012-10-10 12:04:09 +00:00
from auth import login as auth_login
from auth import authenticate
2012-05-15 02:59:16 +00:00
from auth.forms import AuthenticationForm, PasswordResetForm, SetPasswordForm, \
PasswordChangeForm
2012-04-20 05:34:52 +00:00
from auth.tokens import default_token_generator
from share.models import FileShare
2012-07-27 03:39:55 +00:00
from seaserv import ccnet_rpc, ccnet_threaded_rpc, get_repos, get_emailusers, \
get_repo, get_commits, get_branches, is_valid_filename, remove_group_user,\
2012-09-22 09:46:56 +00:00
seafserv_threaded_rpc, seafserv_rpc, get_binding_peerids, is_repo_owner, \
check_group_staff, get_personal_groups_by_user, is_inner_pub_repo, \
del_org_group_repo, get_personal_groups, \
2012-09-03 04:03:06 +00:00
get_group, get_shared_groups_by_repo, is_group_user, check_permission, \
2012-09-04 13:05:20 +00:00
list_personal_shared_repos, is_org_group, get_org_id_by_group, is_org_repo,\
list_inner_pub_repos, get_org_groups_by_repo, is_org_repo_owner, \
get_org_repo_owner, is_passwd_set, get_file_size, \
2012-10-16 06:47:36 +00:00
get_related_users_by_repo, get_related_users_by_org_repo, HtmlDiff
from pysearpc import SearpcError
2011-09-10 12:07:46 +00:00
2012-09-24 12:30:17 +00:00
from signals import repo_created, repo_deleted
2012-08-06 02:58:34 +00:00
from base.accounts import User
2012-08-31 09:28:50 +00:00
from base.decorators import sys_staff_required, ctx_switch_required
from base.mixins import LoginRequiredMixin, CtxSwitchRequiredMixin
2012-09-14 14:15:14 +00:00
from base.models import UuidObjidMap, FileComment, InnerPubMsg, InnerPubMsgReply
from contacts.models import Contact
from contacts.signals import mail_sended
from group.forms import MessageForm, MessageReplyForm
2012-08-26 03:48:43 +00:00
from group.models import GroupMessage, MessageAttachment
from group.signals import grpmsg_added
2012-09-14 14:15:14 +00:00
from notifications.models import UserNotification
from profile.models import Profile
2012-11-06 03:12:49 +00:00
from forms import AddUserForm, RepoCreateForm, RepoNewDirForm, RepoNewFileForm,\
FileCommentForm, RepoRenameFileForm, RepoPassowrdForm, SharedRepoCreateForm,\
SetUserQuotaForm
2012-07-30 12:44:32 +00:00
from utils import render_permission_error, render_error, list_to_string, \
2012-11-06 03:12:49 +00:00
get_httpserver_root, get_ccnetapplet_root, \
2012-07-02 14:45:21 +00:00
calculate_repo_last_modify, valid_previewed_file, \
check_filename_with_rename, get_accessible_repos, EMPTY_SHA1, \
2012-07-23 14:44:09 +00:00
get_file_revision_id_size, get_ccnet_server_addr_port, \
gen_file_get_url, string2list, MAX_INT, \
gen_file_upload_url, check_and_get_org_by_repo, \
2012-10-26 11:50:36 +00:00
get_file_contributors, EVENTS_ENABLED, get_user_events, \
get_starred_files, star_file, unstar_file, is_file_starred
try:
2012-09-13 06:01:32 +00:00
from settings import DOCUMENT_CONVERTOR_ROOT
if DOCUMENT_CONVERTOR_ROOT[-1:] != '/':
DOCUMENT_CONVERTOR_ROOT += '/'
except ImportError:
2012-09-13 06:01:32 +00:00
DOCUMENT_CONVERTOR_ROOT = None
2012-08-06 08:30:51 +00:00
from settings import FILE_PREVIEW_MAX_SIZE, INIT_PASSWD
2012-01-31 16:07:10 +00:00
@login_required
2011-03-19 05:15:02 +00:00
def root(request):
2012-01-31 16:07:10 +00:00
return HttpResponseRedirect(reverse(myhome))
def validate_owner(request, repo_id):
2012-06-12 02:13:14 +00:00
"""
2012-07-30 02:25:46 +00:00
Check whether user in the request owns the repo.
2012-06-12 02:13:14 +00:00
"""
2012-07-30 02:25:46 +00:00
ret = is_repo_owner(request.user.username, repo_id)
2012-07-30 02:25:46 +00:00
return True if ret else False
def is_registered_user(email):
2012-06-12 02:13:14 +00:00
"""
2012-07-30 02:25:46 +00:00
Check whether user is registerd.
2012-06-12 02:13:14 +00:00
"""
try:
user = User.objects.get(email=email)
except User.DoesNotExist:
2012-06-12 02:13:14 +00:00
user = None
return True if user else False
2012-06-12 02:13:14 +00:00
2012-08-27 06:38:36 +00:00
def access_to_repo(request, repo_id, repo_ap=None):
2012-05-22 07:28:24 +00:00
"""
Check whether user in the request can access to repo, which means user can
view directory entries on repo page. Only repo owner or person who is shared
2012-07-30 02:25:46 +00:00
can access to repo.
NOTE: `repo_ap` may be used in future.
2012-05-22 07:28:24 +00:00
"""
2012-08-27 06:38:36 +00:00
if not request.user.is_authenticated():
token = request.COOKIES.get('anontoken', None)
return True if token else False
2012-07-30 02:25:46 +00:00
else:
return True if check_permission(repo_id, request.user.username) else False
def get_user_permission(request, repo_id):
if request.user.is_authenticated():
return check_permission(repo_id, request.user.username)
else:
token = request.COOKIES.get('anontoken', None)
return 'r' if token else ''
2012-05-22 07:28:24 +00:00
def gen_path_link(path, repo_name):
"""
2012-07-03 13:48:33 +00:00
Generate navigate paths and links in repo page.
2012-05-22 07:28:24 +00:00
"""
if path and path[-1] != '/':
2012-07-11 09:47:08 +00:00
path += '/'
2012-05-22 07:28:24 +00:00
paths = []
links = []
if path and path != '/':
paths = path[1:-1].split('/')
i=1
for name in paths:
link = '/' + '/'.join(paths[:i])
i = i + 1
links.append(link)
2012-09-30 11:40:35 +00:00
if repo_name:
paths.insert(0, repo_name)
links.insert(0, '/')
2012-05-22 07:28:24 +00:00
zipped = zip(paths, links)
return zipped
2012-08-31 09:28:50 +00:00
2012-09-30 11:40:35 +00:00
def get_repo_dirents(commit, path):
dir_list = []
file_list = []
if commit.root_id == EMPTY_SHA1:
return ([], [])
else:
try:
dirs = seafserv_threaded_rpc.list_dir_by_path(commit.id, path.encode('utf-8'))
except SearpcError, e:
raise Http404
# return render_error(self.request, e.msg)
for dirent in dirs:
if stat.S_ISDIR(dirent.props.mode):
dir_list.append(dirent)
else:
file_list.append(dirent)
dirent.file_size = get_file_size(dirent.obj_id)
dir_list.sort(lambda x, y : cmp(x.obj_name.lower(),
y.obj_name.lower()))
file_list.sort(lambda x, y : cmp(x.obj_name.lower(),
y.obj_name.lower()))
return (file_list, dir_list)
class RepoMixin(object):
def get_repo_id(self):
return self.kwargs.get('repo_id', '')
2012-04-24 08:15:29 +00:00
def get_path(self):
2012-09-13 05:53:26 +00:00
path = self.request.GET.get('p', '/')
if path[-1] != '/':
path = path + '/'
return path
2012-07-03 13:48:33 +00:00
def get_user(self):
return self.request.user
def get_repo(self, repo_id):
repo = get_repo(repo_id)
if not repo:
raise Http404
return repo
def get_repo_size(self):
repo_size = seafserv_threaded_rpc.server_repo_size(self.repo.id)
return repo_size
def is_password_set(self):
if self.repo.encrypted:
return is_passwd_set(self.repo.id, self.user.username)
return False
def get_nav_path(self):
zipped = gen_path_link(self.path, self.repo.name)
return zipped
def get_applet_root(self):
return get_ccnetapplet_root()
def get_current_commit(self):
2012-09-13 09:45:15 +00:00
# Get newest commit by default, subclasses can override this method.
current_commit = get_commits(self.repo.id, 0, 1)[0]
return current_commit
def get_success_url(self):
2012-09-26 12:44:15 +00:00
next = self.request.GET.get('next', '')
if next:
return next
return reverse('repo', args=[self.repo_id])
def prepare_property(self):
# NOTE: order is important.
self.repo_id = self.get_repo_id()
self.user = self.get_user()
self.path = self.get_path()
self.repo = self.get_repo(self.repo_id)
self.repo_size = self.get_repo_size()
# self.can_access = access_to_repo(self.request, self.repo_id)
self.user_perm = get_user_permission(self.request, self.repo_id)
self.current_commit = self.get_current_commit()
self.password_set = self.is_password_set()
if self.repo.encrypt and not self.password_set:
# Repo is encrypt and password is not set, then no need to
# query following informations.
self.file_list, self.dir_list = [], []
self.zipped = None
self.applet_root = None
else:
2012-09-30 11:40:35 +00:00
self.file_list, self.dir_list = get_repo_dirents(self.current_commit, self.path)
self.zipped = self.get_nav_path()
self.applet_root = self.get_applet_root()
def get(self, request, *args, **kwargs):
self.prepare_property()
return super(RepoMixin, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.prepare_property()
return super(RepoMixin, self).post(request, *args, **kwargs)
2012-11-01 03:50:01 +00:00
class RepoView(LoginRequiredMixin, CtxSwitchRequiredMixin, RepoMixin,
TemplateResponseMixin, BaseFormView):
2012-09-13 09:45:15 +00:00
"""
View to show repo page and handle post request to decrypt repo.
"""
form_class = RepoPassowrdForm
def get_template_names(self):
if self.repo.encrypted and not self.password_set:
template_name = 'decrypt_repo_form.html'
else:
template_name = 'repo.html'
return template_name
2012-08-13 13:26:58 +00:00
def get_accessible_repos(self):
if self.user.is_authenticated():
accessible_repos = get_accessible_repos(self.request, self.repo)
else:
accessible_repos = []
return accessible_repos
def get_repo_shared_groups(self):
if self.user.org:
org_id = self.user.org['org_id']
repo_shared_groups = get_org_groups_by_repo(org_id, self.repo_id)
else:
repo_shared_groups = get_shared_groups_by_repo(self.repo_id)
2012-09-14 03:39:33 +00:00
# Filter out groups that user is joined.
groups = [ x for x in repo_shared_groups if \
is_group_user(x.id, self.user.username)]
return groups
2012-10-26 11:50:36 +00:00
def is_starred_dir(self):
org_id = -1
if self.request.user.org:
org_id = self.request.user.org['org_id']
args = (self.request.user.username, self.repo.id, self.path.encode('utf-8'), org_id)
return is_file_starred(*args)
def get_context_data(self, **kwargs):
kwargs['repo'] = self.repo
# kwargs['can_access'] = self.can_access
kwargs['user_perm'] = self.user_perm
kwargs['current_commit'] = self.get_current_commit()
kwargs['password_set'] = self.password_set
kwargs['repo_size'] = self.repo_size
kwargs['dir_list'] = self.dir_list
kwargs['file_list'] = self.file_list
kwargs['path'] = self.path
kwargs['zipped'] = self.zipped
kwargs['accessible_repos'] = self.get_accessible_repos()
kwargs['applet_root'] = self.applet_root
kwargs['groups'] = self.get_repo_shared_groups()
2012-10-26 11:50:36 +00:00
kwargs['is_starred'] = self.is_starred_dir()
kwargs['next'] = self.get_success_url()
if len(kwargs['groups']) > 1:
ctx = {}
ctx['groups'] = kwargs['groups']
repogrp_str = render_to_string("snippets/repo_group_list.html", ctx)
kwargs['repo_group_str'] = repogrp_str
else:
kwargs['repo_group_str'] = ''
return kwargs
2012-09-13 14:11:00 +00:00
class RepoHistoryView(LoginRequiredMixin, CtxSwitchRequiredMixin, RepoMixin,
TemplateView):
2012-09-13 09:45:15 +00:00
"""
View to show repo page in history.
"""
def get_template_names(self):
if self.repo.encrypted and not self.password_set:
template_name = 'decrypt_repo_form.html'
else:
template_name = 'repo_history_view.html'
return template_name
def get_current_commit(self):
commit_id = self.request.GET.get('commit_id', '')
if not commit_id:
return HttpResponseRedirect(reverse('repo', args=[repo_id]))
current_commit = seafserv_threaded_rpc.get_commit(commit_id)
if not current_commit:
current_commit = get_commits(repo_id, 0, 1)[0]
return current_commit
def get_context_data(self, **kwargs):
kwargs['repo'] = self.repo
# kwargs['can_access'] = self.can_access
kwargs['user_perm'] = self.user_perm
kwargs['current_commit'] = self.get_current_commit()
kwargs['password_set'] = self.password_set
kwargs['repo_size'] = self.repo_size
kwargs['dir_list'] = self.dir_list
kwargs['file_list'] = self.file_list
kwargs['path'] = self.path
kwargs['zipped'] = self.zipped
return kwargs
2012-09-30 11:40:35 +00:00
def render_recycle_root(request, repo_id):
repo = get_repo(repo_id)
if not repo:
raise Http404
try:
deleted_entries = seafserv_threaded_rpc.get_deleted(repo_id)
except:
deleted_entries = []
dir_list = []
file_list = []
for dirent in deleted_entries:
if stat.S_ISDIR(dirent.mode):
dir_list.append(dirent)
else:
file_list.append(dirent)
dir_list.sort(lambda x, y : cmp(x.obj_name.lower(),
y.obj_name.lower()))
file_list.sort(lambda x, y : cmp(x.obj_name.lower(),
y.obj_name.lower()))
return render_to_response('repo_recycle_view.html', {
'show_recycle_root': True,
'repo': repo,
'dir_list': dir_list,
'file_list': file_list,
}, context_instance=RequestContext(request))
def render_recycle_dir(request, repo_id, commit_id):
basedir = request.GET.get('base', '')
path = request.GET.get('p', '')
if not basedir or not path:
return render_recycle_root(request, repo_id)
if basedir[0] != '/':
basedir = '/' + basedir
if path[-1] != '/':
path += '/'
repo = get_repo(repo_id)
if not repo:
raise Http404
commit = seafserv_threaded_rpc.get_commit(commit_id)
if not commit:
raise Http404
zipped = gen_path_link(path, '')
file_list, dir_list = get_repo_dirents(commit, basedir + path)
return render_to_response('repo_recycle_view.html', {
'show_recycle_root': False,
'repo': repo,
'zipped': zipped,
'dir_list': dir_list,
'file_list': file_list,
'commit_id': commit_id,
'basedir': basedir,
'path': path,
}, context_instance=RequestContext(request))
@login_required
@ctx_switch_required
def repo_recycle_view(request, repo_id):
if get_user_permission(request, repo_id) != 'rw':
2012-11-06 09:22:46 +00:00
return render_permission_error(request, _(u'Unable to view recycle page'))
2012-09-30 11:40:35 +00:00
commit_id = request.GET.get('commit_id', '')
if not commit_id:
return render_recycle_root(request, repo_id)
else:
return render_recycle_dir(request, repo_id, commit_id)
2012-08-31 09:28:50 +00:00
@login_required
@ctx_switch_required
def repo_upload_file(request, repo_id):
repo = get_repo(repo_id)
if request.method == 'GET':
2012-07-11 09:47:08 +00:00
parent_dir = request.GET.get('p', '/')
zipped = gen_path_link (parent_dir, repo.name)
2012-08-14 12:36:19 +00:00
if get_user_permission(request, repo_id) == 'rw':
2012-09-14 11:35:19 +00:00
token = seafserv_rpc.web_get_access_token(repo_id,
'dummy',
'upload',
request.user.username)
2012-08-14 12:36:19 +00:00
else:
2012-11-05 06:35:37 +00:00
return render_permission_error(request, _(u'Can not access library'))
no_quota = False
if seafserv_threaded_rpc.check_quota(repo_id) < 0:
no_quota = True
2012-08-14 12:36:19 +00:00
upload_url = gen_file_upload_url(token, 'upload')
httpserver_root = get_httpserver_root()
return render_to_response ('repo_upload_file.html', {
"repo": repo,
2012-08-14 12:36:19 +00:00
"upload_url": upload_url,
"httpserver_root": httpserver_root,
"parent_dir": parent_dir,
"zipped": zipped,
"max_upload_file_size": settings.MAX_UPLOAD_FILE_SIZE,
"no_quota": no_quota,
}, context_instance=RequestContext(request))
2012-07-11 09:47:08 +00:00
@login_required
2012-08-31 09:28:50 +00:00
@ctx_switch_required
2012-07-11 09:47:08 +00:00
def repo_update_file(request, repo_id):
repo = get_repo(repo_id)
2012-07-11 09:47:08 +00:00
if request.method == 'GET':
target_file = request.GET.get('p')
if not target_file:
2012-11-05 06:35:37 +00:00
return render_error(request, _(u'Invalid url'))
2012-07-11 09:47:08 +00:00
zipped = gen_path_link (target_file, repo.name)
2012-08-14 12:36:19 +00:00
if get_user_permission(request, repo_id) == 'rw':
2012-09-14 11:35:19 +00:00
token = seafserv_rpc.web_get_access_token(repo_id,
'dummy',
'update',
request.user.username)
2012-08-14 12:36:19 +00:00
else:
2012-11-05 06:35:37 +00:00
return render_permission_error(request, _(u'Can not access library'))
no_quota = False
if seafserv_threaded_rpc.check_quota(repo_id) < 0:
no_quota = True
2012-08-14 12:36:19 +00:00
update_url = gen_file_upload_url(token, 'update')
httpserver_root = get_httpserver_root()
2012-07-11 09:47:08 +00:00
return render_to_response ('repo_update_file.html', {
"repo": repo,
2012-08-14 12:36:19 +00:00
"update_url": update_url,
"httpserver_root": httpserver_root,
2012-07-11 09:47:08 +00:00
"target_file": target_file,
"zipped": zipped,
"max_upload_file_size": settings.MAX_UPLOAD_FILE_SIZE,
"no_quota": no_quota,
"head_id": repo.head_cmmt_id,
2012-07-11 09:47:08 +00:00
}, context_instance=RequestContext(request))
def upload_error_msg (code):
2012-11-05 06:35:37 +00:00
err_msg = _(u'Internal Server Error')
if (code == 0):
2012-11-05 06:35:37 +00:00
err_msg = _(u'Filename contains invalid character')
elif (code == 1):
2012-11-05 06:35:37 +00:00
err_msg = _(u'Duplicated filename')
elif (code == 2):
2012-11-05 06:35:37 +00:00
err_msg = _(u'File not exists')
elif (code == 3):
2012-11-05 06:35:37 +00:00
err_msg = _(u'File size surpasses the limit')
elif (code == 4):
2012-11-05 06:35:37 +00:00
err_msg = _(u'The space of owner is used up, upload failed')
elif (code == 5):
2012-11-05 06:35:37 +00:00
err_msg = _(u'An error occurs during file transfer')
return err_msg
2012-08-31 09:28:50 +00:00
@ctx_switch_required
def upload_file_error(request, repo_id):
if request.method == 'GET':
repo = get_repo(repo_id)
parent_dir = request.GET.get('p')
2012-10-31 03:16:59 +00:00
filename = request.GET.get('fn', '')
err = request.GET.get('err')
2012-10-31 03:16:59 +00:00
if not parent_dir or not err:
2012-11-05 06:35:37 +00:00
return render_error(request, _(u'Invalid url'))
zipped = gen_path_link (parent_dir, repo.name)
code = int(err)
err_msg = upload_error_msg(code)
return render_to_response('upload_file_error.html', {
'repo': repo,
'zipped': zipped,
'filename': filename,
'err_msg': err_msg,
}, context_instance=RequestContext(request))
2012-08-31 09:28:50 +00:00
@ctx_switch_required
def update_file_error(request, repo_id):
if request.method == 'GET':
repo = get_repo(repo_id)
target_file = request.GET.get('p')
err = request.GET.get('err')
if not target_file or not err:
2012-11-05 06:35:37 +00:00
return render_error(request, _(u'Invalid url'))
zipped = gen_path_link (target_file, repo.name)
code = int(err)
err_msg = upload_error_msg(code)
return render_to_response('update_file_error.html', {
'repo': repo,
'zipped': zipped,
'err_msg': err_msg,
}, context_instance=RequestContext(request))
def get_subdir(request):
repo_id = request.GET.get('repo_id', '')
path = request.GET.get('path', '')
if not (repo_id and path):
2012-07-30 12:44:32 +00:00
return render_error(request)
latest_commit = get_commits(repo_id, 0, 1)[0]
try:
dirents = seafserv_threaded_rpc.list_dir_by_path(latest_commit.id, path.encode('utf-8'))
except SearpcError, e:
2012-07-30 12:44:32 +00:00
return render_error(request, e.msg)
subdirs = []
for dirent in dirents:
if not stat.S_ISDIR(dirent.props.mode):
continue
dirent.has_subdir = False
path_ = os.path.join (path, dirent.obj_name)
try:
dirs_ = seafserv_threaded_rpc.list_dir_by_path(latest_commit.id, path_.encode('utf-8'))
except SearpcError, e:
2012-07-30 12:44:32 +00:00
return render_error(request, e.msg)
for dirent_ in dirs_:
if stat.S_ISDIR(dirent_.props.mode):
dirent.has_subdir = True
break
if dirent.has_subdir:
subdir = {
'data': dirent.obj_name,
'attr': {'repo_id': repo_id },
'state': 'closed'
}
subdirs.append(subdir)
else:
subdirs.append(dirent.obj_name)
content_type = 'application/json; charset=utf-8'
return HttpResponse(json.dumps(subdirs),
content_type=content_type)
2012-08-31 09:28:50 +00:00
2012-06-20 13:38:07 +00:00
@login_required
2012-08-31 09:28:50 +00:00
@ctx_switch_required
2012-04-24 08:15:29 +00:00
def repo_history(request, repo_id):
"""
View repo history.
"""
2012-07-30 02:25:46 +00:00
if not access_to_repo(request, repo_id, ''):
2012-11-05 06:35:37 +00:00
return render_permission_error(request, _(u'Unable to view library modification'))
2012-04-24 08:15:29 +00:00
repo = get_repo(repo_id)
password_set = False
if repo.props.encrypted:
try:
ret = seafserv_rpc.is_passwd_set(repo_id, request.user.username)
if ret == 1:
password_set = True
except SearpcError, e:
2012-07-30 12:44:32 +00:00
return render_error(request, e.msg)
if repo.props.encrypted and not password_set:
return HttpResponseRedirect(reverse('repo', args=[repo_id]))
2012-03-30 05:49:32 +00:00
try:
current_page = int(request.GET.get('page', '1'))
per_page= int(request.GET.get('per_page', '25'))
except ValueError:
2012-04-09 08:48:14 +00:00
current_page = 1
2012-03-30 05:49:32 +00:00
per_page = 25
commits_all = get_commits(repo_id, per_page * (current_page -1),
per_page + 1)
2012-03-30 05:49:32 +00:00
commits = commits_all[:per_page]
if len(commits_all) == per_page + 1:
page_next = True
else:
page_next = False
2012-04-24 08:15:29 +00:00
return render_to_response('repo_history.html', {
2011-09-07 02:57:47 +00:00
"repo": repo,
"commits": commits,
2012-03-30 05:49:32 +00:00
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'per_page': per_page,
'page_next': page_next,
2011-09-07 02:57:47 +00:00
}, context_instance=RequestContext(request))
@login_required
@ctx_switch_required
def repo_view_snapshot(request, repo_id):
if not access_to_repo(request, repo_id, ''):
2012-11-05 06:35:37 +00:00
return render_permission_error(request, _(u'Unable to view library snapshots'))
repo = get_repo(repo_id)
password_set = False
if repo.props.encrypted:
try:
ret = seafserv_rpc.is_passwd_set(repo_id, request.user.username)
if ret == 1:
password_set = True
except SearpcError, e:
return render_error(request, e.msg)
if repo.props.encrypted and not password_set:
return HttpResponseRedirect(reverse('repo', args=[repo_id]))
try:
current_page = int(request.GET.get('page', '1'))
per_page= int(request.GET.get('per_page', '25'))
except ValueError:
current_page = 1
per_page = 25
# don't show the current commit
commits_all = get_commits(repo_id, per_page * (current_page -1) + 1,
per_page + 2)
commits = commits_all[:per_page]
if len(commits_all) == per_page + 1:
page_next = True
else:
page_next = False
return render_to_response('repo_view_snapshot.html', {
"repo": repo,
"commits": commits,
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'per_page': per_page,
'page_next': page_next,
}, context_instance=RequestContext(request))
@login_required
2012-05-25 09:07:08 +00:00
def repo_history_revert(request, repo_id):
repo = get_repo(repo_id)
if not repo:
raise Http404
if not access_to_repo(request, repo_id):
2012-11-05 06:35:37 +00:00
return render_permission_error(request, _(u'You have no permission to restore library'))
2012-05-25 09:07:08 +00:00
password_set = False
if repo.props.encrypted:
try:
ret = seafserv_rpc.is_passwd_set(repo_id, request.user.username)
if ret == 1:
password_set = True
except SearpcError, e:
2012-07-30 12:44:32 +00:00
return render_error(request, e.msg)
2012-05-25 09:07:08 +00:00
if repo.props.encrypted and not password_set:
return HttpResponseRedirect(reverse('repo', args=[repo_id]))
2012-05-25 09:07:08 +00:00
commit_id = request.GET.get('commit_id', '')
if not commit_id:
2012-11-05 06:35:37 +00:00
return render_error(request, _(u'Please specify history ID'))
2012-05-25 09:07:08 +00:00
try:
2012-08-14 10:40:36 +00:00
seafserv_threaded_rpc.revert_on_server(repo_id, commit_id, request.user.username)
2012-05-25 09:07:08 +00:00
except SearpcError, e:
if e.msg == 'Bad arguments':
2012-11-05 06:35:37 +00:00
return render_error(request, _(u'Invalid arguments'))
2012-05-25 09:07:08 +00:00
elif e.msg == 'No such repo':
2012-11-05 06:35:37 +00:00
return render_error(request, _(u'Library not exists'))
2012-05-25 09:07:08 +00:00
elif e.msg == "Commit doesn't exist":
2012-11-05 06:35:37 +00:00
return render_error(request, _(u'History you specified is not exists'))
2012-05-25 09:07:08 +00:00
else:
2012-11-05 06:35:37 +00:00
return render_error(request, _(u'Unknown error'))
2012-05-25 09:07:08 +00:00
return HttpResponseRedirect(reverse(repo_history, args=[repo_id]))
2012-09-25 12:07:46 +00:00
2012-10-12 11:30:57 +00:00
def fpath_to_link(repo_id, path, is_dir=False):
2012-09-25 12:07:46 +00:00
"""Translate file path of a repo to its view link"""
2012-10-12 11:30:57 +00:00
if is_dir:
2012-10-12 11:46:08 +00:00
url = reverse("repo", args=[repo_id])
2012-10-12 11:30:57 +00:00
else:
2012-10-12 11:46:08 +00:00
url = reverse("repo_view_file", args=[repo_id])
href = url + '?p=/%s' % urllib2.quote(path.encode('utf-8'))
2012-09-25 12:07:46 +00:00
return '<a href="%s">%s</a>' % (href, path)
2012-05-30 06:11:33 +00:00
def get_diff(repo_id, arg1, arg2):
2012-07-05 11:56:39 +00:00
lists = {'new' : [], 'removed' : [], 'renamed' : [], 'modified' : [], \
'newdir' : [], 'deldir' : []}
2012-05-30 06:11:33 +00:00
diff_result = seafserv_threaded_rpc.get_diff(repo_id, arg1, arg2)
2012-06-13 11:56:41 +00:00
if not diff_result:
return lists
for d in diff_result:
if d.status == "add":
2012-09-25 12:07:46 +00:00
lists['new'].append(fpath_to_link(repo_id, d.name))
2012-06-13 11:56:41 +00:00
elif d.status == "del":
lists['removed'].append(d.name)
elif d.status == "mov":
2012-09-25 12:07:46 +00:00
lists['renamed'].append(d.name + " ==> " + fpath_to_link(repo_id, d.new_name))
2012-06-13 11:56:41 +00:00
elif d.status == "mod":
2012-09-25 12:07:46 +00:00
lists['modified'].append(fpath_to_link(repo_id, d.name))
2012-07-05 11:56:39 +00:00
elif d.status == "newdir":
2012-10-12 11:30:57 +00:00
lists['newdir'].append(fpath_to_link(repo_id, d.name, is_dir=True))
2012-07-05 11:56:39 +00:00
elif d.status == "deldir":
lists['deldir'].append(d.name)
2012-05-30 06:11:33 +00:00
return lists
def repo_history_changes(request, repo_id):
changes = {}
content_type = 'application/json; charset=utf-8'
2012-07-30 02:25:46 +00:00
if not access_to_repo(request, repo_id, ''):
2012-05-30 06:11:33 +00:00
return HttpResponse(json.dumps(changes),
content_type=content_type)
repo = get_repo(repo_id)
if not repo:
return HttpResponse(json.dumps(changes),
content_type=content_type)
password_set = False
if repo.props.encrypted:
try:
ret = seafserv_rpc.is_passwd_set(repo_id, request.user.username)
if ret == 1:
password_set = True
except:
return HttpResponse(json.dumps(changes),
content_type=content_type)
if repo.props.encrypted and not password_set:
return HttpResponse(json.dumps(changes),
content_type=content_type)
commit_id = request.GET.get('commit_id', '')
if not commit_id:
return HttpResponse(json.dumps(changes),
content_type=content_type)
changes = get_diff(repo_id, '', commit_id)
return HttpResponse(json.dumps(changes),
content_type=content_type)
2012-10-16 06:47:36 +00:00
2011-10-18 07:41:48 +00:00
@login_required
def modify_token(request, repo_id):
if not validate_owner(request, repo_id):
return HttpResponseRedirect(reverse('repo', args=[repo_id]))
2011-10-18 07:41:48 +00:00
token = request.POST.get('token', '')
if token:
2012-02-27 07:24:27 +00:00
seafserv_threaded_rpc.set_repo_token(repo_id, token)
2011-10-18 07:41:48 +00:00
return HttpResponseRedirect(reverse('repo', args=[repo_id]))
@login_required
def remove_repo(request, repo_id):
2012-09-24 12:30:17 +00:00
repo = get_repo(repo_id)
if not repo:
2012-11-05 06:35:37 +00:00
return render_error(request, _(u'Library not exists'))
2012-09-24 12:30:17 +00:00
2012-09-04 13:05:20 +00:00
user = request.user.username
org, base_template = check_and_get_org_by_repo(repo_id, user)
if org:
# Remove repo in org context, only repo owner or org staff can
# perform this operation.
if request.user.is_staff or org.is_staff or \
is_org_repo_owner(org.org_id, repo_id, user):
# Must get related useres before remove the repo
usernames = get_related_users_by_org_repo(org.org_id, repo_id)
2012-09-04 13:05:20 +00:00
seafserv_threaded_rpc.remove_repo(repo_id)
repo_deleted.send(sender=None,
org_id=org.org_id,
usernames=usernames,
repo_owner=user,
repo_id=repo_id,
repo_name=repo.name,
)
2012-09-04 13:05:20 +00:00
else:
2012-11-05 06:35:37 +00:00
err_msg = _(u'Failed to remove library. Only staff or owner can perform this operation.')
2012-09-04 13:05:20 +00:00
return render_permission_error(request, err_msg)
else:
# Remove repo in personal context, only repo owner or site staff can
# perform this operation.
if validate_owner(request, repo_id) or request.user.is_staff:
2012-09-24 12:30:17 +00:00
usernames = get_related_users_by_repo(repo_id)
2012-09-04 13:05:20 +00:00
seafserv_threaded_rpc.remove_repo(repo_id)
2012-09-24 12:30:17 +00:00
repo_deleted.send(sender=None,
org_id=-1,
2012-09-24 12:30:17 +00:00
usernames=usernames,
repo_owner=user,
repo_id=repo_id,
repo_name=repo.name,
)
2012-09-04 13:05:20 +00:00
else:
2012-11-05 06:35:37 +00:00
err_msg = _(u'Failed to remove library. Only staff or owner can perform this operation.')
2012-09-04 13:05:20 +00:00
return render_permission_error(request, err_msg)
2012-09-04 09:15:19 +00:00
next = request.META.get('HTTP_REFERER', None)
if not next:
next = settings.SITE_ROOT
2012-06-05 11:38:28 +00:00
return HttpResponseRedirect(next)
2011-09-07 02:57:47 +00:00
@login_required
def myhome(request):
2011-10-12 16:17:48 +00:00
owned_repos = []
quota_usage = 0
email = request.user.username
quota = seafserv_threaded_rpc.get_user_quota(email)
quota_usage = seafserv_threaded_rpc.get_user_quota_usage(email)
2012-06-28 08:58:09 +00:00
2012-09-03 04:03:06 +00:00
# Personal repos that I own
owned_repos = seafserv_threaded_rpc.list_owned_repos(email)
2012-06-28 08:58:09 +00:00
calculate_repo_last_modify(owned_repos)
2012-06-28 12:02:17 +00:00
owned_repos.sort(lambda x, y: cmp(y.latest_modify, x.latest_modify))
2012-09-03 04:03:06 +00:00
# Personal repos others shared to me
in_repos = list_personal_shared_repos(email,'to_email', -1, -1)
2012-06-25 13:40:18 +00:00
# user notifications
2012-06-27 08:39:49 +00:00
grpmsg_list = []
2012-06-28 11:24:27 +00:00
grpmsg_reply_list = []
2012-07-27 09:54:07 +00:00
orgmsg_list = []
2012-06-26 06:20:37 +00:00
notes = UserNotification.objects.filter(to_user=request.user.username)
2012-06-25 13:40:18 +00:00
for n in notes:
2012-06-26 06:20:37 +00:00
if n.msg_type == 'group_msg':
grp = get_group(n.detail)
if not grp:
continue
grpmsg_list.append(grp)
2012-06-27 08:39:49 +00:00
elif n.msg_type == 'grpmsg_reply':
2012-06-28 11:24:27 +00:00
grpmsg_reply_list.append(n.detail)
2012-09-06 08:57:54 +00:00
elif n.msg_type == 'org_join_msg':
2012-07-27 09:54:07 +00:00
orgmsg_list.append(n.detail)
2012-06-25 13:40:18 +00:00
2012-10-10 11:20:10 +00:00
# Get all personal groups I joined.
2012-09-22 11:17:22 +00:00
joined_groups = get_personal_groups_by_user(request.user.username)
2012-06-21 12:53:13 +00:00
# get nickname
if not Profile.objects.filter(user=request.user.username):
2012-06-21 07:26:03 +00:00
nickname = ''
else:
profile = Profile.objects.filter(user=request.user.username)[0]
nickname = profile.nickname
2012-07-26 09:08:31 +00:00
2012-10-11 06:34:08 +00:00
if request.cloud_mode:
allow_public_share = False
2012-10-10 11:20:10 +00:00
# In cloud mode, list joined groups and registered contacts for
# autocompletion.
autocomp_groups = joined_groups
contacts = [ c for c in Contact.objects.filter(user_email=email) \
if is_registered_user(c.contact_email) ]
else:
2012-10-11 06:34:08 +00:00
allow_public_share = True
2012-11-06 09:22:46 +00:00
# Clear org messages just in case. Should never happen in production
# environment.
orgmsg_list = []
2012-10-10 11:20:10 +00:00
# List all personal groups and all registered users for autocompletion.
autocomp_groups = get_personal_groups(-1, -1)
contacts = []
for u in get_emailusers(-1, -1):
if u.email == request.user.username:
continue
u.contact_email = u.email
contacts.append(u)
2012-09-28 13:51:04 +00:00
# events
if EVENTS_ENABLED:
events = get_user_events(request.user.username)
2012-09-28 13:51:04 +00:00
else:
events = None
2012-10-26 11:50:36 +00:00
starred_files = get_starred_files(request.user.username)
2011-09-07 02:57:47 +00:00
return render_to_response('myhome.html', {
"nickname": nickname,
2011-10-12 16:17:48 +00:00
"owned_repos": owned_repos,
"quota": quota,
"quota_usage": quota_usage,
2012-04-26 14:15:07 +00:00
"in_repos": in_repos,
2012-05-07 08:33:36 +00:00
"contacts": contacts,
2012-09-22 11:17:22 +00:00
"joined_groups": joined_groups,
2012-10-10 11:20:10 +00:00
"autocomp_groups": autocomp_groups,
"notes": notes,
"grpmsg_list": grpmsg_list,
2012-06-28 11:24:27 +00:00
"grpmsg_reply_list": grpmsg_reply_list,
2012-07-27 09:54:07 +00:00
"orgmsg_list": orgmsg_list,
"create_shared_repo": False,
"allow_public_share": allow_public_share,
2012-09-28 13:51:04 +00:00
"events": events,
2012-10-26 11:50:36 +00:00
"starred_files": starred_files,
2011-09-07 02:57:47 +00:00
}, context_instance=RequestContext(request))
2012-08-17 08:35:50 +00:00
@login_required
def public_home(request):
"""
Show public home page when CLOUD_MODE is False.
"""
2012-09-21 11:57:11 +00:00
# if request.method == 'POST':
# form = MessageForm(request.POST)
# if form.is_valid():
# msg = InnerPubMsg()
# msg.from_email = request.user.username
# msg.message = form.cleaned_data['message']
# msg.save()
# return HttpResponseRedirect(reverse('public_home'))
# else:
# form = MessageForm()
2012-09-14 14:15:14 +00:00
public_repos = list_inner_pub_repos(request.user.username)
2012-09-14 14:15:14 +00:00
2012-09-21 11:57:11 +00:00
# """inner pub messages"""
# # Make sure page request is an int. If not, deliver first page.
# try:
# current_page = int(request.GET.get('page', '1'))
# per_page= int(request.GET.get('per_page', '15'))
# except ValueError:
# current_page = 1
# per_page = 15
# msgs_plus_one = InnerPubMsg.objects.all()[per_page*(current_page-1) :
# per_page*current_page+1]
# if len(msgs_plus_one) == per_page + 1:
# page_next = True
# else:
# page_next = False
# innerpub_msgs = msgs_plus_one[:per_page]
# msg_replies = InnerPubMsgReply.objects.filter(reply_to__in=innerpub_msgs)
# reply_to_list = [ r.reply_to_id for r in msg_replies ]
# for msg in innerpub_msgs:
# msg.reply_cnt = reply_to_list.count(msg.id)
# # remove user notifications
# UserNotification.objects.filter(to_user=request.user.username,
# msg_type='innerpub_msg').delete()
2012-09-14 14:15:14 +00:00
2012-08-17 08:35:50 +00:00
return render_to_response('public_home.html', {
'public_repos': public_repos,
'create_shared_repo': True,
2012-09-21 11:57:11 +00:00
# 'form': form,
# 'innerpub_msgs': innerpub_msgs,
# 'current_page': current_page,
# 'prev_page': current_page-1,
# 'next_page': current_page+1,
# 'per_page': per_page,
# 'page_next': page_next,
2012-08-17 08:35:50 +00:00
}, context_instance=RequestContext(request))
2012-09-14 14:15:14 +00:00
@login_required
def innerpub_msg_reply(request, msg_id):
"""Show inner pub message replies, and process message reply in ajax"""
content_type = 'application/json; charset=utf-8'
if request.is_ajax():
ctx = {}
if request.method == 'POST':
form = MessageReplyForm(request.POST)
# TODO: invalid form
if form.is_valid():
msg = form.cleaned_data['message']
try:
innerpub_msg = InnerPubMsg.objects.get(id=msg_id)
except InnerPubMsg.DoesNotExist:
return HttpResponseBadRequest(content_type=content_type)
msg_reply = InnerPubMsgReply()
msg_reply.reply_to = innerpub_msg
msg_reply.from_email = request.user.username
msg_reply.message = msg
msg_reply.save()
ctx['reply'] = msg_reply
html = render_to_string("group/group_reply_new.html", ctx)
else:
try:
msg = InnerPubMsg.objects.get(id=msg_id)
except InnerPubMsg.DoesNotExist:
raise HttpResponse(status=400)
replies = InnerPubMsgReply.objects.filter(reply_to=msg)
ctx['replies'] = replies
html = render_to_string("group/group_reply_list.html", ctx)
serialized_data = json.dumps({"html": html})
return HttpResponse(serialized_data, content_type=content_type)
else:
return HttpResponseBadRequest(content_type=content_type)
@login_required
def innerpub_msg_reply_new(request):
notes = UserNotification.objects.filter(to_user=request.user.username)
innerpub_reply_list = [ n.detail for n in notes if \
n.msg_type == 'innerpubmsg_reply']
innerpub_msgs = []
for msg_id in innerpub_reply_list:
try:
m = InnerPubMsg.objects.get(id=msg_id)
except InnerPubMsg.DoesNotExist:
continue
else:
m.reply_list = InnerPubMsgReply.objects.filter(reply_to=m)
m.reply_cnt = m.reply_list.count()
innerpub_msgs.append(m)
# remove new innerpub msg reply notification
UserNotification.objects.filter(to_user=request.user.username,
msg_type='innerpubmsg_reply').delete()
return render_to_response("new_innerpubmsg_reply.html", {
'innerpub_msgs': innerpub_msgs,
}, context_instance=RequestContext(request))
2012-08-17 08:35:50 +00:00
@login_required
def public_repo_create(request):
'''
Handle ajax post to create public repo.
'''
if not request.is_ajax() or request.method != 'POST':
return Http404
result = {}
content_type = 'application/json; charset=utf-8'
form = SharedRepoCreateForm(request.POST)
2012-08-17 08:35:50 +00:00
if form.is_valid():
repo_name = form.cleaned_data['repo_name']
repo_desc = form.cleaned_data['repo_desc']
permission = form.cleaned_data['permission']
2012-08-17 08:35:50 +00:00
passwd = form.cleaned_data['passwd']
user = request.user.username
try:
2012-08-27 06:38:36 +00:00
# create a repo
repo_id = seafserv_threaded_rpc.create_repo(repo_name, repo_desc,
user, passwd)
# set this repo as inner pub
seafserv_threaded_rpc.set_inner_pub_repo(repo_id, permission)
2012-08-17 08:35:50 +00:00
except:
repo_id = None
if not repo_id:
2012-11-05 06:35:37 +00:00
result['error'] = _(u'Failed to create repo')
2012-08-17 08:35:50 +00:00
else:
result['success'] = True
2012-09-24 12:30:17 +00:00
repo_created.send(sender=None,
org_id=-1,
2012-09-24 12:30:17 +00:00
creator=user,
repo_id=repo_id,
repo_name=repo_name)
2012-08-17 08:35:50 +00:00
return HttpResponse(json.dumps(result), content_type=content_type)
else:
return HttpResponseBadRequest(json.dumps(form.errors),
content_type=content_type)
2012-09-06 02:56:43 +00:00
@login_required
def unset_inner_pub_repo(request, repo_id):
try:
seafserv_threaded_rpc.unset_inner_pub_repo(repo_id)
2012-11-05 03:55:02 +00:00
messages.success(request, _('Operation successful'))
2012-09-06 02:56:43 +00:00
except SearpcError:
2012-11-05 03:55:02 +00:00
messages.error(request, _('Operation failed'))
return HttpResponseRedirect(reverse('share_admin'))
2012-09-06 02:56:43 +00:00
@login_required
def ownerhome(request, owner_name):
owned_repos = []
quota_usage = 0
owned_repos = seafserv_threaded_rpc.list_owned_repos(owner_name)
quota_usage = seafserv_threaded_rpc.get_user_quota_usage(owner_name)
user_dict = user_info(request, owner_name)
return render_to_response('ownerhome.html', {
"owned_repos": owned_repos,
"quota_usage": quota_usage,
"owner": owner_name,
"user_dict": user_dict,
}, context_instance=RequestContext(request))
2012-03-29 07:36:15 +00:00
@login_required
2012-04-26 02:57:36 +00:00
def repo_set_access_property(request, repo_id):
2012-06-05 11:38:28 +00:00
ap = request.GET.get('ap', '')
seafserv_threaded_rpc.repo_set_access_property(repo_id, ap)
return HttpResponseRedirect(reverse('repo', args=[repo_id]))
2012-04-20 05:34:52 +00:00
@login_required
def repo_del_file(request, repo_id):
if get_user_permission(request, repo_id) != 'rw':
2012-11-04 05:29:20 +00:00
return render_permission_error(request, _('Failed to delete file.'))
parent_dir = request.GET.get("p", "/")
file_name = request.GET.get("file_name")
user = request.user.username
try:
seafserv_threaded_rpc.del_file(repo_id, parent_dir,file_name, user)
2012-11-04 05:29:20 +00:00
messages.success(request, _(u'%s successfully deleted.') % file_name)
2012-07-17 12:53:38 +00:00
except:
2012-11-04 05:29:20 +00:00
messages.error(request, _(u'Internal error. Failed to delete %s.') % file_name)
2012-09-02 12:23:57 +00:00
url = reverse('repo', args=[repo_id]) + ('?p=%s' % urllib2.quote(parent_dir.encode('utf-8')))
return HttpResponseRedirect(url)
2012-08-31 09:28:50 +00:00
@ctx_switch_required
def repo_view_file(request, repo_id):
"""
Preview file on web, including files in current worktree and history.
"""
2012-07-02 14:45:21 +00:00
http_server_root = get_httpserver_root()
path = request.GET.get('p', '/')
2012-07-13 09:26:33 +00:00
u_filename = os.path.basename(path)
filename = urllib2.quote(u_filename.encode('utf-8'))
comment_open = request.GET.get('comment_open', '')
page_from = request.GET.get('from', '')
2012-07-05 11:29:56 +00:00
commit_id = request.GET.get('commit_id', '')
view_history = True if commit_id else False
current_commit = seafserv_threaded_rpc.get_commit(commit_id)
2012-07-05 11:29:56 +00:00
if not current_commit:
current_commit = get_commits(repo_id, 0, 1)[0]
2012-07-02 14:45:21 +00:00
2012-09-30 11:40:35 +00:00
basedir = ''
if page_from == 'recycle':
basedir = request.GET.get('base', '')
if not basedir:
raise Http404
if view_history:
obj_id = request.GET.get('obj_id', '')
else:
2012-07-02 14:45:21 +00:00
try:
2012-07-14 13:18:59 +00:00
obj_id = seafserv_threaded_rpc.get_file_by_path(repo_id, path)
except:
obj_id = None
if not obj_id:
2012-11-06 09:22:46 +00:00
return render_error(request, _(u'File not exists'))
2012-07-02 14:45:21 +00:00
repo = get_repo(repo_id)
if not repo:
raise Http404
2012-09-26 12:44:15 +00:00
if repo.encrypted and not is_passwd_set(repo_id, request.user.username):
# Redirect uesr to decrypt repo page.
return render_to_response('decrypt_repo_form.html', {
'repo': repo,
'next': request.get_full_path(),
}, context_instance=RequestContext(request))
permission = get_user_permission(request, repo_id)
if permission:
2012-07-30 02:25:46 +00:00
# Get a token to visit file
2012-09-14 11:35:19 +00:00
token = seafserv_rpc.web_get_access_token(repo_id,
obj_id,
'view',
request.user.username)
else:
2012-11-06 09:22:46 +00:00
return render_permission_error(request, _(u'Unable to view file'))
read_only = True if permission == 'r' else False
2012-07-02 14:45:21 +00:00
# generate path and link
2012-09-30 11:40:35 +00:00
if page_from == 'recycle':
zipped = gen_path_link(path, '')
else:
zipped = gen_path_link(path, repo.name)
2012-07-02 14:45:21 +00:00
# determin whether file can preview on web
filetype, fileext = valid_previewed_file(filename)
2012-07-23 14:44:09 +00:00
2012-07-02 14:45:21 +00:00
# raw path
2012-07-21 07:06:43 +00:00
raw_path = gen_file_get_url(token, filename)
# get file content
err = ''
file_content = ''
2012-09-21 09:16:07 +00:00
swf_exists = False
pdf_use_flash = False
if filetype == 'Text' or filetype == 'Markdown':
2012-08-22 09:08:52 +00:00
err, file_content, encoding, newline_mode = repo_file_get(raw_path)
2012-09-13 06:01:32 +00:00
elif filetype == 'Document':
2012-09-21 09:16:07 +00:00
err, swf_exists = flash_prepare(raw_path, obj_id, fileext)
elif filetype == 'PDF':
pdf_use_flash = use_flash_for_pdf(request)
if pdf_use_flash:
err, swf_exists = flash_prepare(raw_path, obj_id, 'pdf')
2012-09-30 11:40:35 +00:00
if view_history:
return render_to_response('repo_view_file.html', {
'repo': repo,
'obj_id': obj_id,
'u_filename': u_filename,
'file_name': filename,
'path': path,
'zipped': zipped,
'view_history': view_history,
'current_commit': current_commit,
'token': token,
'filetype': filetype,
'fileext': fileext,
'raw_path': raw_path,
'err': err,
'file_content': file_content,
'swf_exists': swf_exists,
'pdf_use_flash': pdf_use_flash,
'DOCUMENT_CONVERTOR_ROOT': DOCUMENT_CONVERTOR_ROOT,
'page_from': page_from,
'basedir': basedir,
}, context_instance=RequestContext(request))
2012-07-21 07:06:43 +00:00
# file share link
l = FileShare.objects.filter(repo_id=repo_id).filter(\
username=request.user.username).filter(path=path)
fileshare = l[0] if len(l) > 0 else None
http_or_https = request.is_secure() and 'https' or 'http'
domain = RequestSite(request).domain
if fileshare:
file_shared_link = '%s://%s%sf/%s/' % (http_or_https, domain,
settings.SITE_ROOT,
fileshare.token)
else:
file_shared_link = ''
# my constacts
contacts = Contact.objects.filter(user_email=request.user.username)
2012-08-10 13:16:55 +00:00
2012-09-14 03:39:33 +00:00
# Get groups this repo is shared.
if request.user.org:
org_id = request.user.org['org_id']
repo_shared_groups = get_org_groups_by_repo(org_id, repo_id)
else:
repo_shared_groups = get_shared_groups_by_repo(repo_id)
2012-09-11 02:11:44 +00:00
# Filter out groups that user in joined.
groups = [ x for x in repo_shared_groups if \
is_group_user(x.id, request.user.username)]
2012-09-14 03:39:33 +00:00
2012-08-26 03:48:43 +00:00
"""file comments"""
# Make sure page request is an int. If not, deliver first page.
file_path_hash = md5_constructor(urllib2.quote(path.encode('utf-8'))).hexdigest()[:12]
comments = FileComment.objects.filter(file_path_hash=file_path_hash, repo_id=repo_id)
2012-10-16 06:47:36 +00:00
contributors, last_modified, last_commit_id = get_file_contributors(repo_id, path.encode('utf-8'), file_path_hash, obj_id)
2012-09-17 04:57:29 +00:00
latest_contributor = contributors[0]
if len(groups) > 1:
ctx = {}
ctx['groups'] = groups
repogrp_str = render_to_string("snippets/repo_group_list.html", ctx)
else:
repogrp_str = ''
2012-10-26 11:50:36 +00:00
is_starred = False
if page_from != 'recycle':
org_id = -1
if request.user.org:
org_id = request.user.org['org_id']
is_starred = is_file_starred(request.user.username, repo.id, path.encode('utf-8'), org_id)
user_perm = get_user_permission(request, repo_id)
2012-07-02 14:45:21 +00:00
return render_to_response('repo_view_file.html', {
'repo': repo,
'obj_id': obj_id,
2012-07-13 09:26:33 +00:00
'u_filename': u_filename,
2012-07-02 14:45:21 +00:00
'file_name': filename,
'path': path,
2012-07-02 14:45:21 +00:00
'zipped': zipped,
2012-07-03 13:48:33 +00:00
'view_history': view_history,
'current_commit': current_commit,
2012-07-02 14:45:21 +00:00
'token': token,
'filetype': filetype,
'fileext': fileext,
2012-07-02 14:45:21 +00:00
'raw_path': raw_path,
'fileshare': fileshare,
'protocol': http_or_https,
'domain': domain,
'file_shared_link': file_shared_link,
'contacts': contacts,
'err': err,
'file_content': file_content,
2012-08-12 03:22:42 +00:00
"applet_root": get_ccnetapplet_root(),
2012-08-10 13:16:55 +00:00
'groups': groups,
2012-08-26 03:48:43 +00:00
'comments': comments,
'comment_open':comment_open,
2012-09-21 09:16:07 +00:00
'swf_exists': swf_exists,
'pdf_use_flash': pdf_use_flash,
2012-09-13 06:01:32 +00:00
'DOCUMENT_CONVERTOR_ROOT': DOCUMENT_CONVERTOR_ROOT,
'contributors': contributors,
2012-09-17 04:57:29 +00:00
'latest_contributor': latest_contributor,
'last_modified': last_modified,
2012-10-16 06:47:36 +00:00
'last_commit_id': last_commit_id,
'read_only': read_only,
'page_from': page_from,
'repo_group_str': repogrp_str,
2012-10-26 11:50:36 +00:00
'is_starred': is_starred,
'user_perm': user_perm,
2012-07-02 14:45:21 +00:00
}, context_instance=RequestContext(request))
def file_comment(request):
if request.method == 'POST':
# handle post request to leave comment on a file
content_type = 'application/json; charset=utf-8'
path = request.GET.get('p', '');
f = FileCommentForm(request.POST)
if f.is_valid():
repo_id = f.cleaned_data['repo_id']
file_path = f.cleaned_data['file_path']
file_path_hash = md5_constructor(file_path).hexdigest()[:12]
message = f.cleaned_data['message']
fc = FileComment(repo_id=repo_id, file_path=file_path,
file_path_hash=file_path_hash,
from_email=request.user.username, message=message)
fc.save()
2012-10-11 08:47:15 +00:00
# Get repo groups
org, base_template = check_and_get_org_by_repo(repo_id,
request.user.username)
if org:
repo_shared_groups = get_org_groups_by_repo(org.org_id,
repo_id)
else:
repo_shared_groups = get_shared_groups_by_repo(repo_id)
for group in repo_shared_groups:
# save group message, and length should be less than 500
gm = GroupMessage(group_id=group.id,
from_email=request.user.username,
message=message[:500])
gm.save()
# send signal
grpmsg_added.send(sender=GroupMessage, group_id=group.id,
from_email=request.user.username)
# save attachment
ma = MessageAttachment(group_message=gm, repo_id=repo_id,
attach_type='file', path=path,
src='filecomment')
ma.save()
2012-10-11 08:47:15 +00:00
comments = FileComment.objects.filter(file_path_hash=file_path_hash,
repo_id=repo_id)
html = render_to_string("file_comments.html", {
'comments':comments})
return HttpResponse(json.dumps({'html': html}),
content_type=content_type)
2012-08-26 03:48:43 +00:00
def repo_file_get(raw_path):
err = ''
file_content = ''
encoding = ''
2012-08-22 09:08:52 +00:00
newline_mode = ''
try:
file_response = urllib2.urlopen(raw_path)
if long(file_response.headers['Content-Length']) > FILE_PREVIEW_MAX_SIZE:
2012-11-06 03:12:49 +00:00
err = _(u'File size surpasses 10M, can not be previewed online.')
2012-08-22 09:08:52 +00:00
return err, '', '', ''
else:
content = file_response.read()
except urllib2.HTTPError, e:
2012-11-06 03:12:49 +00:00
err = _(u'HTTPError: failed to open file online')
2012-08-22 09:08:52 +00:00
return err, '', '', ''
except urllib2.URLError as e:
2012-11-06 03:12:49 +00:00
err = _(u'URLError: failed to open file online')
2012-08-22 09:08:52 +00:00
return err, '', '', ''
else:
try:
2012-07-19 07:51:52 +00:00
u_content = content.decode('utf-8')
encoding = 'utf-8'
2012-08-22 09:08:52 +00:00
except UnicodeDecodeError:
# XXX: file in windows is encoded in gbk
2012-08-22 09:08:52 +00:00
try:
u_content = content.decode('gbk')
encoding = 'gbk'
except UnicodeDecodeError:
2012-11-05 06:35:37 +00:00
err = _(u'Unknown file encoding')
2012-08-22 09:08:52 +00:00
return err, '', '', ''
file_content = u_content
2012-08-22 09:08:52 +00:00
# detect newline mode for ace editor
if '\r\n' in u_content:
newline_mode = 'windows'
elif '\n' in u_content:
newline_mode = 'unix'
else:
newline_mode = 'windows'
return err, file_content, encoding, newline_mode
def pdf_full_view(request):
2012-07-23 06:58:54 +00:00
repo_id = request.GET.get('repo_id', '')
obj_id = request.GET.get('obj_id', '')
file_name = request.GET.get('file_name', '')
2012-09-14 11:35:19 +00:00
token = seafserv_rpc.web_get_access_token(repo_id, obj_id,
'view', request.user.username)
2012-07-23 06:58:54 +00:00
file_src = gen_file_get_url(token, file_name)
return render_to_response('pdf_full_view.html', {
'file_src': file_src,
}, context_instance=RequestContext(request))
2012-09-13 06:01:32 +00:00
def update_file_after_edit(request, repo_id):
content_type = 'application/json; charset=utf-8'
2012-11-05 06:35:37 +00:00
def error_json(error_msg=_(u'Internal Error')):
return HttpResponse(json.dumps({'error': error_msg}),
status=400,
content_type=content_type)
def ok_json():
return HttpResponse(json.dumps({'status': 'ok'}),
content_type=content_type)
if get_user_permission(request, repo_id) != 'rw':
return error_json('Permission denied')
content = request.POST.get('content')
encoding = request.POST.get('encoding')
path = request.GET.get('p')
if content is None or not path:
2012-11-05 06:35:37 +00:00
return error_json(_(u'Invalid arguments'))
head_id = request.GET.get('head', None)
2012-08-06 12:29:14 +00:00
if encoding not in ["gbk", "utf-8"]:
2012-11-05 06:35:37 +00:00
return error_json(_(u'Invalid arguments'))
content = content.encode(encoding)
# first dump the file content to a tmp file, then update the file
fd, tmpfile = tempfile.mkstemp()
def remove_tmp_file():
try:
2012-09-13 06:01:32 +00:00
os.remove(tmpfile)
except:
pass
try:
bytesWritten = os.write(fd, content)
except:
bytesWritten = -1
finally:
os.close(fd)
if bytesWritten != len(content):
remove_tmp_file()
return error_json()
parent_dir = os.path.dirname(path).encode('utf-8')
filename = os.path.basename(path).encode('utf-8')
try:
seafserv_threaded_rpc.put_file (repo_id, tmpfile, parent_dir,
filename, request.user.username, head_id)
remove_tmp_file()
return ok_json()
except SearpcError, e:
remove_tmp_file()
return error_json(str(e))
@login_required
2012-08-31 09:28:50 +00:00
@ctx_switch_required
2012-08-06 12:29:14 +00:00
def repo_file_edit(request, repo_id):
if request.method == 'POST':
return update_file_after_edit(request, repo_id)
2012-08-06 12:29:14 +00:00
if get_user_permission(request, repo_id) != 'rw':
2012-11-06 09:22:46 +00:00
return render_permission_error(request, _(u'Unable to edit file'))
2012-08-06 12:29:14 +00:00
path = request.GET.get('p', '/')
if path[-1] == '/':
path = path[:-1]
u_filename = os.path.basename(path)
filename = urllib2.quote(u_filename.encode('utf-8'))
repo = get_repo(repo_id)
if not repo:
raise Http404
head_id = repo.head_cmmt_id
2012-08-06 12:29:14 +00:00
try:
obj_id = seafserv_threaded_rpc.get_file_by_path(repo_id, path)
except:
obj_id = None
if not obj_id:
2012-11-06 09:22:46 +00:00
return render_error(request, _(u'File not exists'))
2012-08-06 12:29:14 +00:00
if access_to_repo(request, repo_id, ''):
2012-09-14 11:35:19 +00:00
token = seafserv_rpc.web_get_access_token(repo_id, obj_id,
'view', request.user.username)
2012-08-06 12:29:14 +00:00
else:
2012-11-06 09:22:46 +00:00
return render_permission_error(request, _(u'Unable to view file'))
2012-08-06 12:29:14 +00:00
# generate path and link
zipped = gen_path_link(path, repo.name)
filetype, fileext = valid_previewed_file(filename)
# get file content
raw_path = gen_file_get_url(token, filename)
2012-08-22 09:08:52 +00:00
err, file_content, encoding, newline_mode = repo_file_get(raw_path)
2012-08-06 12:29:14 +00:00
return render_to_response('repo_edit_file.html', {
'repo':repo,
'u_filename':u_filename,
'path':path,
'zipped':zipped,
'filetype':filetype,
2012-08-06 12:29:14 +00:00
'fileext':fileext,
'err':err,
'file_content':file_content,
'encoding': encoding,
'newline_mode': newline_mode,
'head_id': head_id,
2012-08-22 09:08:52 +00:00
}, context_instance=RequestContext(request))
2012-08-06 12:29:14 +00:00
2012-05-19 03:50:05 +00:00
def repo_access_file(request, repo_id, obj_id):
2012-07-12 08:14:21 +00:00
repo = get_repo(repo_id)
if not repo:
raise Http404
2012-07-12 08:14:21 +00:00
password_set = False
if repo.props.encrypted:
try:
ret = seafserv_rpc.is_passwd_set(repo_id, request.user.username)
if ret == 1:
password_set = True
except SearpcError, e:
2012-07-30 12:44:32 +00:00
return render_error(request, e.msg)
2012-07-12 08:14:21 +00:00
if repo.props.encrypted and not password_set:
return HttpResponseRedirect(reverse('repo', args=[repo_id]))
2012-07-12 08:14:21 +00:00
op = request.GET.get('op', 'view')
file_name = request.GET.get('file_name', '')
2012-07-12 08:14:21 +00:00
if op == 'del':
return repo_del_file(request, repo_id)
2012-07-12 08:14:21 +00:00
# If vistor's file shared token in url params matches the token in db,
# then we know the vistor is from file shared link.
share_token = request.GET.get('t', '')
path = '/' + file_name
if FileShare.objects.filter(token=share_token).filter(path=path) > 0:
from_shared_link = True
else:
from_shared_link = False
2012-07-30 02:25:46 +00:00
if access_to_repo(request, repo_id, '') or from_shared_link:
# Get a token to access file
2012-09-14 11:35:19 +00:00
token = seafserv_rpc.web_get_access_token(repo_id, obj_id,
op, request.user.username)
2012-07-30 02:25:46 +00:00
else:
2012-11-06 09:22:46 +00:00
return render_permission_error(request, _(u'Unable to access file'))
2012-04-20 05:34:52 +00:00
2012-07-21 07:06:43 +00:00
redirect_url = gen_file_get_url(token, file_name)
2012-07-12 08:14:21 +00:00
return HttpResponseRedirect(redirect_url)
2012-07-02 14:45:21 +00:00
2012-04-24 14:31:24 +00:00
@login_required
2012-04-26 02:57:36 +00:00
def repo_download(request):
repo_id = request.GET.get('repo_id', '')
repo = seafserv_threaded_rpc.get_repo(repo_id)
2012-04-25 11:23:13 +00:00
repo_name = repo.props.name
2012-05-16 14:44:24 +00:00
quote_repo_name = quote(repo_name.encode('utf-8'))
2012-04-25 11:23:13 +00:00
encrypted = repo.props.encrypted
if encrypted:
enc = '1'
else:
2012-04-25 06:34:42 +00:00
enc = ''
2012-05-16 13:31:28 +00:00
relay_id = ccnet_rpc.get_session_info().id
2012-05-12 13:29:51 +00:00
if not relay_id:
return render_to_response('error.html', {
2012-11-05 06:35:37 +00:00
"error_msg": _(u"Failed to download library, unable to find servre")
2012-05-12 13:29:51 +00:00
}, context_instance=RequestContext(request))
2012-04-25 11:56:53 +00:00
2012-07-17 12:53:38 +00:00
try:
token = seafserv_threaded_rpc.get_repo_token_nonnull \
(repo_id, request.user.username)
except Exception, e:
2012-07-30 12:44:32 +00:00
return render_error(request, str(e))
2012-07-17 12:53:38 +00:00
addr, port = get_ccnet_server_addr_port ()
if not (addr and port):
2012-11-05 06:35:37 +00:00
return render_error(request, _(u"Invalid server setting"))
2012-07-17 12:53:38 +00:00
ccnet_applet_root = get_ccnetapplet_root()
2012-07-17 12:53:38 +00:00
email = urllib2.quote(request.user.username)
2012-04-25 11:23:13 +00:00
2012-07-17 12:53:38 +00:00
url = ccnet_applet_root + "/repo/download/"
url += "?relay_id=%s&relay_addr=%s&relay_port=%s" % (relay_id, addr, port)
url += "&email=%s&token=%s" % (email, token)
url += "&repo_id=%s&repo_name=%s&encrypted=%s" % (repo_id, quote_repo_name, enc)
return HttpResponseRedirect(url)
@login_required
def file_move(request):
src_repo_id = request.POST.get('src_repo')
src_path = request.POST.get('src_path')
dst_repo_id = request.POST.get('dst_repo')
dst_path = request.POST.get('dst_path')
obj_name = request.POST.get('obj_name')
obj_type = request.POST.get('obj_type') # dir or file
op = request.POST.get('operation')
if not (src_repo_id and src_path and dst_repo_id \
and dst_path and obj_name and obj_type and op):
2012-07-30 12:44:32 +00:00
return render_error(request)
# do nothing when dst is the same as src
if src_repo_id == dst_repo_id and src_path == dst_path:
2012-09-02 12:23:57 +00:00
url = reverse('repo', args=[src_repo_id]) + ('?p=%s' % urllib2.quote(src_path.encode('utf-8')))
return HttpResponseRedirect(url)
# Error when moving/copying a dir to its subdir
if obj_type == 'dir':
src_dir = os.path.join(src_path, obj_name)
if dst_path.startswith(src_dir):
2012-11-05 06:35:37 +00:00
error_msg = _(u'Can not %(op)s directory %(src)s to its subdirectory %(des)s') \
% {'op': _(u"copy") if op == 'cp' else _(u"move"),
'src': src_dir,
'des': dst_path}
#return render_error(request, error_msg)
messages.add_message(request, messages.ERROR, error_msg)
url = reverse('repo', args=[src_repo_id]) + ('?p=%s' % urllib2.quote(src_path.encode('utf-8')))
return HttpResponseRedirect(url)
new_obj_name = check_filename_with_rename(dst_repo_id, dst_path, obj_name)
try:
2012-09-02 12:23:57 +00:00
msg_url = reverse('repo', args=[dst_repo_id]) + u'?p=' + urllib2.quote(dst_path.encode('utf-8'))
if op == 'cp':
seafserv_threaded_rpc.copy_file (src_repo_id, src_path, obj_name,
dst_repo_id, dst_path, new_obj_name,
request.user.username)
2012-11-05 06:35:37 +00:00
messages.success(request, _(u'Successfully copying %(name)s<a href="%(url)s">view</a>') % \
{"name":obj_name, "url":msg_url})
elif op == 'mv':
seafserv_threaded_rpc.move_file (src_repo_id, src_path, obj_name,
dst_repo_id, dst_path, new_obj_name,
request.user.username)
2012-11-05 06:35:37 +00:00
messages.success(request, _(u'Successfully moving %(name)s <a href="%(url)s">view</a>') % \
{"name":obj_name, "url":msg_url})
except Exception, e:
2012-07-30 12:44:32 +00:00
return render_error(request, str(e))
2012-09-02 12:23:57 +00:00
url = reverse('repo', args=[src_repo_id]) + ('?p=%s' % urllib2.quote(src_path.encode('utf-8')))
return HttpResponseRedirect(url)
def seafile_access_check(request):
repo_id = request.GET.get('repo_id', '')
2012-06-23 02:26:37 +00:00
applet_root = get_ccnetapplet_root()
return render_to_response(
'seafile_access_check.html', {
'repo_id': repo_id,
2012-06-23 02:26:37 +00:00
'applet_root': applet_root,
},
context_instance=RequestContext(request))
2012-09-03 04:03:06 +00:00
@login_required
2012-08-06 02:58:34 +00:00
@sys_staff_required
2012-06-20 11:39:21 +00:00
def sys_seafadmin(request):
2012-03-20 03:35:56 +00:00
# Make sure page request is an int. If not, deliver first page.
try:
current_page = int(request.GET.get('page', '1'))
per_page= int(request.GET.get('per_page', '25'))
except ValueError:
2012-04-09 08:48:14 +00:00
current_page = 1
2012-03-20 03:35:56 +00:00
per_page = 25
2012-05-26 12:52:53 +00:00
repos_all = seafserv_threaded_rpc.get_repo_list(per_page *
(current_page -1),
per_page + 1)
2012-06-20 11:39:21 +00:00
repos = repos_all[:per_page]
if len(repos_all) == per_page + 1:
page_next = True
else:
page_next = False
for repo in repos:
2012-09-04 13:05:20 +00:00
if is_org_repo(repo.id):
repo.owner = get_org_repo_owner(repo.id)
else:
try:
repo.owner = seafserv_threaded_rpc.get_repo_owner(repo.id)
except:
repo.owner = None
2012-06-20 11:39:21 +00:00
return render_to_response(
'sys_seafadmin.html', {
'repos': repos,
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'per_page': per_page,
'page_next': page_next,
},
context_instance=RequestContext(request))
@login_required
2012-08-06 02:58:34 +00:00
@sys_staff_required
2012-06-20 11:39:21 +00:00
def sys_useradmin(request):
2012-07-27 03:39:55 +00:00
# Make sure page request is an int. If not, deliver first page.
try:
current_page = int(request.GET.get('page', '1'))
per_page= int(request.GET.get('per_page', '25'))
except ValueError:
current_page = 1
per_page = 25
users_plus_one = get_emailusers(per_page * (current_page - 1), per_page + 1)
if len(users_plus_one) == per_page + 1:
page_next = True
else:
page_next = False
2012-06-20 11:39:21 +00:00
2012-07-27 03:39:55 +00:00
users = users_plus_one[:per_page]
2012-06-20 11:39:21 +00:00
for user in users:
if user.props.id == request.user.id:
user.is_self = True
return render_to_response(
2012-07-27 03:39:55 +00:00
'sys_useradmin.html', {
'users': users,
2012-07-27 03:39:55 +00:00
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'per_page': per_page,
'page_next': page_next,
},
context_instance=RequestContext(request))
2012-04-13 05:21:48 +00:00
@login_required
2012-08-06 02:58:34 +00:00
@sys_staff_required
2012-04-13 05:21:48 +00:00
def user_info(request, email):
if request.method == 'POST':
result = {}
content_type = 'application/json; charset=utf-8'
f = SetUserQuotaForm(request.POST)
if f.is_valid():
email = f.cleaned_data['email']
quota_mb = f.cleaned_data['quota']
quota = quota_mb * (1 << 20)
try:
seafserv_threaded_rpc.set_user_quota(email, quota)
except:
2012-11-05 06:35:37 +00:00
result['error'] = _(u'Failed to set quota: internal error')
return HttpResponse(json.dumps(result), content_type=content_type)
result['success'] = True
return HttpResponse(json.dumps(result), content_type=content_type)
else:
result['error'] = str(f.errors.values()[0])
return HttpResponse(json.dumps(result), content_type=content_type)
owned_repos = []
owned_repos = seafserv_threaded_rpc.list_owned_repos(email)
quota = seafserv_threaded_rpc.get_user_quota(email)
quota_usage = seafserv_threaded_rpc.get_user_quota_usage(email)
2012-04-15 15:33:22 +00:00
# Repos that are share to user
in_repos = seafserv_threaded_rpc.list_share_repos(email, 'to_email',
-1, -1)
2012-11-01 07:09:14 +00:00
# get nickname
if not Profile.objects.filter(user=email):
nickname = ''
else:
profile = Profile.objects.filter(user=email)[0]
nickname = profile.nickname
2012-04-13 05:21:48 +00:00
return render_to_response(
'userinfo.html', {
'owned_repos': owned_repos,
'quota': quota,
'quota_usage': quota_usage,
"in_repos": in_repos,
2012-11-01 07:09:14 +00:00
'email': email,
'nickname': nickname,
2012-08-06 02:58:34 +00:00
}, context_instance=RequestContext(request))
2012-03-17 06:05:21 +00:00
@login_required
2012-08-06 02:58:34 +00:00
@sys_staff_required
2012-03-17 06:05:21 +00:00
def user_remove(request, user_id):
"""Remove user, also remove group relationship."""
try:
user = User.objects.get(id=int(user_id))
user.delete()
except User.DoesNotExist:
pass
2012-07-26 09:32:51 +00:00
return HttpResponseRedirect(reverse('sys_useradmin'))
@login_required
2012-08-06 02:58:34 +00:00
@sys_staff_required
def activate_user(request, user_id):
try:
user = User.objects.get(id=int(user_id))
user.is_active = True
user.save()
except User.DoesNotExist:
pass
2012-06-05 11:38:28 +00:00
2012-08-06 08:30:51 +00:00
return HttpResponseRedirect(reverse('sys_useradmin'))
2012-08-16 08:58:28 +00:00
def send_user_reset_email(request, email, password):
"""
Send email when reset user password.
"""
use_https = request.is_secure()
domain = RequestSite(request).domain
t = loader.get_template('user_reset_email.html')
c = {
'email': email,
'password': password,
2012-11-06 09:22:46 +00:00
'site_name': settings.SITE_NAME,
2012-08-16 08:58:28 +00:00
}
try:
2012-11-05 06:35:37 +00:00
send_mail(_(u'Password Reset'), t.render(Context(c)),
2012-08-16 08:58:28 +00:00
None, [email], fail_silently=False)
2012-11-05 06:35:37 +00:00
messages.success(request, _(u'Successfully sending mail'))
2012-08-16 08:58:28 +00:00
except:
2012-11-05 06:35:37 +00:00
messages.error(request, _(u'Failed to send mail'))
2012-08-16 08:58:28 +00:00
2012-08-06 08:30:51 +00:00
@login_required
@sys_staff_required
def user_reset(request, user_id):
"""Reset password for user."""
try:
user = User.objects.get(id=int(user_id))
user.set_password(INIT_PASSWD)
2012-08-06 08:30:51 +00:00
user.save()
2012-11-05 06:35:37 +00:00
messages.success(request, _(u'Successfully resetting password'))
2012-08-16 08:58:28 +00:00
if hasattr(settings, 'EMAIL_HOST'):
send_user_reset_email(request, user.email, INIT_PASSWD)
2012-08-06 08:30:51 +00:00
except User.DoesNotExist:
2012-11-05 06:35:37 +00:00
msg = _(u'Failed to reset password: user does not exist')
messages.error(request, msg)
2012-08-06 08:30:51 +00:00
return HttpResponseRedirect(reverse('sys_useradmin'))
2012-08-16 08:58:28 +00:00
2012-06-20 11:39:21 +00:00
def send_user_add_mail(request, email, password):
2012-08-06 08:30:51 +00:00
"""Send email when add new user."""
2012-06-20 11:39:21 +00:00
use_https = request.is_secure()
domain = RequestSite(request).domain
t = loader.get_template('user_add_email.html')
c = {
'user': request.user.username,
'org': request.user.org,
'email': email,
'password': password,
'domain': domain,
'protocol': use_https and 'https' or 'http',
2012-11-06 09:22:46 +00:00
'site_name': settings.SITE_NAME,
2012-06-20 11:39:21 +00:00
}
try:
2012-11-05 06:35:37 +00:00
send_mail(_(u'Seafile Registration Information'), t.render(Context(c)),
2012-06-20 11:39:21 +00:00
None, [email], fail_silently=False)
2012-11-05 06:35:37 +00:00
messages.success(request, _(u'Successfully sending mail'))
2012-06-20 11:39:21 +00:00
except:
2012-11-05 06:35:37 +00:00
messages.error(request, _(u'Failed to send mail'))
2012-06-20 11:39:21 +00:00
@login_required
def user_add(request):
"""Add a user"""
2012-07-26 09:08:31 +00:00
if not request.user.is_staff and not request.user.org['is_staff']:
raise Http404
2012-06-20 11:39:21 +00:00
base_template = 'org_admin_base.html' if request.user.org else 'admin_base.html'
if request.method == 'POST':
form = AddUserForm(request.POST)
if form.is_valid():
email = form.cleaned_data['email']
password = form.cleaned_data['password1']
2012-08-24 03:23:49 +00:00
user = User.objects.create_user(email, password,
is_staff=False,
is_active=True)
2012-06-20 11:39:21 +00:00
if request.user.org:
2012-07-26 09:08:31 +00:00
org_id = request.user.org['org_id']
2012-07-26 09:32:51 +00:00
url_prefix = request.user.org['url_prefix']
2012-06-25 12:42:19 +00:00
ccnet_threaded_rpc.add_org_user(org_id, email, 0)
2012-06-20 11:39:21 +00:00
if hasattr(settings, 'EMAIL_HOST'):
send_user_add_mail(request, email, password)
2012-07-26 09:32:51 +00:00
return HttpResponseRedirect(reverse('org_useradmin',
args=[url_prefix]))
2012-06-20 11:39:21 +00:00
else:
if hasattr(settings, 'EMAIL_HOST'):
send_user_add_mail(request, email, password)
return HttpResponseRedirect(reverse('sys_useradmin', args=[]))
else:
form = AddUserForm()
return render_to_response("add_user_form.html", {
2012-06-20 11:39:21 +00:00
'form': form,
'base_template': base_template,
}, context_instance=RequestContext(request))
2012-05-15 06:29:37 +00:00
2012-08-06 02:58:34 +00:00
@login_required
@sys_staff_required
2012-06-20 11:39:21 +00:00
def sys_group_admin(request):
2012-05-26 12:52:53 +00:00
# Make sure page request is an int. If not, deliver first page.
try:
current_page = int(request.GET.get('page', '1'))
per_page= int(request.GET.get('per_page', '25'))
except ValueError:
current_page = 1
per_page = 25
2012-06-20 11:39:21 +00:00
2012-06-25 12:42:19 +00:00
groups_plus_one = ccnet_threaded_rpc.get_all_groups(per_page * (current_page -1),
2012-05-26 12:52:53 +00:00
per_page +1)
2012-06-20 11:39:21 +00:00
2012-05-26 12:52:53 +00:00
groups = groups_plus_one[:per_page]
if len(groups_plus_one) == per_page + 1:
page_next = True
else:
page_next = False
2012-06-20 11:39:21 +00:00
return render_to_response('sys_group_admin.html', {
'groups': groups,
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'per_page': per_page,
'page_next': page_next,
}, context_instance=RequestContext(request))
2012-08-06 02:58:34 +00:00
@login_required
@sys_staff_required
2012-06-20 11:39:21 +00:00
def sys_org_admin(request):
try:
2012-08-04 09:11:57 +00:00
orgs = ccnet_threaded_rpc.get_all_orgs(0, MAX_INT)
except:
orgs = []
2012-06-20 11:39:21 +00:00
return render_to_response('sys_org_admin.html', {
'orgs': orgs,
}, context_instance=RequestContext(request))
2012-08-06 02:58:34 +00:00
@login_required
@sys_staff_required
2012-06-20 11:39:21 +00:00
def org_remove(request, org_id):
try:
org_id_int = int(org_id)
except ValueError:
return HttpResponseRedirect(reverse('sys_org_admin'))
# Remove repos in that org
seafserv_threaded_rpc.remove_org_repo_by_org_id(org_id_int)
# TODO: Remove repos in org's groups
2012-06-25 12:42:19 +00:00
ccnet_threaded_rpc.remove_org(org_id_int)
2012-06-20 11:39:21 +00:00
return HttpResponseRedirect(reverse('sys_org_admin'))
@login_required
def file_upload_progress_page(request):
'''
As iframe in repo_upload_file.html, for solving problem in chrome.
'''
uuid = request.GET.get('uuid', '')
2012-08-14 12:36:19 +00:00
httpserver_root = get_httpserver_root()
return render_to_response('file_upload_progress_page.html', {
'uuid': uuid,
2012-08-14 12:36:19 +00:00
'httpserver_root': httpserver_root,
}, context_instance=RequestContext(request))
@login_required
def repo_new_dir(request):
result = {}
content_type = 'application/json; charset=utf-8'
2012-08-13 07:24:31 +00:00
form = RepoNewDirForm(request.POST)
if form.is_valid():
repo_id = form.cleaned_data["repo_id"]
parent_dir = form.cleaned_data["parent_dir"]
new_dir_name = form.cleaned_data["new_dir_name"]
user = request.user.username
else:
result['error'] = str(form.errors.values()[0])
return HttpResponse(json.dumps(result), content_type=content_type)
if get_user_permission(request, repo_id) != 'rw':
result['error'] = 'Permission denied'
return HttpResponse(json.dumps(result), content_type=content_type)
new_dir_name = check_filename_with_rename(repo_id, parent_dir, new_dir_name)
try:
2012-07-11 09:47:08 +00:00
seafserv_threaded_rpc.post_dir(repo_id, parent_dir, new_dir_name, user)
except Exception, e:
result['error'] = str(e)
return HttpResponse(json.dumps(result), content_type=content_type)
url = reverse('repo', args=[repo_id]) + \
('?p=%s' % urllib2.quote(parent_dir.encode('utf-8')))
return HttpResponse(json.dumps({'success': True}),
content_type=content_type)
2012-08-11 06:07:12 +00:00
@login_required
def repo_new_file(request):
result = {}
content_type = 'application/json; charset=utf-8'
2012-08-11 06:07:12 +00:00
2012-08-13 07:24:31 +00:00
form = RepoNewFileForm(request.POST)
if form.is_valid():
repo_id = form.cleaned_data["repo_id"]
parent_dir = form.cleaned_data["parent_dir"]
new_file_name = form.cleaned_data["new_file_name"]
user = request.user.username
else:
result['error'] = str(form.errors.values()[0])
return HttpResponse(json.dumps(result), content_type=content_type)
if get_user_permission(request, repo_id) != 'rw':
result['error'] = 'Permission denied'
return HttpResponse(json.dumps(result), content_type=content_type)
2012-08-13 07:24:31 +00:00
new_file_name = check_filename_with_rename(repo_id, parent_dir,
new_file_name)
2012-08-11 06:07:12 +00:00
try:
seafserv_threaded_rpc.post_empty_file(repo_id, parent_dir,
new_file_name, user)
2012-08-11 06:07:12 +00:00
except Exception, e:
result['error'] = str(e)
return HttpResponse(json.dumps(result), content_type=content_type)
url = reverse('repo', args=[repo_id]) + \
('?p=%s' % urllib2.quote(parent_dir.encode('utf-8')))
return HttpResponse(json.dumps({'success': True}),
content_type=content_type)
@login_required
def repo_rename_file(request):
result = {}
content_type = 'application/json; charset=utf-8'
form = RepoRenameFileForm(request.POST)
if form.is_valid():
repo_id = form.cleaned_data["repo_id"]
parent_dir = form.cleaned_data["parent_dir"]
oldname = form.cleaned_data["oldname"]
newname = form.cleaned_data["newname"]
user = request.user.username
else:
result['error'] = str(form.errors.values()[0])
return HttpResponse(json.dumps(result), content_type=content_type)
if get_user_permission(request, repo_id) != 'rw':
result['error'] = 'Permission denied'
return HttpResponse(json.dumps(result), content_type=content_type)
2012-09-02 12:10:49 +00:00
if newname == oldname:
return HttpResponse(json.dumps({'success': True}),
content_type=content_type)
2012-09-02 12:10:49 +00:00
newname = check_filename_with_rename(repo_id, parent_dir, newname)
try:
seafserv_threaded_rpc.rename_file (repo_id, parent_dir,
oldname, newname, user)
2012-11-05 06:35:37 +00:00
messages.success(request, _(u'Successfully rename %(old)s to %(new)s') % \
{"old":oldname, "new":newname})
except Exception, e:
result['error'] = str(e)
return HttpResponse(json.dumps(result), content_type=content_type)
url = reverse('repo', args=[repo_id]) + \
('?p=%s' % urllib2.quote(parent_dir.encode('utf-8')))
return HttpResponse(json.dumps({'success': True}),
content_type=content_type)
@login_required
def validate_filename(request):
repo_id = request.GET.get('repo_id')
filename = request.GET.get('filename')
if not (repo_id and filename):
2012-07-30 12:44:32 +00:00
return render_error(request)
result = {'ret':'yes'}
try:
2012-09-13 06:01:32 +00:00
ret = is_valid_filename(filename)
except SearpcError:
result['ret'] = 'error'
else:
result['ret'] = 'yes' if ret == 1 else 'no'
content_type = 'application/json; charset=utf-8'
return HttpResponse(json.dumps(result), content_type=content_type)
2012-07-09 12:56:21 +00:00
@login_required
def repo_create(request):
2012-07-16 08:36:46 +00:00
'''
Handle ajax post.
2012-07-09 12:56:21 +00:00
2012-07-16 08:36:46 +00:00
'''
2012-07-30 02:25:46 +00:00
if not request.is_ajax() or request.method != 'POST':
return Http404
2012-07-09 12:56:21 +00:00
2012-07-30 02:25:46 +00:00
result = {}
content_type = 'application/json; charset=utf-8'
form = RepoCreateForm(request.POST)
if form.is_valid():
repo_name = form.cleaned_data['repo_name']
repo_desc = form.cleaned_data['repo_desc']
passwd = form.cleaned_data['passwd']
user = request.user.username
2012-07-16 08:36:46 +00:00
try:
2012-07-30 02:25:46 +00:00
repo_id = seafserv_threaded_rpc.create_repo(repo_name, repo_desc,
user, passwd)
2012-07-16 08:36:46 +00:00
except:
2012-07-30 02:25:46 +00:00
repo_id = None
if not repo_id:
2012-11-05 06:35:37 +00:00
result['error'] = _(u"Failed to create library")
2012-07-16 08:36:46 +00:00
else:
2012-07-30 02:25:46 +00:00
result['success'] = True
2012-09-24 12:30:17 +00:00
repo_created.send(sender=None,
org_id=-1,
2012-09-24 12:30:17 +00:00
creator=user,
repo_id=repo_id,
repo_name=repo_name)
2012-07-16 08:36:46 +00:00
return HttpResponse(json.dumps(result), content_type=content_type)
2012-07-30 02:25:46 +00:00
else:
return HttpResponseBadRequest(json.dumps(form.errors),
content_type=content_type)
def render_file_revisions (request, repo_id):
"""List all history versions of a file."""
2012-08-11 11:45:58 +00:00
path = request.GET.get('p', '/')
if path[-1] == '/':
path = path[:-1]
u_filename = os.path.basename(path)
filename = urllib2.quote(u_filename.encode('utf-8'))
if not path:
2012-07-30 12:44:32 +00:00
return render_error(request)
repo = get_repo(repo_id)
if not repo:
2012-11-05 06:35:37 +00:00
error_msg = _(u"Library not exists")
2012-07-30 12:44:32 +00:00
return render_error(request, error_msg)
try:
commits = seafserv_threaded_rpc.list_file_revisions(repo_id, path, 0)
except SearpcError, e:
2012-07-30 12:44:32 +00:00
return render_error(request, e.msg)
if not commits:
2012-07-30 12:44:32 +00:00
return render_error(request)
# Check whether use is repo owner
if validate_owner(request, repo_id):
is_owner = True
else:
is_owner = False
try:
for commit in commits:
2012-08-11 11:45:58 +00:00
file_id, file_size = get_file_revision_id_size (commit.id, path)
2012-08-09 09:08:50 +00:00
if not file_id or file_size is None:
2012-10-31 08:36:37 +00:00
# do not use 'not file_size', since it's ok to have file_size = 0
2012-07-30 12:44:32 +00:00
return render_error(request)
commit.revision_file_size = file_size
commit.file_id = file_id
except Exception, e:
2012-07-30 12:44:32 +00:00
return render_error(request, str(e))
2012-08-11 11:45:58 +00:00
zipped = gen_path_link(path, repo.name)
return render_to_response('file_revisions.html', {
'repo': repo,
2012-08-11 11:45:58 +00:00
'path': path,
'u_filename': u_filename,
'zipped': zipped,
'commits': commits,
'is_owner': is_owner,
}, context_instance=RequestContext(request))
2012-08-14 10:40:36 +00:00
@login_required
def repo_revert_file (request, repo_id):
commit_id = request.GET.get('commit')
path = request.GET.get('p')
from_page = request.GET.get('from')
2012-08-14 10:40:36 +00:00
if not (commit_id and path and from_page):
2012-11-05 06:35:37 +00:00
return render_error(request, _(u"Invalid arguments"))
2012-08-14 10:40:36 +00:00
try:
ret = seafserv_threaded_rpc.revert_file (repo_id, commit_id,
path.encode('utf-8'), request.user.username)
except Exception, e:
return render_error(request, str(e))
else:
if from_page == 'repo_history':
# When revert file from repo history, we redirect to repo history
url = reverse('repo', args=[repo_id]) + u'?commit_id=%s&history=y' % commit_id
2012-10-09 06:31:40 +00:00
elif from_page == 'recycle':
# When revert from recycle page, redirect to recycle page.
url = reverse('repo_recycle_view', args=[repo_id])
else:
# When revert file from file history, we redirect to parent dir of this file
parent_dir = os.path.dirname(path)
url = reverse('repo', args=[repo_id]) + ('?p=%s' % urllib2.quote(parent_dir.encode('utf-8')))
2012-08-14 10:40:36 +00:00
if ret == 1:
2012-10-11 06:44:14 +00:00
root_url = reverse('repo', args=[repo_id]) + u'?p=/'
2012-11-05 06:35:37 +00:00
msg = _(u'Successfully revert %(path)s to <a href="%(root)s">root directory.</a>') % {"path":path.lstrip('/'), "root":root_url}
2012-08-14 10:40:36 +00:00
messages.add_message(request, messages.INFO, msg)
else:
2012-10-11 06:44:14 +00:00
file_view_url = reverse('repo_view_file', args=[repo_id]) + u'?p=' + urllib2.quote(path.encode('utf-8'))
2012-11-05 06:35:37 +00:00
msg = _(u'Successfully revert <a href="%(url)s">%(path)s</a>') % {"url":file_view_url, "path":path.lstrip('/')}
2012-08-14 10:40:36 +00:00
messages.add_message(request, messages.INFO, msg)
return HttpResponseRedirect(url)
2012-10-11 06:44:14 +00:00
@login_required
def repo_revert_dir (request, repo_id):
commit_id = request.GET.get('commit')
path = request.GET.get('p')
if not (commit_id and path):
2012-11-05 06:35:37 +00:00
return render_error(request, _(u"Invalid arguments"))
2012-10-11 06:44:14 +00:00
try:
ret = seafserv_threaded_rpc.revert_dir (repo_id, commit_id,
path.encode('utf-8'), request.user.username)
except Exception, e:
return render_error(request, str(e))
else:
url = reverse('repo_recycle_view', args=[repo_id])
if ret == 1:
root_url = reverse('repo', args=[repo_id]) + u'?p=/'
2012-11-05 06:35:37 +00:00
msg = _(u'Successfully revert %(path)s to <a href="%(url)s">root directory.</a>') % {"path":path.lstrip('/'), "url":root_url}
2012-10-11 06:44:14 +00:00
messages.add_message(request, messages.INFO, msg)
else:
dir_view_url = reverse('repo', args=[repo_id]) + u'?p=' + urllib2.quote(path.encode('utf-8'))
2012-11-05 06:35:37 +00:00
msg = _(u'Successfully revert <a href="%(url)s">%(path)s</a>') % {"url":dir_view_url, "path":path.lstrip('/')}
2012-10-11 06:44:14 +00:00
messages.add_message(request, messages.INFO, msg)
return HttpResponseRedirect(url)
2012-08-31 09:28:50 +00:00
@login_required
@ctx_switch_required
def file_revisions(request, repo_id):
if request.method != 'GET':
2012-07-30 12:44:32 +00:00
return render_error(request)
op = request.GET.get('op')
if not op:
return render_file_revisions(request, repo_id)
elif op != 'download':
2012-07-30 12:44:32 +00:00
return render_error(request)
commit_id = request.GET.get('commit')
path = request.GET.get('p')
if not (commit_id and path):
2012-07-30 12:44:32 +00:00
return render_error(request)
2012-08-14 10:40:36 +00:00
if op == 'download':
def handle_download():
parent_dir = os.path.dirname(path)
file_name = os.path.basename(path)
seafdir = seafserv_threaded_rpc.list_dir_by_path (commit_id, \
parent_dir.encode('utf-8'))
if not seafdir:
2012-07-30 12:44:32 +00:00
return render_error(request)
# for ... else ...
for dirent in seafdir:
if dirent.obj_name == file_name:
break
else:
2012-07-30 12:44:32 +00:00
return render_error(request)
url = reverse('repo_access_file', args=[repo_id, dirent.obj_id])
2012-09-02 12:23:57 +00:00
url += '?file_name=%s&op=download' % urllib2.quote(file_name.encode('utf-8'))
return HttpResponseRedirect(url)
try:
return handle_download()
except Exception, e:
2012-07-30 12:44:32 +00:00
return render_error(request, str(e))
def view_shared_file(request, token):
"""
Preview file via shared link.
"""
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 = fileshare.path
http_server_root = get_httpserver_root()
if path[-1] == '/':
path = path[:-1]
filename = os.path.basename(path)
quote_filename = urllib2.quote(filename.encode('utf-8'))
try:
2012-07-14 14:41:32 +00:00
obj_id = seafserv_threaded_rpc.get_file_by_path(repo_id, path)
except:
obj_id = None
if not obj_id:
2012-11-06 03:12:49 +00:00
return render_error(request, _(u'File not exists'))
repo = get_repo(repo_id)
if not repo:
raise Http404
2012-09-14 11:35:19 +00:00
access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id,
'view', '')
filetype, fileext = valid_previewed_file(filename)
# Raw path
2012-07-21 07:06:43 +00:00
raw_path = gen_file_get_url(access_token, quote_filename)
# get file content
err = ''
file_content = ''
2012-09-21 09:16:07 +00:00
swf_exists = False
pdf_use_flash = False
if filetype == 'Text' or filetype == 'Markdown':
2012-08-22 09:08:52 +00:00
err, file_content, encoding, newline_mode = repo_file_get(raw_path)
2012-09-21 09:16:07 +00:00
elif filetype == 'Document':
err, swf_exists = flash_prepare(raw_path, obj_id, fileext)
elif filetype == 'PDF':
pdf_use_flash = use_flash_for_pdf(request)
if pdf_use_flash:
err, swf_exists = flash_prepare(raw_path, obj_id, 'pdf')
2012-07-21 07:06:43 +00:00
# Increase file shared link view_cnt, this operation should be atomic
fileshare = FileShare.objects.get(token=token)
fileshare.view_cnt = F('view_cnt') + 1
fileshare.save()
return render_to_response('view_shared_file.html', {
'repo': repo,
'obj_id': obj_id,
'path': path,
'file_name': filename,
2012-07-12 08:14:21 +00:00
'shared_token': token,
'access_token': access_token,
'filetype': filetype,
'fileext': fileext,
'raw_path': raw_path,
'username': username,
'err': err,
'file_content': file_content,
2012-09-21 09:16:07 +00:00
'swf_exists': swf_exists,
'pdf_use_flash': pdf_use_flash,
'DOCUMENT_CONVERTOR_ROOT': DOCUMENT_CONVERTOR_ROOT,
}, context_instance=RequestContext(request))
2012-07-23 14:44:09 +00:00
2012-09-21 09:16:07 +00:00
def flash_prepare(raw_path, obj_id, doctype):
2012-09-13 06:01:32 +00:00
curl = DOCUMENT_CONVERTOR_ROOT + 'convert'
data = {'doctype': doctype,
'file_id': obj_id,
2012-07-23 14:44:09 +00:00
'url': raw_path}
try:
f = urllib2.urlopen(url=curl, data=urllib.urlencode(data))
except urllib2.URLError, e:
2012-11-05 06:35:37 +00:00
return _(u'Internal error'), False
2012-07-23 14:44:09 +00:00
else:
ret = f.read()
ret_dict = json.loads(ret)
if ret_dict.has_key('error'):
2012-09-13 06:01:32 +00:00
return ret_dict['error'], False
2012-07-23 14:44:09 +00:00
else:
2012-09-13 06:01:32 +00:00
return None, ret_dict['exists']
2012-09-21 09:16:07 +00:00
def use_flash_for_pdf(request):
"""Decide whether to use flash to view pdf file, according to the current
browser type and version.
"""
ua = request.META.get('HTTP_USER_AGENT', '')
if 'MSIE' in ua:
return True
else:
return False
2012-10-10 12:04:09 +00:00
def demo(request):
"""
Login as demo account.
"""
2012-10-10 12:11:55 +00:00
redirect_to = settings.SITE_ROOT
2012-10-10 12:04:09 +00:00
auth_login(request, authenticate(username='demo@seafile.com',
password='demo'))
return HttpResponseRedirect(redirect_to)
2012-10-11 06:34:08 +00:00
@login_required
def pubinfo(request):
"""
Show public information.
"""
if request.cloud_mode:
# Users are not allowed to see public information when in cloud mode.
raise Http404
else:
groups = get_personal_groups(-1, -1)
users = get_emailusers(-1, -1)
return render_to_response('pubinfo.html', {
'groups': groups,
'users': users,
}, context_instance=RequestContext(request))
def repo_set_password(request):
ret = {}
content_type = 'application/json; charset=utf-8'
form = RepoPassowrdForm(request.POST)
if form.is_valid():
ret['success'] = True
else:
ret['success'] = False
ret['error'] = str(form.errors.values()[0])
return HttpResponse(json.dumps(ret),
content_type=content_type)
2012-10-16 06:47:36 +00:00
def get_file_content_by_commit_and_path(request, repo_id, commit_id, path):
try:
obj_id = seafserv_threaded_rpc.get_file_id_by_commit_and_path( \
commit_id, path)
except:
return None, 'bad path'
if not obj_id or obj_id == EMPTY_SHA1:
return '', None
else:
permission = get_user_permission(request, repo_id)
if permission:
# Get a token to visit file
token = seafserv_rpc.web_get_access_token(repo_id,
obj_id,
'view',
request.user.username)
else:
return None, 'permission denied'
filename = os.path.basename(path)
raw_path = gen_file_get_url(token, urllib2.quote(filename))
try:
err, file_content, encoding, newline_mode = repo_file_get(raw_path)
except Exception, e:
return None, 'error when read file from httpserver: %s' % e
return file_content, err
@login_required
def text_diff(request, repo_id):
commit_id = request.GET.get('commit', '')
path = request.GET.get('p', '')
2012-10-24 07:40:25 +00:00
u_filename = os.path.basename(path)
2012-10-16 06:47:36 +00:00
if not (commit_id and path):
return render_error(request, 'bad params')
repo = get_repo(repo_id)
if not repo:
return render_error(request, 'bad repo')
current_commit = seafserv_threaded_rpc.get_commit(commit_id)
if not current_commit:
return render_error(request, 'bad commit id')
prev_commit = seafserv_threaded_rpc.get_commit(current_commit.parent_id)
if not prev_commit:
return render_error('bad commit id')
path = path.encode('utf-8')
current_content, err = get_file_content_by_commit_and_path(request, \
repo_id, current_commit.id, path)
if err:
return render_error(request, err)
prev_content, err = get_file_content_by_commit_and_path(request, \
repo_id, prev_commit.id, path)
if err:
return render_error(request, err)
is_new_file = False
diff_result_table = ''
if prev_content == '' and current_content == '':
is_new_file = True
else:
diff = HtmlDiff()
diff_result_table = diff.make_table(prev_content.splitlines(),
current_content.splitlines())
zipped = gen_path_link(path, repo.name)
return render_to_response('text_diff.html', {
2012-10-24 07:40:25 +00:00
'u_filename':u_filename,
2012-10-16 06:47:36 +00:00
'repo': repo,
'path': path,
'zipped': zipped,
'current_commit': current_commit,
'prev_commit': prev_commit,
'diff_result_table': diff_result_table,
'is_new_file': is_new_file,
}, context_instance=RequestContext(request))
2012-10-26 11:15:52 +00:00
def i18n(request):
"""
Set client language preference, lasts for one month
"""
from django.conf import settings
next = request.META.get('HTTP_REFERER', None)
if not next:
next = settings.SITE_ROOT
lang = request.GET.get('lang', 'en')
res = HttpResponseRedirect(next)
res.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang, max_age=30*24*60*60)
return res
2012-10-26 11:50:36 +00:00
@login_required
def repo_star_file(request, repo_id):
path = request.POST.get('path')
state = request.POST.get('state');
content_type = 'application/json; charset=utf-8'
if not (path and state):
2012-11-05 06:35:37 +00:00
return HttpResponse(json.dumps({'success':False, 'err_msg':_(u'Invalid arguments')}),
2012-10-26 11:50:36 +00:00
content_type=content_type)
org_id = int(request.POST.get('org_id'))
path = urllib2.unquote(path.encode('utf-8'))
is_dir = False
if state == 'unstarred':
star_file(request.user.username, repo_id, path, is_dir, org_id=org_id)
else:
unstar_file(request.user.username, repo_id, path)
return HttpResponse(json.dumps({'success':True}), content_type=content_type)