diff --git a/seahub/api2/urls.py b/seahub/api2/urls.py index 264d8431dc..f7daff8183 100644 --- a/seahub/api2/urls.py +++ b/seahub/api2/urls.py @@ -68,3 +68,18 @@ urlpatterns = patterns('', url(r'^repos/(?P[-0-9-a-f]{36})/fileops/copy/$', OpCopyView.as_view()), url(r'^repos/(?P[-0-9-a-f]{36})/fileops/move/$', OpMoveView.as_view()), ) + +# serve office converter static files +from seahub.utils import HAS_OFFICE_CONVERTER +if HAS_OFFICE_CONVERTER: + from seahub.utils import OFFICE_HTML_DIR + urlpatterns += patterns('', + url(r'^office-convert/static/(?P.*)$', 'django.views.static.serve', {'document_root': OFFICE_HTML_DIR}, name='api_office_convert_static'), + ) + urlpatterns += patterns('', + url(r'^office-convert/status/$', OfficeConvertQueryStatus.as_view()), + url(r'^office-convert/page-num/$', OfficeConvertQueryPageNum.as_view()), + ) + urlpatterns += patterns('', + url(r'^office-convert/generate/repos/(?P[-0-9-a-f]{36})/$', OfficeGenerateView.as_view()), + ) diff --git a/seahub/api2/views.py b/seahub/api2/views.py index deca55781e..ef335885fb 100644 --- a/seahub/api2/views.py +++ b/seahub/api2/views.py @@ -74,7 +74,13 @@ from seaserv import seafserv_rpc, seafserv_threaded_rpc, server_repo_size, \ get_user_share_usage, get_user_quota_usage, CALC_SHARE_USAGE, get_group, \ get_commit, get_file_id_by_path, MAX_DOWNLOAD_DIR_SIZE from seaserv import seafile_api - +from seahub.views.file import get_file_view_path_and_perm +from seahub.utils.file_types import (IMAGE, PDF, IMAGE, DOCUMENT, MARKDOWN, \ + TEXT, SF) +from seahub.utils import HAS_OFFICE_CONVERTER +if HAS_OFFICE_CONVERTER: + from seahub.utils import query_office_convert_status, query_office_file_pages, \ + prepare_converted_html, OFFICE_PREVIEW_MAX_SIZE, OFFICE_PREVIEW_MAX_PAGES logger = logging.getLogger(__name__) json_content_type = 'application/json; charset=utf-8' @@ -2558,6 +2564,126 @@ class RepoHistoryChangeHtml(APIView): def get(self, request, repo_id, format=None): return api_repo_history_changes (request, repo_id) +# based on views/file.py::office_convert_query_status +class OfficeConvertQueryStatus(APIView): + authentication_classes = (TokenAuthentication, ) + permission_classes = (IsAuthenticated, ) + throttle_classes = (UserRateThrottle, ) + + def get(self, request, format=None): + if not HAS_OFFICE_CONVERTER: + return api_error(status.HTTP_404_NOT_FOUND, 'Office converter not enabled.') + + content_type = 'application/json; charset=utf-8' + + ret = {'success': False} + + file_id = request.GET.get('file_id', '') + if len(file_id) != 40: + ret['error'] = 'invalid param' + else: + try: + d = query_office_convert_status(file_id) + if d.error: + ret['error'] = d.error + else: + ret['success'] = True + ret['status'] = d.status + except Exception, e: + logging.exception('failed to call query_office_convert_status') + ret['error'] = str(e) + + return HttpResponse(json.dumps(ret), content_type=content_type) + +# based on views/file.py::office_convert_query_page_num +class OfficeConvertQueryPageNum(APIView): + authentication_classes = (TokenAuthentication, ) + permission_classes = (IsAuthenticated, ) + throttle_classes = (UserRateThrottle, ) + + def get(self, request, format=None): + if not HAS_OFFICE_CONVERTER: + return api_error(status.HTTP_404_NOT_FOUND, 'Office converter not enabled.') + + content_type = 'application/json; charset=utf-8' + + ret = {'success': False} + + file_id = request.GET.get('file_id', '') + if len(file_id) != 40: + ret['error'] = 'invalid param' + else: + try: + d = query_office_file_pages(file_id) + if d.error: + ret['error'] = d.error + else: + ret['success'] = True + ret['count'] = d.count + except Exception, e: + logging.exception('failed to call query_office_file_pages') + ret['error'] = str(e) + + return HttpResponse(json.dumps(ret), content_type=content_type) + +# based on views/file.py::view_file and views/file.py::handle_document +class OfficeGenerateView(APIView): + authentication_classes = (TokenAuthentication, ) + permission_classes = (IsAuthenticated, ) + throttle_classes = (UserRateThrottle, ) + + def get(self, request, repo_id, format=None): + username = request.user.username + # check arguments + repo = get_repo(repo_id) + if not repo: + return api_error(status.HTTP_404_NOT_FOUND, 'Repo not found.') + + + path = request.GET.get('p', '/').rstrip('/') + commit_id = request.GET.get('commit_id', None) + + if commit_id: + try: + obj_id = seafserv_threaded_rpc.get_file_id_by_commit_and_path( \ + commit_id, path) + except: + return api_error(status.HTTP_404_NOT_FOUND, 'Revision not found.') + else: + try: + obj_id = seafile_api.get_file_id_by_path(repo_id, + path.encode('utf-8')) + except: + return api_error(status.HTTP_404_NOT_FOUND, 'File not found.') + + if not obj_id: + return api_error(status.HTTP_404_NOT_FOUND, 'File not found.') + + # Check whether user has permission to view file and get file raw path, + # render error page if permission deny. + raw_path, inner_path, user_perm = get_file_view_path_and_perm(request, + repo_id, + obj_id, path) + + if not user_perm: + return api_error(status.HTTP_403_FORBIDDEN, 'You do not have permission to view this file.') + + u_filename = os.path.basename(path) + filetype, fileext = get_file_type_and_ext(u_filename) + if filetype != DOCUMENT: + return api_error(status.HTTP_400_BAD_REQUEST, 'File is not a convertable document') + + ret_dict = {} + if HAS_OFFICE_CONVERTER: + err, html_exists = prepare_converted_html(inner_path, obj_id, fileext, ret_dict) + # populate return value dict + ret_dict['err'] = err + ret_dict['html_exists'] = html_exists + ret_dict['obj_id'] = obj_id + else: + ret_dict['filetype'] = 'Unknown' + + return HttpResponse(json.dumps(ret_dict), status=200, content_type=json_content_type) #Following is only for debug from seahub.auth.decorators import login_required