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 shared_by = fileshare.username repo_id = fileshare.repo_id repo = get_repo(repo_id) if not repo: raise Http404 path = fileshare.path.rstrip('/') # Normalize file path obj_id = seafile_api.get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u'File does not exist')) file_size = seafile_api.get_file_size(obj_id) filename = os.path.basename(path) filetype, fileext = get_file_type_and_ext(filename) access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id, 'view', '') raw_path = gen_file_get_url(access_token, filename) inner_path = gen_inner_file_get_url(access_token, filename) # get file content ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype} fsize = get_file_size(obj_id) exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype) if exceeds_limit: err = err_msg else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, inner_path, ret_dict) elif filetype == DOCUMENT: handle_document(inner_path, obj_id, fileext, ret_dict) elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) # Increase file shared link view_cnt, this operation should be atomic fileshare.view_cnt = F('view_cnt') + 1 fileshare.save() # send statistic messages if ret_dict['filetype'] != 'Unknown': try: obj_size = seafserv_threaded_rpc.get_file_size(obj_id) send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \ (repo.id, shared_by, obj_id, obj_size)) except SearpcError, e: logger.error('Error when sending file-view message: %s' % str(e))
def get_file_content_by_commit_and_path(request, repo_id, commit_id, path, file_enc): 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 = repo_file_get(raw_path, file_enc) except Exception, e: return None, 'error when read file from httpserver: %s' % e return file_content, err
def get_onlyoffice_dict(username, repo_id, file_path, file_id='', can_edit=False, can_download=True): repo = seafile_api.get_repo(repo_id) if repo.is_virtual: origin_repo_id = repo.origin_repo_id origin_file_path = posixpath.join(repo.origin_path, file_path.strip('/')) # for view history/trash/snapshot file if not file_id: file_id = seafile_api.get_file_id_by_path(origin_repo_id, origin_file_path) else: origin_repo_id = repo_id origin_file_path = file_path if not file_id: file_id = seafile_api.get_file_id_by_path(repo_id, file_path) dl_token = seafile_api.get_fileserver_access_token(repo_id, file_id, 'download', username, use_onetime=True) if not dl_token: return None filetype, fileext = get_file_type_and_ext(file_path) if fileext in ('xls', 'xlsx', 'ods', 'fods', 'csv'): document_type = 'spreadsheet' elif fileext in ('pptx', 'ppt', 'odp', 'fodp', 'ppsx', 'pps'): document_type = 'presentation' else: document_type = 'text' doc_info = json.dumps({'repo_id': repo_id, 'file_path': file_path, 'username': username}) doc_key = hashlib.md5(force_bytes(origin_repo_id + origin_file_path + file_id)).hexdigest()[:20] cache.set("ONLYOFFICE_%s" % doc_key, doc_info, None) file_name = os.path.basename(file_path.rstrip('/')) doc_url = gen_file_get_url(dl_token, file_name) base_url = get_site_scheme_and_netloc() onlyoffice_editor_callback_url = reverse('onlyoffice_editor_callback') calllback_url = urlparse.urljoin(base_url, onlyoffice_editor_callback_url) return_dict = { 'repo_id': repo_id, 'path': file_path, 'ONLYOFFICE_APIJS_URL': ONLYOFFICE_APIJS_URL, 'file_type': fileext, 'doc_key': doc_key, 'doc_title': file_name, 'doc_url': doc_url, 'document_type': document_type, 'callback_url': calllback_url, 'can_edit': can_edit, 'can_download': can_download, 'username': username, 'enable_watermark': ENABLE_WATERMARK and not can_edit, } return return_dict
def get_group_msgs(groupid, page, username): # Show 15 group messages per page. paginator = Paginator(GroupMessage.objects.filter(group_id=groupid).order_by("-timestamp"), 15) # If page request (9999) is out of range, return None try: group_msgs = paginator.page(page) except (EmptyPage, InvalidPage): return None # Force evaluate queryset to fix some database error for mysql. group_msgs.object_list = list(group_msgs.object_list) attachments = MessageAttachment.objects.filter(group_message__in=group_msgs.object_list) msg_replies = MessageReply.objects.filter(reply_to__in=group_msgs.object_list) reply_to_list = [r.reply_to_id for r in msg_replies] for msg in group_msgs.object_list: msg.reply_cnt = reply_to_list.count(msg.id) msg.replies = [] for r in msg_replies: if msg.id == r.reply_to_id: msg.replies.append(r) msg.replies = msg.replies[-3:] for att in attachments: if att.group_message_id != msg.id: continue # Attachment name is file name or directory name. # If is top directory, use repo name instead. path = att.path if path == "/": repo = seafile_api.get_repo(att.repo_id) if not repo: # TODO: what should we do here, tell user the repo # is no longer exists? continue att.name = repo.name else: path = path.rstrip("/") # cut out last '/' if possible att.name = os.path.basename(path) # Load to discuss page if attachment is a image and from recommend. if att.attach_type == "file" and att.src == "recommend": att.filetype, att.fileext = get_file_type_and_ext(att.name) if att.filetype == IMAGE: att.obj_id = seafile_api.get_file_id_by_path(att.repo_id, path) if not att.obj_id: att.err = "File does not exist" else: att.token = seafile_api.get_fileserver_access_token(att.repo_id, att.obj_id, "view", username) att.img_url = gen_file_get_url(att.token, att.name) msg.attachment = att return group_msgs
def get_file_url(repo_id, path, filename): obj_id = get_file_id_by_path(repo_id, path) if not obj_id: raise WikiPageMissing access_token = seafserv_rpc.web_get_access_token(repo_id, obj_id, 'view', '') url = gen_file_get_url(access_token, filename) return url, obj_id
def view_file_via_shared_dir(request, token): assert token is not None # Checked by URLconf try: fileshare = FileShare.objects.get(token=token) except FileShare.DoesNotExist: raise Http404 shared_by = fileshare.username repo_id = fileshare.repo_id repo = get_repo(repo_id) if not repo: raise Http404 path = request.GET.get('p', '').rstrip('/') if not path: raise Http404 if not path.startswith(fileshare.path): # Can not view upper dir of shared dir raise Http404 zipped = gen_path_link(path, '') obj_id = seafile_api.get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u'File does not exist')) file_size = seafile_api.get_file_size(obj_id) filename = os.path.basename(path) filetype, fileext = get_file_type_and_ext(filename) access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id, 'view', '') raw_path = gen_file_get_url(access_token, filename) inner_path = gen_inner_file_get_url(access_token, filename) # get file content ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype} fsize = get_file_size(obj_id) exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype) if exceeds_limit: err = err_msg else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, inner_path, ret_dict) elif filetype == DOCUMENT: handle_document(inner_path, obj_id, fileext, ret_dict) elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) # send statistic messages try: obj_size = seafserv_threaded_rpc.get_file_size(obj_id) send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \ (repo.id, shared_by, obj_id, obj_size)) except SearpcError, e: logger.error('Error when sending file-view message: %s' % str(e))
def get_file_view_path_and_perm(request, repo_id, obj_id, filename): """ Return raw path of a file and the permission to view file. """ username = request.user.username # check permission perm = get_user_permission(request, repo_id) if perm: # Get a token to visit file token = web_get_access_token(repo_id, obj_id, 'view', username) return (gen_file_get_url(token, filename), perm) else: return ('', perm)
def get_repo_file(request, repo_id, file_id, file_name, op): if op == 'download': token = seafserv_rpc.web_get_access_token(repo_id, file_id, op, request.user.username) redirect_url = gen_file_get_url(token, file_name) response = HttpResponse(json.dumps(redirect_url), status=200, content_type=json_content_type) response["oid"] = file_id return response if op == 'sharelink': path = request.GET.get('p', None) assert path, 'path must be passed in the url' return get_shared_link(request, repo_id, path)
def get(self, request, repo_id): """ get info of a single file/folder in a library """ repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not can_view_sys_admin_repo(repo): error_msg = 'Feature disabled.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) path = request.GET.get('path', None) if not path: error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if path[0] != '/': path = '/' + path try: dirent = seafile_api.get_dirent_by_path(repo_id, path) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not dirent: error_msg = 'file/folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if stat.S_ISDIR(dirent.mode): is_file = False else: is_file = True username = request.user.username if is_file and request.GET.get('dl', '0') == '1': token = seafile_api.get_fileserver_access_token(repo_id, dirent.obj_id, 'download', username, use_onetime=True) dl_url = gen_file_get_url(token, dirent.obj_name) send_file_access_msg(request, repo, path, 'web') return Response({'download_url': dl_url}) dirent_info = get_dirent_info(dirent) return Response(dirent_info)
def repl(matchobj): if matchobj.group(2): # return origin string in backquotes return matchobj.group(2) page_alias = page_name = matchobj.group(1).strip() if len(page_name.split("|")) > 1: page_alias = page_name.split("|")[0] page_name = page_name.split("|")[1] filetype, fileext = get_file_type_and_ext(page_name) if fileext == "": # convert page_name that extension is missing to a markdown page try: dirent = get_wiki_dirent(repo_id, page_name) a_tag = "<a href='%s'>%s</a>" return a_tag % (smart_str(url_prefix + normalize_page_name(page_name) + "/"), page_alias) except (WikiDoesNotExist, WikiPageMissing): a_tag = """<a class="wiki-page-missing" href='%s'>%s</a>""" return a_tag % (smart_str(url_prefix + page_name.replace("/", "-") + "/"), page_alias) elif filetype == IMAGE: # load image to wiki page path = "/" + page_name filename = os.path.basename(path) obj_id = seaserv.get_file_id_by_path(repo_id, path) if not obj_id: # Replace '/' in page_name to '-', since wiki name can not # contain '/'. return """<a class="wiki-page-missing" href='%s'>%s</a>""" % ( url_prefix + "/" + page_name.replace("/", "-"), page_name, ) token = seaserv.web_get_access_token(repo_id, obj_id, "view", username) ret = '<img class="wiki-image" src="%s" alt="%s" />' % (gen_file_get_url(token, filename), filename) return smart_str(ret) else: from seahub.base.templatetags.seahub_tags import file_icon_filter from django.conf import settings # convert other types of filelinks to clickable links path = "/" + page_name icon = file_icon_filter(page_name) s = reverse("repo_view_file", args=[repo_id]) + "?p=" + urlquote(path) a_tag = ( """<img src="%simg/file/%s" alt="%s" class="vam" /> <a href='%s' target='_blank' class="vam">%s</a>""" ) ret = a_tag % (settings.MEDIA_URL, icon, icon, smart_str(s), page_name) return smart_str(ret)
def get(self, request, repo_id): """ get info of a single file/folder in a library """ repo = seafile_api.get_repo(repo_id) path = request.GET.get('path', None) if not path: error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) path = normalize_file_path(path) try: dirent = seafile_api.get_dirent_by_path(repo_id, path) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not dirent: error_msg = 'File or folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if stat.S_ISDIR(dirent.mode): is_file = False else: is_file = True username = request.user.username if is_file and request.GET.get('dl', '0') == '1': token = seafile_api.get_fileserver_access_token( repo_id, dirent.obj_id, 'download', username, use_onetime=settings.FILESERVER_TOKEN_ONCE_ONLY) if not token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) dl_url = gen_file_get_url(token, dirent.obj_name) send_file_access_msg(request, repo, path, 'web') return Response({'download_url': dl_url}) dirent_info = get_dirent_info(dirent) return Response(dirent_info)
def repl(matchobj): if matchobj.group(2): # return origin string in backquotes return matchobj.group(2) page_alias = page_name = matchobj.group(1).strip() if len(page_name.split('|')) > 1: page_alias = page_name.split('|')[0] page_name = page_name.split('|')[1] filetype, fileext = get_file_type_and_ext(page_name) if fileext == '': # convert page_name that extension is missing to a markdown page try: dirent = get_wiki_dirent(repo_id, page_name) a_tag = '''<a href="%s">%s</a>''' return a_tag % (smart_str(url_prefix + normalize_page_name(page_name) + '/'), page_alias) except (WikiDoesNotExist, WikiPageMissing): a_tag = '''<a href="%s" class="wiki-page-missing">%s</a>''' return a_tag % (smart_str(url_prefix + normalize_page_name(page_name) + '/'), page_alias) elif filetype == IMAGE: # load image to wiki page path = "/" + page_name filename = os.path.basename(path) obj_id = seaserv.get_file_id_by_path(repo_id, path) if not obj_id: # Replace '/' in page_name to '-', since wiki name can not # contain '/'. return '''<a href="%s" class="wiki-page-missing">%s</a>''' % \ (url_prefix + '/' + page_name.replace('/', '-'), page_name) token = seafile_api.get_fileserver_access_token(repo_id, obj_id, 'view', username) ret = '<img src="%s" alt="%s" class="wiki-image" />' % (gen_file_get_url(token, filename), filename) return smart_str(ret) else: from seahub.base.templatetags.seahub_tags import file_icon_filter from django.conf import settings # convert other types of filelinks to clickable links path = "/" + page_name icon = file_icon_filter(page_name) s = reverse('view_lib_file', args=[repo_id, urlquote(path)]) a_tag = '''<img src="%simg/file/%s" alt="%s" class="file-icon vam" /> <a href="%s" class="vam" target="_blank">%s</a>''' ret = a_tag % (settings.MEDIA_URL, icon, icon, smart_str(s), page_name) return smart_str(ret)
def _download_dir_from_share_link(request, fileshare, repo, real_path): # check whether owner's traffic over the limit if user_traffic_over_limit(fileshare.username): return render_error( request, _(u'Unable to access file: share link traffic is used up.')) shared_by = fileshare.username if real_path == '/': dirname = repo.name else: dirname = os.path.basename(real_path.rstrip('/')) dir_id = seafile_api.get_dir_id_by_path(repo.id, real_path) if not dir_id: return render_error(request, _(u'Unable to download: folder not found.')) try: total_size = seaserv.seafserv_threaded_rpc.get_dir_size( repo.store_id, repo.version, dir_id) except Exception as e: logger.error(str(e)) return render_error(request, _(u'Internal Error')) if total_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: return render_error( request, _(u'Unable to download directory "%s": size is too large.') % dirname) token = seafile_api.get_fileserver_access_token( repo.id, dir_id, 'download-dir', request.user.username) try: seaserv.send_message( 'seahub.stats', 'dir-download\t%s\t%s\t%s\t%s' % (repo.id, shared_by, dir_id, total_size)) except Exception as e: logger.error('Error when sending dir-download message: %s' % str(e)) return HttpResponseRedirect(gen_file_get_url(token, dirname))
def repl(matchobj): if matchobj.group(2): # return origin string in backquotes return matchobj.group(2) link_alias = link_name = matchobj.group(1).strip() if len(link_name.split("|")) > 1: link_alias = link_name.split("|")[0] link_name = link_name.split("|")[1] filetype, fileext = get_file_type_and_ext(link_name) if fileext == "": # convert link_name that extension is missing to a markdown page try: dirent = get_wiki_dirent(repo_id, link_name) path = "/" + dirent.obj_name href = reverse("repo_view_file", args=[repo_id]) + "?p=" + urlquote(path) a_tag = """<a href="%s">%s</a>""" return a_tag % (href, link_alias) except (WikiDoesNotExist, WikiPageMissing): a_tag = """<p class="wiki-page-missing">%s</p>""" return a_tag % (link_alias) elif filetype == IMAGE: # load image to current page path = "/" + link_name filename = os.path.basename(path) obj_id = get_file_id_by_path(repo_id, path) if not obj_id: return """<p class="wiki-page-missing">%s</p>""" % link_name token = web_get_access_token(repo_id, obj_id, "view", username) return '<img class="wiki-image" src="%s" alt="%s" />' % (gen_file_get_url(token, filename), filename) else: from seahub.base.templatetags.seahub_tags import file_icon_filter # convert other types of filelinks to clickable links path = "/" + link_name icon = file_icon_filter(link_name) s = reverse("repo_view_file", args=[repo_id]) + "?p=" + urlquote(path) a_tag = ( """<img src="%simg/file/%s" alt="%s" class="vam" /> <a href="%s" target="_blank" class="vam">%s</a>""" ) return a_tag % (MEDIA_URL, icon, icon, s, link_name)
def get_file_view_path_and_perm(request, repo_id, obj_id, path): """ Get path and the permission to view file. Returns: outer fileserver file url, inner fileserver file url, permission """ username = request.user.username filename = os.path.basename(path) # user_perm = get_file_access_permission(repo_id, path, username) or \ # get_repo_access_permission(repo_id, username) user_perm = check_repo_access_permission(repo_id, request.user) if user_perm is None: return ('', '', user_perm) else: # Get a token to visit file token = web_get_access_token(repo_id, obj_id, 'view', username) outer_url = gen_file_get_url(token, filename) inner_url = gen_inner_file_get_url(token, filename) return (outer_url, inner_url, user_perm)
def repl(matchobj): if matchobj.group(2): # return origin string in backquotes return matchobj.group(2) linkname = matchobj.group(1).strip() filetype, fileext = get_file_type_and_ext(linkname) filetype = filetype.lower() if fileext == '': # convert linkname that extension is missing to a markdown page filename = linkname + ".md" path = "/" + filename if get_file_id_by_path(repo_id, path): a_tag = "<a href='%s'>%s</a>" return a_tag % (reverse('group_wiki', args=[group.id, linkname]), linkname) else: a_tag = '''<a class="wiki-page-missing" href='%s'>%s</a>''' return a_tag % (reverse('group_wiki', args=[group.id, linkname.replace('/', '-')]), linkname) elif filetype == 'image': # load image to wiki page path = "/" + linkname filename = os.path.basename(path) obj_id = get_file_id_by_path(repo_id, path) if not obj_id: # Replace '/' in linkname to '-', since wiki name can not # contain '/'. return '''<a class="wiki-page-missing" href='%s'>%s</a>''' % \ (reverse('group_wiki', args=[group.id, linkname.replace('/', '-')]), linkname) token = web_get_access_token(repo_id, obj_id, 'view', username) return '<img src="%s" alt="%s" />' % (gen_file_get_url(token, filename), filename) else: from base.templatetags.seahub_tags import file_icon_filter # convert other types of filelinks to clickable links path = "/" + linkname icon = file_icon_filter(linkname) s = reverse('repo_view_file', args=[repo_id]) + '?p=' + path a_tag = '''<img src="%simg/file/%s" alt="%s" class="vam" /> <a href='%s' target='_blank' class="vam">%s</a>''' return a_tag % (MEDIA_URL, icon, icon, s, linkname)
def repl(matchobj): if matchobj.group(2): # return origin string in backquotes return matchobj.group(2) page_name = matchobj.group(1).strip() filetype, fileext = get_file_type_and_ext(page_name) if fileext == '': # convert page_name that extension is missing to a markdown page dirent = get_wiki_dirent(repo_id, page_name) if dirent is not None: a_tag = "<a href='%s'>%s</a>" return a_tag % (url_prefix + '/' + normalize_page_name(page_name), page_name) else: a_tag = '''<a class="wiki-page-missing" href='%s'>%s</a>''' return a_tag % (url_prefix + '/' + page_name.replace('/', '-'), page_name) elif filetype == IMAGE: # load image to wiki page path = "/" + page_name filename = os.path.basename(path) obj_id = get_file_id_by_path(repo_id, path) if not obj_id: # Replace '/' in page_name to '-', since wiki name can not # contain '/'. return '''<a class="wiki-page-missing" href='%s'>%s</a>''' % \ (url_prefix + '/' + page_name.replace('/', '-'), page_name) token = seaserv.web_get_access_token(repo_id, obj_id, 'view', username) return '<img src="%s" alt="%s" />' % (gen_file_get_url(token, filename), filename) else: from base.templatetags.seahub_tags import file_icon_filter # convert other types of filelinks to clickable links path = "/" + page_name icon = file_icon_filter(page_name) s = reverse('repo_view_file', args=[repo_id]) + \ '?p=' + urllib2.quote(smart_str(path)) a_tag = '''<img src="%simg/file/%s" alt="%s" class="vam" /> <a href='%s' target='_blank' class="vam">%s</a>''' return a_tag % (MEDIA_URL, icon, icon, s, page_name)
def view_raw_shared_file(request, token, obj_id, file_name): """Returns raw content of a shared file. Arguments: - `request`: - `token`: - `obj_id`: - `file_name`: """ fileshare = FileShare.objects.get_valid_file_link_by_token(token) if fileshare is None: raise Http404 repo_id = fileshare.repo_id repo = get_repo(repo_id) if not repo: raise Http404 # Normalize file path based on file or dir share link if fileshare.is_file_share_link(): file_path = fileshare.path.rstrip('/') else: file_path = fileshare.path.rstrip('/') + '/' + file_name real_obj_id = seafile_api.get_file_id_by_path(repo_id, file_path) if not real_obj_id: raise Http404 if real_obj_id != obj_id: # perm check raise Http404 filename = os.path.basename(file_path) username = request.user.username token = web_get_access_token(repo_id, real_obj_id, 'view', username) outer_url = gen_file_get_url(token, filename) return HttpResponseRedirect(outer_url)
def view_raw_shared_file(request, token, obj_id, file_name): """Returns raw content of a shared file. Arguments: - `request`: - `token`: - `obj_id`: - `file_name`: """ fileshare = FileShare.objects.get_valid_file_link_by_token(token) if fileshare is None: raise Http404 repo_id = fileshare.repo_id repo = get_repo(repo_id) if not repo: raise Http404 # Normalize file path based on file or dir share link if fileshare.is_file_share_link(): file_path = fileshare.path.rstrip("/") else: file_path = fileshare.path.rstrip("/") + "/" + file_name real_obj_id = seafile_api.get_file_id_by_path(repo_id, file_path) if not real_obj_id: raise Http404 if real_obj_id != obj_id: # perm check raise Http404 filename = os.path.basename(file_path) username = request.user.username token = web_get_access_token(repo_id, real_obj_id, "view", username) outer_url = gen_file_get_url(token, filename) return HttpResponseRedirect(outer_url)
def view_priv_shared_file(request, token): """View private shared file. """ try: pfs = PrivateFileDirShare.objects.get_priv_file_dir_share_by_token(token) except PrivateFileDirShare.DoesNotExist: raise Http404 repo_id = pfs.repo_id repo = get_repo(repo_id) if not repo: raise Http404 username = request.user.username if username != pfs.from_user and username != pfs.to_user: raise Http404 # permission check path = normalize_file_path(pfs.path) obj_id = seafile_api.get_file_id_by_path(repo.id, path) if not obj_id: raise Http404 filename = os.path.basename(path) filetype, fileext = get_file_type_and_ext(filename) access_token = seafile_api.get_fileserver_access_token(repo.id, obj_id, 'view', username) raw_path = gen_file_get_url(access_token, filename) inner_path = gen_inner_file_get_url(access_token, filename) # get file content ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype} fsize = get_file_size(repo.store_id, repo.version, obj_id) exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype) if exceeds_limit: ret_dict['err'] = err_msg else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, inner_path, ret_dict) elif filetype == DOCUMENT: handle_document(inner_path, obj_id, fileext, ret_dict) elif filetype == SPREADSHEET: handle_spreadsheet(inner_path, obj_id, fileext, ret_dict) elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) accessible_repos = get_unencry_rw_repos_by_user(request) save_to_link = reverse('save_private_file_share', args=[pfs.token]) return render_to_response('shared_file_view.html', { 'repo': repo, 'obj_id': obj_id, 'path': path, 'file_name': filename, 'file_size': fsize, 'access_token': access_token, 'fileext': fileext, 'raw_path': raw_path, 'shared_by': pfs.from_user, 'err': ret_dict['err'], 'file_content': ret_dict['file_content'], 'encoding': ret_dict['encoding'], 'file_encoding_list':ret_dict['file_encoding_list'], 'html_exists': ret_dict['html_exists'], 'html_detail': ret_dict.get('html_detail', {}), 'filetype': ret_dict['filetype'], 'use_pdfjs':USE_PDFJS, 'accessible_repos': accessible_repos, 'save_to_link': save_to_link, }, context_instance=RequestContext(request))
def get(self, request, workspace_id, name, commit_id): """Get dtable snapshot by commit_id """ table_name = name table_file_name = table_name + FILE_TYPE # resource check workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: error_msg = 'Workspace %s not found.' % workspace_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) if '@seafile_group' in workspace.owner: group_id = workspace.owner.split('@')[0] group = ccnet_api.get_group(int(group_id)) if not group: error_msg = 'Group %s not found.' % group_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) repo_id = workspace.repo_id repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) dtable = DTables.objects.get_dtable(workspace, table_name) if not dtable: error_msg = 'dtable %s not found.' % table_name return api_error(status.HTTP_404_NOT_FOUND, error_msg) # check for get download link table_path = normalize_file_path(table_file_name) table_file_id = seafile_api.get_file_id_by_path(repo_id, table_path) if not table_file_id: error_msg = 'file %s not found.' % table_file_name return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check username = request.user.username if not check_dtable_permission(username, workspace, dtable): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # main try: snapshot = DTableSnapshot.objects.get_by_commit_id(commit_id) # check if not snapshot: error_msg = 'commit_id not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) dtable_uuid = str(dtable.uuid.hex) if dtable_uuid != snapshot.dtable_uuid: error_msg = 'commit_id invalid.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) # get by commit snapshot_table_path = normalize_file_path(snapshot.dtable_name) obj_id = seafile_api.get_file_id_by_commit_and_path( repo_id, commit_id, snapshot_table_path) if not obj_id: return api_error(status.HTTP_404_NOT_FOUND, 'snapshot not found.') except Exception as e: logger.error(e) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error') # download url token = seafile_api.get_fileserver_access_token( repo_id, obj_id, 'download', username, FILESERVER_TOKEN_ONCE_ONLY) if not token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) redirect_url = gen_file_get_url(token, snapshot.dtable_name) return Response(redirect_url)
def get(self, request): """ Return file info. """ # argument check doc_id = request.GET.get('doc_id', '') if not doc_id: error_msg = 'doc_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_info = cache.get('BISHENG_OFFICE_' + doc_id) if not file_info: error_msg = 'doc_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) username = file_info.get('username') if not username: error_msg = 'username invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) repo_id = file_info.get('repo_id') if not repo_id: error_msg = 'repo_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_path = file_info.get('file_path') if not file_path: error_msg = 'file_path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_path = normalize_file_path(file_path) # resource check try: User.objects.get(email=username) except User.DoesNotExist: error_msg = 'User %s not found.' % username return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not seafile_api.get_repo(repo_id): error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not seafile_api.get_file_id_by_path(repo_id, file_path): error_msg = 'File %s not found.' % file_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check parent_dir = os.path.dirname(file_path) permission = seafile_api.check_permission_by_path(repo_id, parent_dir, username) if not permission: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # get file basic info file_name = os.path.basename(file_path.rstrip('/')) filetype, fileext = get_file_type_and_ext(file_name) # get file raw url file_id = seafile_api.get_file_id_by_path(repo_id, file_path) download_token = seafile_api.get_fileserver_access_token(repo_id, file_id, 'download', username, use_onetime=True) raw_url = gen_file_get_url(download_token, file_name) # get avatar url url, _, _ = api_avatar_url(username, int(72)) # prepare file permission privilege = copy.deepcopy(BISHENG_OFFICE_PRIVILEGE) can_edit = file_info.get('can_edit', False) if not can_edit: privilege.remove('FILE_WRITE') # prepare response file_info = { 'doc': { 'docId': doc_id, 'title': file_name, 'mime_type': BISHENG_OFFICE_MIME_TYPE[fileext], 'fetchUrl': raw_url, 'thumbnail': "", 'fromApi': True }, 'user': { 'uid': username, 'oid': username, 'nickName': email2nickname(username), 'avatar': request.build_absolute_uri(url), 'privilege': privilege }, } return Response(file_info)
def get_file_url(repo, obj_id, file_name): repo_id = repo.id access_token = seaserv.seafserv_rpc.web_get_access_token(repo_id, obj_id, "view", "") url = gen_file_get_url(access_token, file_name) return url
def file_edit(request, repo_id): repo = get_repo(repo_id) if not repo: raise Http404 if request.method == "POST": return file_edit_submit(request, repo_id) if get_user_permission(request, repo_id) != "rw": return render_permission_error(request, _(u"Unable to edit file")) 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")) head_id = repo.head_cmmt_id obj_id = get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u"The file does not exist.")) token = web_get_access_token(repo_id, obj_id, "view", request.user.username) # generate path and link zipped = gen_path_link(path, repo.name) filetype, fileext = get_file_type_and_ext(filename) op = None err = "" file_content = None encoding = None file_encoding_list = FILE_ENCODING_LIST if filetype == TEXT or filetype == MARKDOWN or filetype == SF: if repo.encrypted: repo.password_set = seafserv_rpc.is_passwd_set(repo_id, request.user.username) if not repo.password_set: op = "decrypt" if not op: raw_path = gen_file_get_url(token, filename) file_enc = request.GET.get("file_enc", "auto") if not file_enc in FILE_ENCODING_LIST: file_enc = "auto" err, file_content, encoding = repo_file_get(raw_path, file_enc) if encoding and encoding not in FILE_ENCODING_LIST: file_encoding_list.append(encoding) else: err = _(u"Edit online is not offered for this type of file.") return render_to_response( "file_edit.html", { "repo": repo, "u_filename": u_filename, "wiki_name": os.path.splitext(u_filename)[0], "path": path, "zipped": zipped, "filetype": filetype, "fileext": fileext, "op": op, "err": err, "file_content": file_content, "encoding": encoding, "file_encoding_list": file_encoding_list, "head_id": head_id, "from": request.GET.get("from", ""), "gid": request.GET.get("gid", ""), }, context_instance=RequestContext(request), )
def view_file_via_shared_dir(request, token): assert token is not None # Checked by URLconf fileshare = FileShare.objects.get_valid_file_link_by_token(token) if fileshare is None: raise Http404 shared_by = fileshare.username repo_id = fileshare.repo_id repo = get_repo(repo_id) if not repo: raise Http404 path = request.GET.get('p', '').rstrip('/') if not path: raise Http404 if not path.startswith(fileshare.path): # Can not view upper dir of shared dir raise Http404 zipped = gen_path_link(path, '') obj_id = seafile_api.get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u'File does not exist')) file_size = seafile_api.get_file_size(repo.store_id, repo.version, obj_id) filename = os.path.basename(path) filetype, fileext = get_file_type_and_ext(filename) access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id, 'view', '') raw_path = gen_file_get_url(access_token, filename) inner_path = gen_inner_file_get_url(access_token, filename) img_prev = None img_next = None # get file content ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype} exceeds_limit, err_msg = file_size_exceeds_preview_limit(file_size, filetype) if exceeds_limit: ret_dict['err'] = err_msg else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, inner_path, ret_dict) elif filetype == DOCUMENT: handle_document(inner_path, obj_id, fileext, ret_dict) elif filetype == SPREADSHEET: handle_spreadsheet(inner_path, obj_id, fileext, ret_dict) elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) elif filetype == IMAGE: current_commit = get_commits(repo_id, 0, 1)[0] parent_dir = os.path.dirname(path) dirs = seafile_api.list_dir_by_commit_and_path(current_commit.repo_id, current_commit.id, parent_dir) if not dirs: raise Http404 img_list = [] for dirent in dirs: if not stat.S_ISDIR(dirent.props.mode): fltype, flext = get_file_type_and_ext(dirent.obj_name) if fltype == 'Image': img_list.append(dirent.obj_name) if len(img_list) > 1: img_list.sort(lambda x, y : cmp(x.lower(), y.lower())) cur_img_index = img_list.index(filename) if cur_img_index != 0: img_prev = posixpath.join(parent_dir, img_list[cur_img_index - 1]) if cur_img_index != len(img_list) - 1: img_next = posixpath.join(parent_dir, img_list[cur_img_index + 1]) # send statistic messages if ret_dict['filetype'] != 'Unknown': try: send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \ (repo.id, shared_by, obj_id, file_size)) except SearpcError, e: logger.error('Error when sending file-view message: %s' % str(e))
if from_shared_link: try: file_size = seafile_api.get_file_size(repo.store_id, repo.version, obj_id) send_message( 'seahub.stats', 'file-download\t%s\t%s\t%s\t%s' % (repo.id, shared_by, obj_id, file_size)) except Exception, e: logger.error('Error when sending file-download message: %s' % str(e)) else: # send stats message send_file_download_msg(request, repo, path, 'web') file_name = os.path.basename(path.rstrip('/')) redirect_url = gen_file_get_url(token, file_name) return HttpResponseRedirect(redirect_url) ########## text diff def get_file_content_by_commit_and_path(request, repo_id, commit_id, path, file_enc): try: obj_id = seafserv_threaded_rpc.get_file_id_by_commit_and_path( \ repo_id, commit_id, path) except: return None, 'bad path' if not obj_id or obj_id == EMPTY_SHA1: return '', None else:
def repo_download_dir(request, repo_id): repo = get_repo(repo_id) if not repo: return render_error(request, _('Library does not exist')) path = request.GET.get('p', '/') if path[-1] != '/': # Normalize dir path path += '/' if not seafile_api.get_dir_id_by_path(repo.id, path): return render_error(request, _('"%s" does not exist.') % path) if len(path) > 1: dirname = os.path.basename( path.rstrip('/')) # Here use `rstrip` to cut out last '/' in path else: dirname = repo.name allow_download = parse_repo_perm( check_folder_permission(request, repo_id, '/')).can_download if allow_download: dir_id = seafile_api.get_dir_id_by_commit_and_path( repo.id, repo.head_cmmt_id, path) try: total_size = seafile_api.get_dir_size(repo.store_id, repo.version, dir_id) except Exception as e: logger.error(str(e)) return render_error(request, _('Internal Server Error')) if total_size > MAX_DOWNLOAD_DIR_SIZE: return render_error( request, _('Unable to download directory "%s": size is too large.') % dirname) is_windows = 0 if is_windows_operating_system(request): is_windows = 1 fake_obj_id = { 'obj_id': dir_id, 'dir_name': dirname, 'is_windows': is_windows } token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-dir', request.user.username) if not token: return render_error(request, _('Internal Server Error')) else: return render_error(request, _('Unable to download "%s"') % dirname) url = gen_file_get_url(token, dirname) from seahub.views.file import send_file_access_msg send_file_access_msg(request, repo, path, 'web') return redirect(url)
def view_priv_shared_file(request, token): """View private shared file. """ try: pfs = PrivateFileDirShare.objects.get_priv_file_dir_share_by_token( token) except PrivateFileDirShare.DoesNotExist: raise Http404 repo_id = pfs.repo_id repo = get_repo(repo_id) if not repo: raise Http404 username = request.user.username if username != pfs.from_user and username != pfs.to_user: raise Http404 # permission check path = normalize_file_path(pfs.path) obj_id = seafile_api.get_file_id_by_path(repo.id, path) if not obj_id: raise Http404 filename = os.path.basename(path) filetype, fileext = get_file_type_and_ext(filename) access_token = seafile_api.get_fileserver_access_token( repo.id, obj_id, 'view', username) raw_path = gen_file_get_url(access_token, filename) inner_path = gen_inner_file_get_url(access_token, filename) # get file content ret_dict = { 'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype } fsize = get_file_size(repo.store_id, repo.version, obj_id) exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype) if exceeds_limit: ret_dict['err'] = err_msg else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, inner_path, ret_dict) elif filetype == DOCUMENT: handle_document(inner_path, obj_id, fileext, ret_dict) elif filetype == SPREADSHEET: handle_spreadsheet(inner_path, obj_id, fileext, ret_dict) elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) accessible_repos = get_unencry_rw_repos_by_user(request) save_to_link = reverse('save_private_file_share', args=[pfs.token]) return render_to_response( 'shared_file_view.html', { 'repo': repo, 'obj_id': obj_id, 'path': path, 'file_name': filename, 'file_size': fsize, 'access_token': access_token, 'fileext': fileext, 'raw_path': raw_path, 'shared_by': pfs.from_user, 'err': ret_dict['err'], 'file_content': ret_dict['file_content'], 'encoding': ret_dict['encoding'], 'file_encoding_list': ret_dict['file_encoding_list'], 'html_exists': ret_dict['html_exists'], 'html_detail': ret_dict.get('html_detail', {}), 'filetype': ret_dict['filetype'], 'use_pdfjs': USE_PDFJS, 'accessible_repos': accessible_repos, 'save_to_link': save_to_link, }, context_instance=RequestContext(request))
def view_file_via_shared_dir(request, token): assert token is not None # Checked by URLconf fileshare = FileShare.objects.get_valid_file_link_by_token(token) if fileshare is None: raise Http404 shared_by = fileshare.username repo_id = fileshare.repo_id repo = get_repo(repo_id) if not repo: raise Http404 path = request.GET.get('p', '').rstrip('/') if not path: raise Http404 if not path.startswith( fileshare.path): # Can not view upper dir of shared dir raise Http404 zipped = gen_path_link(path, '') obj_id = seafile_api.get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u'File does not exist')) file_size = seafile_api.get_file_size(repo.store_id, repo.version, obj_id) filename = os.path.basename(path) filetype, fileext = get_file_type_and_ext(filename) access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id, 'view', '') raw_path = gen_file_get_url(access_token, filename) inner_path = gen_inner_file_get_url(access_token, filename) img_prev = None img_next = None # get file content ret_dict = { 'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype } exceeds_limit, err_msg = file_size_exceeds_preview_limit( file_size, filetype) if exceeds_limit: ret_dict['err'] = err_msg else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, inner_path, ret_dict) elif filetype == DOCUMENT: handle_document(inner_path, obj_id, fileext, ret_dict) elif filetype == SPREADSHEET: handle_spreadsheet(inner_path, obj_id, fileext, ret_dict) elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) elif filetype == IMAGE: current_commit = get_commits(repo_id, 0, 1)[0] parent_dir = os.path.dirname(path) dirs = seafile_api.list_dir_by_commit_and_path( current_commit.repo_id, current_commit.id, parent_dir) if not dirs: raise Http404 img_list = [] for dirent in dirs: if not stat.S_ISDIR(dirent.props.mode): fltype, flext = get_file_type_and_ext(dirent.obj_name) if fltype == 'Image': img_list.append(dirent.obj_name) if len(img_list) > 1: img_list.sort(lambda x, y: cmp(x.lower(), y.lower())) cur_img_index = img_list.index(filename) if cur_img_index != 0: img_prev = posixpath.join(parent_dir, img_list[cur_img_index - 1]) if cur_img_index != len(img_list) - 1: img_next = posixpath.join(parent_dir, img_list[cur_img_index + 1]) # send statistic messages if ret_dict['filetype'] != 'Unknown': try: send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \ (repo.id, shared_by, obj_id, file_size)) except SearpcError, e: logger.error('Error when sending file-view message: %s' % str(e))
def post(self, request, workspace_id, name): # arguments check path = request.data.get('path') if not path: error_msg = 'path is invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) angle = request.data.get('angle') if not angle or angle not in ('90', '180', '270'): error_msg = 'angle is invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) angle = {'90': 2, '180': 3, '270': 4}[angle] # resource check workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: error_msg = 'Workspace %s not found.' % (workspace_id, ) return api_error(status.HTTP_404_NOT_FOUND, error_msg) dtable = DTables.objects.get_dtable(workspace, name) if not dtable: error_msg = 'Table %s not found.' % (name, ) return api_error(status.HTTP_404_NOT_FOUND, error_msg) parent_dir = os.path.join('/asset', str(dtable.uuid)) asset_path = os.path.join(parent_dir, path.lstrip('/')) asset_id = seafile_api.get_file_id_by_path(workspace.repo_id, asset_path) if not asset_id: error_msg = 'Picture %s not found.' % (path, ) return api_error(status.HTTP_404_NOT_FOUND, error_msg) asset_name = os.path.basename(path) file_type, _ = get_file_type_and_ext(asset_name) if file_type != file_types.IMAGE: error_msg = '%s is not a picture.' % (path, ) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # permission check user = request.user if check_dtable_permission(user.username, workspace, dtable) != PERMISSION_READ_WRITE: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # get token try: token = seafile_api.get_fileserver_access_token(workspace.repo_id, asset_id, 'view', '', use_onetime=False) except Exception as e: logger.error('get view token error: %s', e) error_msg = 'Internal Server Error.' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) asset_url = gen_file_get_url(token, asset_name) # request pic try: response = requests.get(asset_url) if response.status_code != 200: logger.error('request asset url: %s response code: %s', asset_url, response.status_code) error_msg = 'Internal Server Error.' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) except Exception as e: logger.error('request: %s error: %s', asset_url, e) error_msg = 'Internal Server Error.' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) img = response.content # get upload link old_img = Image.open(BytesIO(img)) obj_id = json.dumps({'parent_dir': parent_dir}) try: token = seafile_api.get_fileserver_access_token(workspace.repo_id, obj_id, 'upload', '', use_onetime=False) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) upload_link = gen_file_upload_url(token, 'upload-api') # upload try: # rotate and save to fp fp = BytesIO() content_type = response.headers['Content-Type'] old_img.transpose(angle).save(fp, content_type.split('/')[1]) response = requests.post( upload_link, data={ 'parent_dir': parent_dir, 'relative_path': os.path.dirname(path.strip('/')), 'replace': 1 }, files={'file': (asset_name, fp.getvalue(), content_type)}) if response.status_code != 200: logger.error('upload: %s status code: %s', upload_link, response.status_code) error_msg = 'Internal Server Error.' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) except Exception as e: logger.error('upload rotated image error: %s', e) error_msg = 'Internal Server Error.' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # remove thumbnails remove_thumbnail_by_id(asset_id) return Response({'success': True})
def get_onlyoffice_dict(request, username, repo_id, file_path, file_id='', can_edit=False, can_download=True): repo = seafile_api.get_repo(repo_id) if repo.is_virtual: origin_repo_id = repo.origin_repo_id origin_file_path = posixpath.join(repo.origin_path, file_path.strip('/')) # for view history/trash/snapshot file if not file_id: file_id = seafile_api.get_file_id_by_path(origin_repo_id, origin_file_path) else: origin_repo_id = repo_id origin_file_path = file_path if not file_id: file_id = seafile_api.get_file_id_by_path(repo_id, file_path) dl_token = seafile_api.get_fileserver_access_token(repo_id, file_id, 'download', username, use_onetime=True) if not dl_token: return None filetype, fileext = get_file_type_and_ext(file_path) if fileext in ('xls', 'xlsx', 'ods', 'fods', 'csv'): document_type = 'spreadsheet' elif fileext in ('pptx', 'ppt', 'odp', 'fodp', 'ppsx', 'pps'): document_type = 'presentation' else: document_type = 'text' cache_key = generate_onlyoffice_cache_key(repo_id, file_path) doc_key = cache.get(cache_key) # temporary solution when failed to get data from cache(django_pylibmc) # when init process for the first time if not doc_key: doc_key = cache.get(cache_key) if not doc_key: info_bytes = force_bytes(origin_repo_id + origin_file_path + file_id) doc_key = hashlib.md5(info_bytes).hexdigest()[:20] doc_info = json.dumps({ 'repo_id': repo_id, 'file_path': file_path, 'username': username }) cache.set("ONLYOFFICE_%s" % doc_key, doc_info, None) file_name = os.path.basename(file_path.rstrip('/')) doc_url = gen_file_get_url(dl_token, file_name) base_url = get_site_scheme_and_netloc() onlyoffice_editor_callback_url = reverse('onlyoffice_editor_callback') callback_url = urllib.parse.urljoin(base_url, onlyoffice_editor_callback_url) return_dict = { 'repo_id': repo_id, 'path': file_path, 'ONLYOFFICE_APIJS_URL': ONLYOFFICE_APIJS_URL, 'file_type': fileext, 'doc_key': doc_key, 'doc_title': file_name, 'doc_url': doc_url, 'document_type': document_type, 'callback_url': callback_url, 'can_edit': can_edit, 'can_download': can_download, 'username': username, 'onlyoffice_force_save': ONLYOFFICE_FORCE_SAVE, 'enable_watermark': ENABLE_WATERMARK and not can_edit, } if ONLYOFFICE_JWT_SECRET: import jwt config = { "document": { "fileType": fileext, "key": doc_key, "title": file_name, "url": doc_url, "permissions": { "download": can_download, "edit": can_edit, "print": can_download, "review": True } }, "documentType": document_type, "editorConfig": { "callbackUrl": callback_url, "lang": request.LANGUAGE_CODE, "mode": can_edit, "customization": { "forcesave": ONLYOFFICE_FORCE_SAVE, }, "user": { "name": email2nickname(username) } } } return_dict['onlyoffice_jwt_token'] = jwt.encode( config, ONLYOFFICE_JWT_SECRET) return return_dict
def get(self, request, slug): """Get content of a wiki """ path = request.GET.get('p', '/') try: wiki = Wiki.objects.get(slug=slug) except Wiki.DoesNotExist: error_msg = "Wiki not found." return api_error(status.HTTP_404_NOT_FOUND, error_msg) # perm check if not wiki.check_access_wiki(request): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) if request.user.username: parent_dir = os.path.dirname(path) permission = check_folder_permission(request, wiki.repo_id, parent_dir) else: permission = 'r' try: repo = seafile_api.get_repo(wiki.repo_id) if not repo: error_msg = "Wiki library not found." return api_error(status.HTTP_404_NOT_FOUND, error_msg) except SearpcError: error_msg = _("Internal Server Error") return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) file_id = None try: file_id = seafile_api.get_file_id_by_path(repo.repo_id, path) except SearpcError as e: logger.error(e) return api_error(HTTP_520_OPERATION_FAILED, "Failed to get file id by path.") if not file_id: return api_error(status.HTTP_404_NOT_FOUND, "File not found") # send stats message send_file_access_msg(request, repo, path, 'api') file_name = os.path.basename(path) token = seafile_api.get_fileserver_access_token(repo.repo_id, file_id, 'download', request.user.username, 'False') if not token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) url = gen_file_get_url(token, file_name) file_response = urllib2.urlopen(url) content = file_response.read() try: dirent = seafile_api.get_dirent_by_path(repo.repo_id, path) if dirent: latest_contributor, last_modified = dirent.modifier, dirent.mtime else: latest_contributor, last_modified = None, 0 except SearpcError as e: logger.error(e) latest_contributor, last_modified = None, 0 return Response({ "content": content, "latest_contributor": email2nickname(latest_contributor), "last_modified": last_modified, "permission": permission, })
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 shared_by = fileshare.username repo_id = fileshare.repo_id repo = get_repo(repo_id) if not repo: raise Http404 path = fileshare.path.rstrip('/') # Normalize file path obj_id = seafile_api.get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u'File does not exist')) file_size = seafile_api.get_file_size(obj_id) filename = os.path.basename(path) filetype, fileext = get_file_type_and_ext(filename) access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id, 'view', '') raw_path = gen_file_get_url(access_token, filename) inner_path = gen_inner_file_get_url(access_token, filename) # get file content ret_dict = { 'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype } fsize = get_file_size(obj_id) exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype) if exceeds_limit: err = err_msg else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, inner_path, ret_dict) elif filetype == DOCUMENT: handle_document(inner_path, obj_id, fileext, ret_dict) elif filetype == SPREADSHEET: handle_spreadsheet(inner_path, obj_id, fileext, ret_dict) elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) # Increase file shared link view_cnt, this operation should be atomic fileshare.view_cnt = F('view_cnt') + 1 fileshare.save() # send statistic messages if ret_dict['filetype'] != 'Unknown': try: obj_size = seafserv_threaded_rpc.get_file_size(obj_id) send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \ (repo.id, shared_by, obj_id, obj_size)) except SearpcError, e: logger.error('Error when sending file-view message: %s' % str(e))
'obj_id': dir_id, 'dir_name': dirname, 'is_windows': is_windows } token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-dir', request.user.username) if not token: return render_error(request, _(u'Internal Server Error')) else: return render_error(request, _(u'Unable to download "%s"') % dirname) url = gen_file_get_url(token, dirname) from seahub.views.file import send_file_access_msg send_file_access_msg(request, repo, path, 'web') return redirect(url) def group_events_data(events): """ Group events according to the date. """ event_groups = [] for e in events: e.time = utc_to_local(e.timestamp) e.date = e.time.strftime("%Y-%m-%d") if e.etype == 'repo-update': e.author = e.commit.creator_name
def view_shared_file(request, token): """ Preview file via shared link. """ assert token is not None # Checked by URLconf fileshare = FileShare.objects.get_valid_file_link_by_token(token) if fileshare is None: raise Http404 if fileshare.is_encrypted(): if not check_share_link_access(request.user.username, token): d = {'token': token, 'view_name': 'view_shared_file', } if request.method == 'POST': post_values = request.POST.copy() post_values['enc_password'] = fileshare.password form = SharedLinkPasswordForm(post_values) d['form'] = form if form.is_valid(): # set cache for non-anonymous user if request.user.is_authenticated(): set_share_link_access(request.user.username, token) else: return render_to_response('share_access_validation.html', d, context_instance=RequestContext(request)) else: return render_to_response('share_access_validation.html', d, context_instance=RequestContext(request)) shared_by = fileshare.username repo_id = fileshare.repo_id repo = get_repo(repo_id) if not repo: raise Http404 path = fileshare.path.rstrip('/') # Normalize file path obj_id = seafile_api.get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u'File does not exist')) file_size = seafile_api.get_file_size(repo.store_id, repo.version, obj_id) filename = os.path.basename(path) filetype, fileext = get_file_type_and_ext(filename) access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id, 'view', '') raw_path = gen_file_get_url(access_token, filename) inner_path = gen_inner_file_get_url(access_token, filename) # get file content ret_dict = {'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype} exceeds_limit, err_msg = file_size_exceeds_preview_limit(file_size, filetype) if exceeds_limit: ret_dict['err'] = err_msg else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, inner_path, ret_dict) elif filetype == DOCUMENT: handle_document(inner_path, obj_id, fileext, ret_dict) elif filetype == SPREADSHEET: handle_spreadsheet(inner_path, obj_id, fileext, ret_dict) elif filetype == OPENDOCUMENT: if file_size == 0: ret_dict['err'] = _(u'Invalid file format.') elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) # Increase file shared link view_cnt, this operation should be atomic fileshare.view_cnt = F('view_cnt') + 1 fileshare.save() # send statistic messages if ret_dict['filetype'] != 'Unknown': try: send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \ (repo.id, shared_by, obj_id, file_size)) except SearpcError, e: logger.error('Error when sending file-view message: %s' % str(e))
def group_discuss(request, group): if group.is_pub: raise Http404 username = request.user.username form = MessageForm() # remove user notifications UserNotification.objects.seen_group_msg_notices(username, group.id) # Get all group members. members = get_group_members(group.id) """group messages""" # Show 15 group messages per page. paginator = Paginator(GroupMessage.objects.filter(group_id=group.id).order_by("-timestamp"), 15) # Make sure page request is an int. If not, deliver first page. try: page = int(request.GET.get("page", "1")) except ValueError: page = 1 # If page request (9999) is out of range, deliver last page of results. try: group_msgs = paginator.page(page) except (EmptyPage, InvalidPage): group_msgs = paginator.page(paginator.num_pages) group_msgs.page_range = paginator.get_page_range(group_msgs.number) # Force evaluate queryset to fix some database error for mysql. group_msgs.object_list = list(group_msgs.object_list) msg_attachments = MessageAttachment.objects.filter(group_message__in=group_msgs.object_list) msg_replies = MessageReply.objects.filter(reply_to__in=group_msgs.object_list) reply_to_list = [r.reply_to_id for r in msg_replies] for msg in group_msgs.object_list: msg.reply_cnt = reply_to_list.count(msg.id) msg.replies = [] for r in msg_replies: if msg.id == r.reply_to_id: msg.replies.append(r) msg.replies = msg.replies[-3:] msg.attachments = [] for att in msg_attachments: if att.group_message_id != msg.id: continue # Attachment name is file name or directory name. # If is top directory, use repo name instead. path = att.path if path == "/": repo = get_repo(att.repo_id) if not repo: # TODO: what should we do here, tell user the repo # is no longer exists? continue att.name = repo.name else: path = path.rstrip("/") # cut out last '/' if possible att.name = os.path.basename(path) # Load to discuss page if attachment is a image and from recommend. if att.attach_type == "file" and att.src == "recommend": att.filetype, att.fileext = get_file_type_and_ext(att.name) if att.filetype == IMAGE: att.obj_id = get_file_id_by_path(att.repo_id, path) if not att.obj_id: att.err = _(u"File does not exist") else: att.token = seafile_api.get_fileserver_access_token(att.repo_id, att.obj_id, "view", username) att.img_url = gen_file_get_url(att.token, att.name) msg.attachments.append(att) # get available modules(wiki, etc) mods_available = get_available_mods_by_group(group.id) mods_enabled = get_enabled_mods_by_group(group.id) return render_to_response( "group/group_discuss.html", { "group": group, "is_staff": group.is_staff, "group_msgs": group_msgs, "form": form, "mods_enabled": mods_enabled, "mods_available": mods_available, }, context_instance=RequestContext(request), )
def get_onlyoffice_dict(request, username, repo_id, file_path, file_id='', can_edit=False, can_download=True): logger.info('{} open file {} in repo {} with can_edit {}'.format( username, file_path, repo_id, can_edit)) repo = seafile_api.get_repo(repo_id) if repo.is_virtual: origin_repo_id = repo.origin_repo_id origin_file_path = posixpath.join(repo.origin_path, file_path.strip('/')) else: origin_repo_id = repo_id origin_file_path = file_path # for view history/trash/snapshot file if not file_id: file_id = seafile_api.get_file_id_by_path(origin_repo_id, origin_file_path) dl_token = seafile_api.get_fileserver_access_token(repo_id, file_id, 'download', username, use_onetime=False) if not dl_token: return None filetype, fileext = get_file_type_and_ext(file_path) if fileext in ('xls', 'xlsx', 'ods', 'fods', 'csv'): document_type = 'cell' elif fileext in ('pptx', 'ppt', 'odp', 'fodp', 'ppsx', 'pps'): document_type = 'slide' else: document_type = 'word' if not can_edit: doc_key = generate_onlyoffice_doc_key(origin_repo_id, origin_file_path, file_id) else: doc_key = get_doc_key_by_repo_id_file_path(origin_repo_id, origin_file_path) if doc_key: logger.info( 'get doc_key {} from database by repo_id {} file_path {}'. format(doc_key, origin_repo_id, origin_file_path)) else: doc_key = generate_onlyoffice_doc_key(origin_repo_id, origin_file_path, file_id) save_doc_key(doc_key, username, origin_repo_id, origin_file_path) logger.info('save doc_key {} to database'.format(doc_key)) # for render onlyoffice html file_name = os.path.basename(file_path.rstrip('/')) doc_url = gen_file_get_url(dl_token, file_name) base_url = get_site_scheme_and_netloc() onlyoffice_editor_callback_url = reverse('onlyoffice_editor_callback') callback_url = urllib.parse.urljoin(base_url, onlyoffice_editor_callback_url) return_dict = { 'repo_id': repo_id, 'path': file_path, 'ONLYOFFICE_APIJS_URL': ONLYOFFICE_APIJS_URL, 'file_type': fileext, 'doc_key': doc_key, 'doc_title': file_name, 'doc_url': doc_url, 'document_type': document_type, 'callback_url': callback_url, 'can_edit': can_edit, 'can_download': can_download, 'username': username, 'onlyoffice_force_save': ONLYOFFICE_FORCE_SAVE, 'enable_watermark': ENABLE_WATERMARK, 'request_from_onlyoffice_desktop_editor': ONLYOFFICE_DESKTOP_EDITOR_HTTP_USER_AGENT in request.META.get('HTTP_USER_AGENT', ''), } if ONLYOFFICE_JWT_SECRET: import jwt config = { "document": { "fileType": fileext, "key": doc_key, "title": file_name, "url": doc_url, "permissions": { "download": can_download, "edit": can_edit, "print": can_download, "review": True } }, "documentType": document_type, "editorConfig": { "callbackUrl": callback_url, "lang": request.LANGUAGE_CODE, "mode": can_edit, "customization": { "forcesave": ONLYOFFICE_FORCE_SAVE, }, } } if request.user.is_authenticated: user_dict = {"id": username, "name": email2nickname(username)} config['editorConfig']['user'] = user_dict else: anonymous_dict = {"request": True, "label": "Guest"} config['editorConfig']['customization'][ 'anonymous'] = anonymous_dict return_dict['onlyoffice_jwt_token'] = jwt.encode( config, ONLYOFFICE_JWT_SECRET) return return_dict
def get(self, request, repo_id, format=None): repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) path = request.GET.get('p', None) if not path: error_msg = 'p invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: file_id = seafile_api.get_file_id_by_path(repo_id, path) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not file_id: error_msg = 'File %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if check_folder_permission(request, repo_id, path) is None: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # send stats message send_file_access_msg(request, repo, path, 'api') op = request.GET.get('op', 'download') if op == 'download': reuse = request.GET.get('reuse', '0') if reuse not in ('1', '0'): error_msg = "If you want to reuse file server access token for download file, you should set 'reuse' argument as '1'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) use_onetime = False if reuse == '1' else True file_name = os.path.basename(path) token = seafile_api.get_fileserver_access_token(repo_id, file_id, op, request.user.username, use_onetime) redirect_url = gen_file_get_url(token, file_name) return Response({"url": redirect_url}) elif op == 'downloadblks': blklist = [] encrypted = False enc_version = 0 if file_id != EMPTY_SHA1: try: blks = seafile_api.list_blocks_by_file_id(repo_id, file_id) blklist = blks.split('\n') except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) blklist = [i for i in blklist if len(i) == 40] if len(blklist) > 0: repo = seafile_api.get_repo(repo_id) encrypted = repo.encrypted enc_version = repo.enc_version res = { 'file_id': file_id, 'blklist': blklist, 'encrypted': encrypted, 'enc_version': enc_version, } return Response(res) elif op == 'sharelink': link = get_shared_link(request, repo_id, path) return Response({"link": link}) else: error_msg = 'op invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
def file_edit(request, repo_id): repo = get_repo(repo_id) if not repo: raise Http404 if request.method == 'POST': return file_edit_submit(request, repo_id) if get_user_permission(request, repo_id) != 'rw': return render_permission_error(request, _(u'Unable to edit file')) 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')) head_id = repo.head_cmmt_id obj_id = get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u'The file does not exist.')) token = web_get_access_token(repo_id, obj_id, 'view', request.user.username) # generate path and link zipped = gen_path_link(path, repo.name) filetype, fileext = get_file_type_and_ext(filename) op = None err = '' file_content = None encoding = None file_encoding_list = FILE_ENCODING_LIST if filetype == TEXT or filetype == MARKDOWN or filetype == SF: if repo.encrypted: repo.password_set = seafserv_rpc.is_passwd_set(repo_id, request.user.username) if not repo.password_set: op = 'decrypt' if not op: raw_path = gen_file_get_url(token, filename) file_enc = request.GET.get('file_enc', 'auto') if not file_enc in FILE_ENCODING_LIST: file_enc = 'auto' err, file_content, encoding = repo_file_get(raw_path, file_enc) if encoding and encoding not in FILE_ENCODING_LIST: file_encoding_list.append(encoding) else: err = _(u'Edit online is not offered for this type of file.') # Redirect to different place according to from page when user click # cancel button on file edit page. cancel_url = reverse('repo_view_file', args=[repo.id]) + '?p=' + urlquote(path) page_from = request.GET.get('from', '') gid = request.GET.get('gid', '') wiki_name = os.path.splitext(u_filename)[0] if page_from == 'wiki_page_edit' or page_from == 'wiki_page_new': cancel_url = reverse('group_wiki', args=[gid, wiki_name]) elif page_from == 'personal_wiki_page_edit' or page_from == 'personal_wiki_page_new': cancel_url = reverse('personal_wiki', args=[wiki_name]) search_repo_id = None if not repo.encrypted: search_repo_id = repo.id return render_to_response('file_edit.html', { 'repo':repo, 'u_filename':u_filename, 'wiki_name': wiki_name, 'path':path, 'zipped':zipped, 'filetype':filetype, 'fileext':fileext, 'op':op, 'err':err, 'file_content':file_content, 'encoding': encoding, 'file_encoding_list':file_encoding_list, 'head_id': head_id, 'from': page_from, 'gid': gid, 'cancel_url': cancel_url, 'search_repo_id': search_repo_id, }, context_instance=RequestContext(request))
def group_discuss(request, group): if group.is_pub: raise Http404 username = request.user.username form = MessageForm() # remove user notifications UserNotification.objects.seen_group_msg_notices(username, group.id) # Get all group members. members = get_group_members(group.id) """group messages""" # Show 15 group messages per page. paginator = Paginator(GroupMessage.objects.filter( group_id=group.id).order_by('-timestamp'), 15) # Make sure page request is an int. If not, deliver first page. try: page = int(request.GET.get('page', '1')) except ValueError: page = 1 # If page request (9999) is out of range, deliver last page of results. try: group_msgs = paginator.page(page) except (EmptyPage, InvalidPage): group_msgs = paginator.page(paginator.num_pages) group_msgs.page_range = paginator.get_page_range(group_msgs.number) # Force evaluate queryset to fix some database error for mysql. group_msgs.object_list = list(group_msgs.object_list) msg_attachments = MessageAttachment.objects.filter(group_message__in=group_msgs.object_list) msg_replies = MessageReply.objects.filter(reply_to__in=group_msgs.object_list) reply_to_list = [ r.reply_to_id for r in msg_replies ] for msg in group_msgs.object_list: msg.reply_cnt = reply_to_list.count(msg.id) msg.replies = [] for r in msg_replies: if msg.id == r.reply_to_id: msg.replies.append(r) msg.replies = msg.replies[-3:] msg.attachments = [] for att in msg_attachments: if att.group_message_id != msg.id: continue # Attachment name is file name or directory name. # If is top directory, use repo name instead. path = att.path if path == '/': repo = get_repo(att.repo_id) if not repo: # TODO: what should we do here, tell user the repo # is no longer exists? continue att.name = repo.name else: path = path.rstrip('/') # cut out last '/' if possible att.name = os.path.basename(path) # Load to discuss page if attachment is a image and from recommend. if att.attach_type == 'file' and att.src == 'recommend': att.filetype, att.fileext = get_file_type_and_ext(att.name) if att.filetype == IMAGE: att.obj_id = get_file_id_by_path(att.repo_id, path) if not att.obj_id: att.err = _(u'File does not exist') else: att.token = seafile_api.get_fileserver_access_token( att.repo_id, att.obj_id, 'view', username) att.img_url = gen_file_get_url(att.token, att.name) msg.attachments.append(att) # get available modules(wiki, etc) mods_available = get_available_mods_by_group(group.id) mods_enabled = get_enabled_mods_by_group(group.id) return render_to_response("group/group_discuss.html", { "group" : group, "is_staff": group.is_staff, "group_msgs": group_msgs, "form": form, "mods_enabled": mods_enabled, "mods_available": mods_available, }, context_instance=RequestContext(request))
def view_priv_shared_file(request, token): """View private shared file. """ try: pfs = PrivateFileDirShare.objects.get_priv_file_dir_share_by_token(token) except PrivateFileDirShare.DoesNotExist: raise Http404 repo_id = pfs.repo_id repo = get_repo(repo_id) if not repo: raise Http404 username = request.user.username if username != pfs.from_user and username != pfs.to_user: raise Http404 # permission check path = normalize_file_path(pfs.path) obj_id = seafile_api.get_file_id_by_path(repo.id, path) if not obj_id: raise Http404 filename = os.path.basename(path) filetype, fileext = get_file_type_and_ext(filename) access_token = seafile_api.get_fileserver_access_token(repo.id, obj_id, "view", username) raw_path = gen_file_get_url(access_token, filename) inner_path = gen_inner_file_get_url(access_token, filename) # get file content ret_dict = { "err": "", "file_content": "", "encoding": "", "file_enc": "", "file_encoding_list": [], "html_exists": False, "filetype": filetype, } fsize = get_file_size(repo.store_id, repo.version, obj_id) exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype) if exceeds_limit: ret_dict["err"] = err_msg else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, inner_path, ret_dict) elif filetype == DOCUMENT: handle_document(inner_path, obj_id, fileext, ret_dict) elif filetype == SPREADSHEET: handle_spreadsheet(inner_path, obj_id, fileext, ret_dict) elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) accessible_repos = get_unencry_rw_repos_by_user(request) save_to_link = reverse("save_private_file_share", args=[pfs.token]) return render_to_response( "shared_file_view.html", { "repo": repo, "obj_id": obj_id, "path": path, "file_name": filename, "file_size": fsize, "access_token": access_token, "fileext": fileext, "raw_path": raw_path, "shared_by": pfs.from_user, "err": ret_dict["err"], "file_content": ret_dict["file_content"], "encoding": ret_dict["encoding"], "file_encoding_list": ret_dict["file_encoding_list"], "html_exists": ret_dict["html_exists"], "html_detail": ret_dict.get("html_detail", {}), "filetype": ret_dict["filetype"], "use_pdfjs": USE_PDFJS, "accessible_repos": accessible_repos, "save_to_link": save_to_link, }, context_instance=RequestContext(request), )
def get(self, request): """get file download link by dtable api token Permission: 1. valid token """ # argument check auth = request.META.get('HTTP_AUTHORIZATION', '').split() if not auth or auth[0].lower() != 'token' or len(auth) != 2: return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') api_token = auth[1] path = request.GET.get('path', '/') # resource check try: api_token_obj = DTableAPIToken.objects.get_by_token(api_token) if not api_token_obj: return api_error(status.HTTP_404_NOT_FOUND, 'api token not found.') except Exception as e: logger.error(e) error_msg = 'Internal Server Error.' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) dtable = api_token_obj.dtable table_name = dtable.name workspace_id = dtable.workspace_id error, workspace, dtable = _resource_check(workspace_id, table_name) if error: return error repo_id = workspace.repo_id asset_dir_path = '/asset/' + str(dtable.uuid) asset_dir_id = seafile_api.get_dir_id_by_path(repo_id, asset_dir_path) if not asset_dir_id: error_msg = 'asset not found.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) target_path = os.path.join( asset_dir_path, path.strip('/')) # target_path is path inside repo file_id = seafile_api.get_file_id_by_path(repo_id, target_path.strip('/')) if not file_id: error_msg = 'path %s not found.' % path return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: download_token = seafile_api.get_fileserver_access_token( repo_id, file_id, 'download-link', request.user.username, use_onetime=False) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) file_name = os.path.basename(path.rstrip('/')) download_link = gen_file_get_url(download_token, file_name) return Response({'download_link': download_link})
def view_file_via_shared_dir(request, token): assert token is not None # Checked by URLconf try: fileshare = FileShare.objects.get(token=token) except FileShare.DoesNotExist: raise Http404 shared_by = fileshare.username repo_id = fileshare.repo_id repo = get_repo(repo_id) if not repo: raise Http404 path = request.GET.get('p', '').rstrip('/') if not path: raise Http404 if not path.startswith( fileshare.path): # Can not view upper dir of shared dir raise Http404 zipped = gen_path_link(path, '') obj_id = seafile_api.get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u'File does not exist')) file_size = seafile_api.get_file_size(obj_id) filename = os.path.basename(path) filetype, fileext = get_file_type_and_ext(filename) access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id, 'view', '') raw_path = gen_file_get_url(access_token, filename) inner_path = gen_inner_file_get_url(access_token, filename) # get file content ret_dict = { 'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype } fsize = get_file_size(obj_id) exceeds_limit, err_msg = file_size_exceeds_preview_limit(fsize, filetype) if exceeds_limit: err = err_msg else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, inner_path, ret_dict) elif filetype == DOCUMENT: handle_document(inner_path, obj_id, fileext, ret_dict) elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) # send statistic messages try: obj_size = seafserv_threaded_rpc.get_file_size(obj_id) send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \ (repo.id, shared_by, obj_id, obj_size)) except SearpcError, e: logger.error('Error when sending file-view message: %s' % str(e))
def thumbnail_create(request, repo_id): content_type = 'application/json; charset=utf-8' result = {} if not request.is_ajax(): err_msg = _(u"Permission denied.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=403, content_type=content_type) if not ENABLE_THUMBNAIL: err_msg = _(u"Thumbnail function is not enabled.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=403, content_type=content_type) repo = get_repo(repo_id) if not repo: err_msg = _(u"Library does not exist.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=403, content_type=content_type) if repo.encrypted: err_msg = _( u"Image thumbnail is not supported in encrypted libraries.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=403, content_type=content_type) path = request.GET.get('path', None) obj_id = get_file_id_by_path(repo_id, path) if path is None or obj_id is None: err_msg = _(u"Wrong path.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=403, content_type=content_type) # permission check token = request.GET.get('t', None) if token: fileshare = FileShare.objects.get_valid_file_link_by_token(token) if not fileshare or not path.startswith(fileshare.path) or \ fileshare.repo_id != repo_id: # check if is valid download link share token and # if is a valid repo/dir belonged to this file share err_msg = _(u"Permission denied.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=403, content_type=content_type) else: if not request.user.is_authenticated(): err_msg = _(u"Please login first.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=403, content_type=content_type) elif check_repo_access_permission(repo_id, request.user) is None: err_msg = _(u"Permission denied.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=403, content_type=content_type) # get image file from url size = request.GET.get('size', THUMBNAIL_DEFAULT_SIZE) file_name = os.path.basename(path) access_token = seafile_api.get_fileserver_access_token( repo_id, obj_id, 'view', request.user.username) raw_path = gen_file_get_url(access_token, file_name) open_file = urllib2.urlopen(raw_path) file_size = int(open_file.info()['Content-Length']) # image file size limit check if file_size > THUMBNAIL_IMAGE_SIZE_LIMIT * 1024**2: err_msg = _(u"Image file is too large.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=520, content_type=content_type) thumbnail_dir = os.path.join(THUMBNAIL_ROOT, size) if not os.path.exists(thumbnail_dir): os.makedirs(thumbnail_dir) thumbnail_file = os.path.join(thumbnail_dir, obj_id) if not os.path.exists(thumbnail_file): try: f = StringIO(open_file.read()) image = Image.open(f) if image.mode not in ["1", "L", "P", "RGB", "RGBA"]: image = image.convert("RGB") image.thumbnail((int(size), int(size)), Image.ANTIALIAS) image.save(thumbnail_file, THUMBNAIL_EXTENSION) except Exception as e: logger.error(e) err_msg = _('Failed to create thumbnail.') return HttpResponse(json.dumps({'err_msg': err_msg}), status=500, content_type=content_type) result['thumbnail_src'] = get_thumbnail_src(repo_id, obj_id, size) return HttpResponse(json.dumps(result), content_type=content_type)
def get_onlyoffice_dict(username, repo_id, file_path, file_id='', can_edit=False, can_download=True): repo = seafile_api.get_repo(repo_id) if repo.is_virtual: origin_repo_id = repo.origin_repo_id origin_file_path = posixpath.join(repo.origin_path, file_path.strip('/')) # for view history/trash/snapshot file if not file_id: file_id = seafile_api.get_file_id_by_path(origin_repo_id, origin_file_path) else: origin_repo_id = repo_id origin_file_path = file_path if not file_id: file_id = seafile_api.get_file_id_by_path(repo_id, file_path) dl_token = seafile_api.get_fileserver_access_token(repo_id, file_id, 'download', username, use_onetime=True) if not dl_token: return None filetype, fileext = get_file_type_and_ext(file_path) if fileext in ('xls', 'xlsx', 'ods', 'fods', 'csv'): document_type = 'spreadsheet' elif fileext in ('pptx', 'ppt', 'odp', 'fodp', 'ppsx', 'pps'): document_type = 'presentation' else: document_type = 'text' cache_key = generate_onlyoffice_cache_key(repo_id, file_path) doc_key = cache.get(cache_key) # temporary solution when failed to get data from cache(django_pylibmc) # when init process for the first time if not doc_key: doc_key = cache.get(cache_key) if not doc_key: doc_key = hashlib.md5(force_bytes(origin_repo_id + origin_file_path + file_id)).hexdigest()[:20] doc_info = json.dumps({'repo_id': repo_id, 'file_path': file_path, 'username': username}) cache.set("ONLYOFFICE_%s" % doc_key, doc_info, None) file_name = os.path.basename(file_path.rstrip('/')) doc_url = gen_file_get_url(dl_token, file_name) base_url = get_site_scheme_and_netloc() onlyoffice_editor_callback_url = reverse('onlyoffice_editor_callback') calllback_url = urllib.parse.urljoin(base_url, onlyoffice_editor_callback_url) return_dict = { 'repo_id': repo_id, 'path': file_path, 'ONLYOFFICE_APIJS_URL': ONLYOFFICE_APIJS_URL, 'file_type': fileext, 'doc_key': doc_key, 'doc_title': file_name, 'doc_url': doc_url, 'document_type': document_type, 'callback_url': calllback_url, 'can_edit': can_edit, 'can_download': can_download, 'username': username, 'onlyoffice_force_save': ONLYOFFICE_FORCE_SAVE, 'enable_watermark': ENABLE_WATERMARK and not can_edit, } return return_dict
def get(self, request): """ Return file info. """ # argument check doc_id = request.GET.get('doc_id', '') if not doc_id: error_msg = 'doc_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_info = cache.get('BISHENG_OFFICE_' + doc_id) if not file_info: error_msg = 'doc_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) username = file_info.get('username') if not username: error_msg = 'username invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) repo_id = file_info.get('repo_id') if not repo_id: error_msg = 'repo_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_path = file_info.get('file_path') if not file_path: error_msg = 'file_path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_path = normalize_file_path(file_path) # resource check try: User.objects.get(email=username) except User.DoesNotExist: error_msg = 'User %s not found.' % username return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not seafile_api.get_repo(repo_id): error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) if not seafile_api.get_file_id_by_path(repo_id, file_path): error_msg = 'File %s not found.' % file_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check parent_dir = os.path.dirname(file_path) permission = seafile_api.check_permission_by_path(repo_id, parent_dir, username) if not permission: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # get file basic info file_name = os.path.basename(file_path.rstrip('/')) filetype, fileext = get_file_type_and_ext(file_name) # get file raw url file_id = seafile_api.get_file_id_by_path(repo_id, file_path) download_token = seafile_api.get_fileserver_access_token(repo_id, file_id, 'download', username, use_onetime=True) raw_url = gen_file_get_url(download_token, file_name) # get avatar url url, _, _ = api_avatar_url(username, int(72)) # prepare file permission privilege = copy.deepcopy(BISHENG_OFFICE_PRIVILEGE) can_edit = file_info.get('can_edit', False) if not can_edit: privilege.remove('FILE_WRITE') # prepare response file_info = { 'doc': { 'docId': doc_id, 'title': file_name, 'mime_type': BISHENG_OFFICE_MIME_TYPE[fileext], 'fetchUrl': raw_url, 'thumbnail': "", 'fromApi': True }, 'user': { 'uid': username, 'oid': username, 'nickName': email2nickname(username), 'avatar': url, 'privilege': privilege }, } return Response(file_info)
def view_shared_file(request, token): """ Preview file via shared link. """ assert token is not None # Checked by URLconf fileshare = FileShare.objects.get_valid_file_link_by_token(token) if fileshare is None: raise Http404 if fileshare.is_encrypted(): if not check_share_link_access(request.user.username, token): d = { 'token': token, 'view_name': 'view_shared_file', } if request.method == 'POST': post_values = request.POST.copy() post_values['enc_password'] = fileshare.password form = SharedLinkPasswordForm(post_values) d['form'] = form if form.is_valid(): # set cache for non-anonymous user if request.user.is_authenticated(): set_share_link_access(request.user.username, token) else: return render_to_response( 'share_access_validation.html', d, context_instance=RequestContext(request)) else: return render_to_response( 'share_access_validation.html', d, context_instance=RequestContext(request)) shared_by = fileshare.username repo_id = fileshare.repo_id repo = get_repo(repo_id) if not repo: raise Http404 path = fileshare.path.rstrip('/') # Normalize file path obj_id = seafile_api.get_file_id_by_path(repo_id, path) if not obj_id: return render_error(request, _(u'File does not exist')) file_size = seafile_api.get_file_size(repo.store_id, repo.version, obj_id) filename = os.path.basename(path) filetype, fileext = get_file_type_and_ext(filename) access_token = seafserv_rpc.web_get_access_token(repo.id, obj_id, 'view', '') raw_path = gen_file_get_url(access_token, filename) inner_path = gen_inner_file_get_url(access_token, filename) # get file content ret_dict = { 'err': '', 'file_content': '', 'encoding': '', 'file_enc': '', 'file_encoding_list': [], 'html_exists': False, 'filetype': filetype } exceeds_limit, err_msg = file_size_exceeds_preview_limit( file_size, filetype) if exceeds_limit: ret_dict['err'] = err_msg else: """Choose different approach when dealing with different type of file.""" if is_textual_file(file_type=filetype): handle_textual_file(request, filetype, inner_path, ret_dict) elif filetype == DOCUMENT: handle_document(inner_path, obj_id, fileext, ret_dict) elif filetype == SPREADSHEET: handle_spreadsheet(inner_path, obj_id, fileext, ret_dict) elif filetype == OPENDOCUMENT: if file_size == 0: ret_dict['err'] = _(u'Invalid file format.') elif filetype == PDF: handle_pdf(inner_path, obj_id, fileext, ret_dict) # Increase file shared link view_cnt, this operation should be atomic fileshare.view_cnt = F('view_cnt') + 1 fileshare.save() # send statistic messages if ret_dict['filetype'] != 'Unknown': try: send_message('seahub.stats', 'file-view\t%s\t%s\t%s\t%s' % \ (repo.id, shared_by, obj_id, file_size)) except SearpcError, e: logger.error('Error when sending file-view message: %s' % str(e))
def dtable_asset_preview(request, workspace_id, dtable_id, path): # resource check workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: return render_error(request, 'Workspace does not exist.') repo_id = workspace.repo_id repo = seafile_api.get_repo(repo_id) if not repo: return render_error(request, 'Library does not exist.') dtable = DTables.objects.get_dtable_by_uuid(dtable_id) if not dtable: return render_error(request, 'DTable does not exist.') asset_path = normalize_file_path(os.path.join('/asset', dtable_id, path)) asset_id = seafile_api.get_file_id_by_path(repo_id, asset_path) if not asset_id: return render_error(request, 'Asset file does not exist.') # permission check username = request.user.username if not check_dtable_permission(username, workspace, dtable): return render_permission_error(request, _('Permission denied.')) file_enc = request.GET.get('file_enc', 'auto') if file_enc not in FILE_ENCODING_LIST: file_enc = 'auto' token = seafile_api.get_fileserver_access_token(repo_id, asset_id, 'view', '', use_onetime=False) file_name = os.path.basename(normalize_file_path(path)) file_type, file_ext = get_file_type_and_ext(file_name) inner_path = gen_inner_file_get_url(token, file_name) error_msg, file_content, encoding = get_file_content( file_type, inner_path, file_enc) raw_path = gen_file_get_url(token, file_name) download_url = '%s/workspace/%s/asset/%s/%s?dl=1' % ( DTABLE_WEB_SERVICE_URL.strip('/'), workspace_id, dtable_id, path) return_dict = { 'repo': repo, 'filename': file_name, 'file_path': asset_path, 'file_type': file_type, 'file_ext': file_ext, 'raw_path': raw_path, 'download_url': download_url, 'file_content': file_content, 'err': 'File preview unsupported' if file_type == 'Unknown' else error_msg, } return render(request, 'dtable_asset_file_view_react.html', return_dict)
def get_group_msgs(groupid, page, username): # Show 15 group messages per page. paginator = Paginator(GroupMessage.objects.filter( group_id=groupid).order_by('-timestamp'), 15) # If page request (9999) is out of range, return None try: group_msgs = paginator.page(page) except (EmptyPage, InvalidPage): return None # Force evaluate queryset to fix some database error for mysql. group_msgs.object_list = list(group_msgs.object_list) attachments = MessageAttachment.objects.filter(group_message__in=group_msgs.object_list) msg_replies = MessageReply.objects.filter(reply_to__in=group_msgs.object_list) reply_to_list = [ r.reply_to_id for r in msg_replies ] for msg in group_msgs.object_list: msg.reply_cnt = reply_to_list.count(msg.id) msg.replies = [] for r in msg_replies: if msg.id == r.reply_to_id: msg.replies.append(r) msg.replies = msg.replies[-3:] for att in attachments: if att.group_message_id != msg.id: continue # Attachment name is file name or directory name. # If is top directory, use repo name instead. path = att.path if path == '/': repo = seafile_api.get_repo(att.repo_id) if not repo: # TODO: what should we do here, tell user the repo # is no longer exists? continue att.name = repo.name else: path = path.rstrip('/') # cut out last '/' if possible att.name = os.path.basename(path) # Load to discuss page if attachment is a image and from recommend. if att.attach_type == 'file' and att.src == 'recommend': att.filetype, att.fileext = get_file_type_and_ext(att.name) if att.filetype == IMAGE: att.obj_id = seafile_api.get_file_id_by_path(att.repo_id, path) if not att.obj_id: att.err = 'File does not exist' else: att.token = seafile_api.get_fileserver_access_token( att.repo_id, att.obj_id, 'view', username) att.img_url = gen_file_get_url(att.token, att.name) msg.attachment = att return group_msgs
def dtable_plugin_asset_view(request, workspace_id, name, plugin_id, path): """ Permission: 1. owner 2. group member 3. shared user """ try: plugin_record = DTablePlugins.objects.get(pk=plugin_id) except DTablePlugins.DoesNotExist: error_msg = 'Plugin %s not found.' % plugin_id return render_error(request, error_msg) workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: error_msg = 'Workspace %s not found.' % workspace_id return render_error(request, error_msg) if '@seafile_group' in workspace.owner: group_id = workspace.owner.split('@')[0] group = ccnet_api.get_group(int(group_id)) if not group: error_msg = 'Group %s not found.' % group_id return render_error(request, error_msg) table_name = name dtable = DTables.objects.get_dtable(workspace, table_name) if not dtable: error_msg = 'DTable %s not found.' % table_name return render_error(request, error_msg) # permission check username = request.user.username permission = check_dtable_permission(username, workspace, dtable) if not permission: error_msg = 'Permission denied.' return render_error(request, error_msg) repo_id = workspace.repo_id repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return render_error(request, error_msg) plugin_file_path = os.path.join('/asset', str(dtable.uuid), 'plugins', plugin_record.name) asset_path = os.path.join(plugin_file_path, path) plugin_file_dir_id = seafile_api.get_file_id_by_path(repo_id, asset_path) if not plugin_file_dir_id: return render_error(request, 'Asset file does not exist.') token = seafile_api.get_fileserver_access_token(workspace.repo_id, plugin_file_dir_id, 'view', '', use_onetime=False) url = gen_file_get_url(token, asset_path) import requests r = requests.get(url) response = HttpResponse(r.content) content_type = mimetypes.guess_type(path) if type: response['Content-Type'] = content_type[0] return response
def get(self, request, token): """ Get FileServer download url of the shared file/dir. Permission checking: 1. only admin can perform this action. """ try: sharelink = FileShare.objects.get(token=token) except FileShare.DoesNotExist: error_msg = 'Share link %s not found.' % token return api_error(status.HTTP_404_NOT_FOUND, error_msg) repo_id = sharelink.repo_id repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) result = {} obj_path = sharelink.path if sharelink.s_type == 'f': # download shared file obj_id = seafile_api.get_file_id_by_path(repo_id, obj_path) if not obj_id: error_msg = 'File not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: # `username` parameter only used for encrypted repo download_token = seafile_api.get_fileserver_access_token( repo_id, obj_id, 'download-link', sharelink.username, use_onetime=False) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not download_token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) obj_name = os.path.basename(obj_path.rstrip('/')) result['download_link'] = gen_file_get_url(download_token, obj_name) else: # download (sub) file/folder in shared dir obj_id = seafile_api.get_dir_id_by_path(repo_id, obj_path) if not obj_id: error_msg = 'Folder not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) download_type = request.GET.get('type', None) if not download_type or download_type not in ('file', 'folder'): error_msg = 'type invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) req_path = request.GET.get('path', None) if not req_path: error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if req_path == '/': real_path = obj_path else: real_path = posixpath.join(obj_path, req_path.strip('/')) if download_type == 'file': # download sub file in shared dir real_obj_id = seafile_api.get_file_id_by_path( repo_id, real_path) if not real_obj_id: error_msg = 'File not found.' return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: download_token = seafile_api.get_fileserver_access_token( repo_id, real_obj_id, 'download-link', sharelink.username, use_onetime=False) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not download_token: error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) file_name = os.path.basename(real_path.rstrip('/')) result['download_link'] = gen_file_get_url( download_token, file_name) else: # download sub folder in shared dir if real_path[-1] != '/': real_path += '/' real_obj_id = seafile_api.get_dir_id_by_path( repo_id, real_path) if not real_obj_id: error_msg = 'Folder %s not found.' % req_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) dir_name = repo.name if real_path == '/' else \ os.path.basename(real_path.rstrip('/')) dir_size = seafile_api.get_dir_size(repo.store_id, repo.version, real_obj_id) if dir_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: error_msg = 'Unable to download directory "%s": size is too large.' % dir_name return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # get file server access token is_windows = 0 if is_windows_operating_system(request): is_windows = 1 fake_obj_id = { 'obj_id': real_obj_id, 'dir_name': dir_name, 'is_windows': is_windows } try: zip_token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-dir-link', sharelink.username, use_onetime=False) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) result['download_link'] = gen_dir_zip_download_url(zip_token) return Response(result)
def get_onlyoffice_dict(request, username, repo_id, file_path, file_id='', can_edit=False, can_download=True): logger.info('{} open file {} in repo {} with can_edit {}'.format( username, file_path, repo_id, can_edit)) repo = seafile_api.get_repo(repo_id) if repo.is_virtual: origin_repo_id = repo.origin_repo_id origin_file_path = posixpath.join(repo.origin_path, file_path.strip('/')) # for view history/trash/snapshot file if not file_id: file_id = seafile_api.get_file_id_by_path(origin_repo_id, origin_file_path) else: origin_repo_id = repo_id origin_file_path = file_path if not file_id: file_id = seafile_api.get_file_id_by_path(repo_id, file_path) dl_token = seafile_api.get_fileserver_access_token(repo_id, file_id, 'download', username, use_onetime=False) if not dl_token: return None filetype, fileext = get_file_type_and_ext(file_path) if fileext in ('xls', 'xlsx', 'ods', 'fods', 'csv'): document_type = 'spreadsheet' elif fileext in ('pptx', 'ppt', 'odp', 'fodp', 'ppsx', 'pps'): document_type = 'presentation' else: document_type = 'text' if not can_edit: info_bytes = force_bytes(origin_repo_id + origin_file_path + file_id) doc_key = hashlib.md5(info_bytes).hexdigest()[:20] else: cache_key = generate_onlyoffice_cache_key(origin_repo_id, origin_file_path) doc_key = cache.get(cache_key) # temporary solution when failed to get data from cache(django_pylibmc) # when init process for the first time if not doc_key: doc_key = cache.get(cache_key) if doc_key: logger.info('get doc_key {} from cache by cache_key {}'.format( doc_key, cache_key)) else: # In theory, file is unlocked when editing finished. # This can happend if memcache is restarted or memcache is full and doc key is deleted. if if_locked_by_online_office(repo_id, file_path): logger.warning( 'no doc_key in cache, but file {} in {} is locked by online office' .format(file_path, repo_id)) # generate doc_key info_bytes = force_bytes(origin_repo_id + origin_file_path + file_id) doc_key = hashlib.md5(info_bytes).hexdigest()[:20] logger.info( 'generate new doc_key {} by repo_id {} file_path {} file_id {}' .format(doc_key, origin_repo_id, origin_file_path, file_id)) logger.info('set cache_key {} and doc_key {} to cache'.format( cache_key, doc_key)) cache.set(cache_key, doc_key, None) if not cache.get("ONLYOFFICE_%s" % doc_key): doc_info = json.dumps({ 'repo_id': origin_repo_id, 'file_path': origin_file_path, 'username': username }) cache.set("ONLYOFFICE_%s" % doc_key, doc_info, None) logger.info('set doc_key {} and doc_info {} to cache'.format( doc_key, doc_info)) # for render onlyoffice html file_name = os.path.basename(file_path.rstrip('/')) doc_url = gen_file_get_url(dl_token, file_name) base_url = get_site_scheme_and_netloc() onlyoffice_editor_callback_url = reverse('onlyoffice_editor_callback') callback_url = urllib.parse.urljoin(base_url, onlyoffice_editor_callback_url) return_dict = { 'repo_id': repo_id, 'path': file_path, 'ONLYOFFICE_APIJS_URL': ONLYOFFICE_APIJS_URL, 'file_type': fileext, 'doc_key': doc_key, 'doc_title': file_name, 'doc_url': doc_url, 'document_type': document_type, 'callback_url': callback_url, 'can_edit': can_edit, 'can_download': can_download, 'username': username, 'onlyoffice_force_save': ONLYOFFICE_FORCE_SAVE, 'enable_watermark': ENABLE_WATERMARK, } if ONLYOFFICE_JWT_SECRET: import jwt config = { "document": { "fileType": fileext, "key": doc_key, "title": file_name, "url": doc_url, "permissions": { "download": can_download, "edit": can_edit, "print": can_download, "review": True } }, "documentType": document_type, "editorConfig": { "callbackUrl": callback_url, "lang": request.LANGUAGE_CODE, "mode": can_edit, "customization": { "forcesave": ONLYOFFICE_FORCE_SAVE, }, "user": { "name": email2nickname(username) } } } return_dict['onlyoffice_jwt_token'] = jwt.encode( config, ONLYOFFICE_JWT_SECRET) return return_dict
except Exception, e: logger.error(str(e)) return render_error(request, _(u'Internal Error')) if total_size > MAX_DOWNLOAD_DIR_SIZE: return render_error(request, _(u'Unable to download directory "%s": size is too large.') % dirname) token = seafile_api.get_fileserver_access_token(repo_id, dir_id, 'download-dir', request.user.username) else: return render_error(request, _(u'Unable to download "%s"') % dirname ) url = gen_file_get_url(token, dirname) from seahub.views.file import send_file_access_msg send_file_access_msg(request, repo, path, 'web') return redirect(url) def group_events_data(events): """ Group events according to the date. """ event_groups = [] for e in events: e.time = utc_to_local(e.timestamp) e.date = e.time.strftime("%Y-%m-%d") if e.etype == 'repo-update': e.author = e.commit.creator_name elif e.etype == 'repo-create':
def get_file_url(repo, obj_id, file_name): repo_id = repo.id access_token = seaserv.seafserv_rpc.web_get_access_token(repo_id, obj_id, 'view', '') url = gen_file_get_url(access_token, file_name) return url
def thumbnail_create(request, repo_id): content_type = 'application/json; charset=utf-8' result = {} if not request.is_ajax(): err_msg = _(u"Permission denied.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=403, content_type=content_type) if not ENABLE_THUMBNAIL: err_msg = _(u"Thumbnail function is not enabled.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=403, content_type=content_type) repo = get_repo(repo_id) if not repo: err_msg = _(u"Library does not exist.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=403, content_type=content_type) if repo.encrypted: err_msg = _(u"Image thumbnail is not supported in encrypted libraries.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=403, content_type=content_type) path = request.GET.get('path', None) obj_id = get_file_id_by_path(repo_id, path) if path is None or obj_id is None: err_msg = _(u"Wrong path.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=403, content_type=content_type) # permission check token = request.GET.get('t', None) if token: fileshare = FileShare.objects.get_valid_file_link_by_token(token) if not fileshare or not path.startswith(fileshare.path) or \ fileshare.repo_id != repo_id: # check if is valid download link share token and # if is a valid repo/dir belonged to this file share err_msg = _(u"Permission denied.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=403, content_type=content_type) else: if not request.user.is_authenticated(): err_msg = _(u"Please login first.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=403, content_type=content_type) elif check_repo_access_permission(repo_id, request.user) is None: err_msg = _(u"Permission denied.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=403, content_type=content_type) # get image file from url size = request.GET.get('size', THUMBNAIL_DEFAULT_SIZE) file_name = os.path.basename(path) access_token = seafile_api.get_fileserver_access_token(repo_id, obj_id, 'view', request.user.username) raw_path = gen_file_get_url(access_token, file_name) open_file = urllib2.urlopen(raw_path) file_size = int(open_file.info()['Content-Length']) # image file size limit check if file_size > THUMBNAIL_IMAGE_SIZE_LIMIT * 1024**2: err_msg = _(u"Image file is too large.") return HttpResponse(json.dumps({"err_msg": err_msg}), status=520, content_type=content_type) thumbnail_dir = os.path.join(THUMBNAIL_ROOT, size) if not os.path.exists(thumbnail_dir): os.makedirs(thumbnail_dir) thumbnail_file = os.path.join(thumbnail_dir, obj_id) if not os.path.exists(thumbnail_file): try: f = StringIO(open_file.read()) image = Image.open(f) if image.mode not in ["1", "L", "P", "RGB", "RGBA"]: image = image.convert("RGB") image.thumbnail((int(size), int(size)), Image.ANTIALIAS) image.save(thumbnail_file, THUMBNAIL_EXTENSION) except Exception as e: logger.error(e) err_msg = _('Failed to create thumbnail.') return HttpResponse(json.dumps({'err_msg': err_msg}), status=500, content_type=content_type) result['thumbnail_src'] = get_thumbnail_src(repo_id, obj_id, size) return HttpResponse(json.dumps(result), content_type=content_type)
def get(self, request, repo_id, format=None): repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) path = request.GET.get('p', None) if not path: error_msg = 'p invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: file_id = seafile_api.get_file_id_by_path(repo_id, path) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if not file_id: error_msg = 'File %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if check_folder_permission(request, repo_id, path) is None: error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # send stats message send_file_access_msg(request, repo, path, 'api') op = request.GET.get('op', 'download') if op == 'download': reuse = request.GET.get('reuse', '0') if reuse not in ('1', '0'): error_msg = "If you want to reuse file server access token for download file, you should set 'reuse' argument as '1'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) use_onetime = False if reuse == '1' else True file_name = os.path.basename(path) token = seafile_api.get_fileserver_access_token( repo_id, file_id, op, request.user.username, use_onetime) redirect_url = gen_file_get_url(token, file_name) return Response({"url": redirect_url}) elif op == 'downloadblks': blklist = [] encrypted = False enc_version = 0 if file_id != EMPTY_SHA1: try: blks = seafile_api.list_blocks_by_file_id(repo_id, file_id) blklist = blks.split('\n') except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) blklist = [i for i in blklist if len(i) == 40] if len(blklist) > 0: repo = seafile_api.get_repo(repo_id) encrypted = repo.encrypted enc_version = repo.enc_version res = { 'file_id': file_id, 'blklist': blklist, 'encrypted': encrypted, 'enc_version': enc_version, } return Response(res) elif op == 'sharelink': link = get_shared_link(request, repo_id, path) return Response({"link": link}) else: error_msg = 'op invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg)