1# Copyright (c) 2012-2016 Seafile Ltd. 2import os 3import json 4import logging 5import posixpath 6import datetime 7 8from django.utils.translation import ugettext as _ 9from django.utils.http import urlquote 10from django.http import HttpResponse 11from django.views.decorators.http import condition 12from django.shortcuts import render 13 14from seaserv import get_repo, get_file_id_by_path 15 16from seahub.auth.decorators import login_required_ajax, login_required 17from seahub.views import check_folder_permission 18from seahub.settings import THUMBNAIL_DEFAULT_SIZE, THUMBNAIL_EXTENSION, \ 19 THUMBNAIL_ROOT, ENABLE_THUMBNAIL 20from seahub.thumbnail.utils import generate_thumbnail, \ 21 get_thumbnail_src, get_share_link_thumbnail_src 22from seahub.share.models import FileShare, check_share_link_common 23 24# Get an instance of a logger 25logger = logging.getLogger(__name__) 26 27@login_required_ajax 28def thumbnail_create(request, repo_id): 29 """create thumbnail from repo file list 30 31 return thumbnail src 32 """ 33 34 content_type = 'application/json; charset=utf-8' 35 result = {} 36 37 repo = get_repo(repo_id) 38 if not repo: 39 err_msg = _("Library does not exist.") 40 return HttpResponse(json.dumps({"error": err_msg}), status=400, 41 content_type=content_type) 42 43 path = request.GET.get('path', None) 44 if not path: 45 err_msg = _("Invalid arguments.") 46 return HttpResponse(json.dumps({"error": err_msg}), status=400, 47 content_type=content_type) 48 49 if repo.encrypted or not ENABLE_THUMBNAIL or \ 50 check_folder_permission(request, repo_id, path) is None: 51 err_msg = _("Permission denied.") 52 return HttpResponse(json.dumps({"error": err_msg}), status=403, 53 content_type=content_type) 54 55 size = request.GET.get('size', THUMBNAIL_DEFAULT_SIZE) 56 success, status_code = generate_thumbnail(request, repo_id, size, path) 57 if success: 58 src = get_thumbnail_src(repo_id, size, path) 59 result['encoded_thumbnail_src'] = urlquote(src) 60 return HttpResponse(json.dumps(result), content_type=content_type) 61 else: 62 err_msg = _('Failed to create thumbnail.') 63 return HttpResponse(json.dumps({'err_msg': err_msg}), 64 status=status_code, content_type=content_type) 65 66def latest_entry(request, repo_id, size, path): 67 obj_id = get_file_id_by_path(repo_id, path) 68 if obj_id: 69 try: 70 thumbnail_file = os.path.join(THUMBNAIL_ROOT, str(size), obj_id) 71 last_modified_time = os.path.getmtime(thumbnail_file) 72 # convert float to datatime obj 73 return datetime.datetime.fromtimestamp(last_modified_time) 74 except os.error: 75 # no thumbnail file exists 76 return None 77 except Exception as e: 78 # catch all other errors 79 logger.error(e, exc_info=True) 80 return None 81 else: 82 return None 83 84@login_required 85@condition(last_modified_func=latest_entry) 86def thumbnail_get(request, repo_id, size, path): 87 """ handle thumbnail src from repo file list 88 89 return thumbnail file to web 90 """ 91 92 repo = get_repo(repo_id) 93 obj_id = get_file_id_by_path(repo_id, path) 94 95 # check if file exist 96 if not repo or not obj_id: 97 return HttpResponse() 98 99 # check if is allowed 100 if repo.encrypted or not ENABLE_THUMBNAIL or \ 101 check_folder_permission(request, repo_id, path) is None: 102 return HttpResponse() 103 104 try: 105 size = int(size) 106 except ValueError as e: 107 logger.error(e) 108 return HttpResponse() 109 110 success = True 111 thumbnail_file = os.path.join(THUMBNAIL_ROOT, str(size), obj_id) 112 if not os.path.exists(thumbnail_file): 113 success, status_code = generate_thumbnail(request, repo_id, size, path) 114 115 if success: 116 try: 117 with open(thumbnail_file, 'rb') as f: 118 thumbnail = f.read() 119 return HttpResponse(content=thumbnail, 120 content_type='image/' + THUMBNAIL_EXTENSION) 121 except IOError as e: 122 logger.error(e) 123 return HttpResponse(status=500) 124 else: 125 return HttpResponse(status=status_code) 126 127def get_real_path_by_fs_and_req_path(fileshare, req_path): 128 """ Return the real path of a file. 129 130 The file could be a file in a shared dir or a shared file. 131 """ 132 133 if fileshare.s_type == 'd': 134 if fileshare.path == '/': 135 real_path = req_path 136 else: 137 real_path = posixpath.join(fileshare.path, req_path.lstrip('/')) 138 else: 139 real_path = fileshare.path 140 141 return real_path 142 143def share_link_thumbnail_create(request, token): 144 """generate thumbnail from dir download link page 145 146 return thumbnail src to web 147 """ 148 149 content_type = 'application/json; charset=utf-8' 150 result = {} 151 152 fileshare = FileShare.objects.get_valid_file_link_by_token(token) 153 if not fileshare: 154 err_msg = _("Invalid token.") 155 return HttpResponse(json.dumps({"error": err_msg}), status=400, 156 content_type=content_type) 157 158 repo_id = fileshare.repo_id 159 repo = get_repo(repo_id) 160 if not repo: 161 err_msg = _("Library does not exist.") 162 return HttpResponse(json.dumps({"error": err_msg}), status=400, 163 content_type=content_type) 164 165 if repo.encrypted or not ENABLE_THUMBNAIL: 166 err_msg = _("Permission denied.") 167 return HttpResponse(json.dumps({"error": err_msg}), status=403, 168 content_type=content_type) 169 170 req_path = request.GET.get('path', None) 171 if not req_path or '../' in req_path: 172 err_msg = _("Invalid arguments.") 173 return HttpResponse(json.dumps({"error": err_msg}), status=400, 174 content_type=content_type) 175 176 real_path = get_real_path_by_fs_and_req_path(fileshare, req_path) 177 178 size = request.GET.get('size', THUMBNAIL_DEFAULT_SIZE) 179 success, status_code = generate_thumbnail(request, repo_id, size, real_path) 180 if success: 181 src = get_share_link_thumbnail_src(token, size, req_path) 182 result['encoded_thumbnail_src'] = urlquote(src) 183 return HttpResponse(json.dumps(result), content_type=content_type) 184 else: 185 err_msg = _('Failed to create thumbnail.') 186 return HttpResponse(json.dumps({'err_msg': err_msg}), 187 status=status_code, content_type=content_type) 188 189def share_link_latest_entry(request, token, size, path): 190 fileshare = FileShare.objects.get_valid_file_link_by_token(token) 191 if not fileshare: 192 return None 193 194 repo_id = fileshare.repo_id 195 repo = get_repo(repo_id) 196 if not repo: 197 return None 198 199 image_path = get_real_path_by_fs_and_req_path(fileshare, path) 200 201 obj_id = get_file_id_by_path(repo_id, image_path) 202 if obj_id: 203 try: 204 thumbnail_file = os.path.join(THUMBNAIL_ROOT, str(size), obj_id) 205 last_modified_time = os.path.getmtime(thumbnail_file) 206 # convert float to datatime obj 207 return datetime.datetime.fromtimestamp(last_modified_time) 208 except Exception as e: 209 logger.error(e) 210 # no thumbnail file exists 211 return None 212 else: 213 return None 214 215@condition(last_modified_func=share_link_latest_entry) 216def share_link_thumbnail_get(request, token, size, path): 217 """ handle thumbnail src from dir download link page 218 219 return thumbnail file to web 220 """ 221 222 try: 223 size = int(size) 224 except ValueError as e: 225 logger.error(e) 226 return HttpResponse() 227 228 fileshare = FileShare.objects.get_valid_file_link_by_token(token) 229 if not fileshare: 230 return HttpResponse() 231 232 password_check_passed, err_msg = check_share_link_common(request, fileshare) 233 if not password_check_passed: 234 d = {'token': token, 'view_name': 'view_shared_dir', 'err_msg': err_msg} 235 return render(request, 'share_access_validation.html', d) 236 237 image_path = get_real_path_by_fs_and_req_path(fileshare, path) 238 239 repo_id = fileshare.repo_id 240 repo = get_repo(repo_id) 241 obj_id = get_file_id_by_path(repo_id, image_path) 242 243 # check if file exist 244 if not repo or not obj_id: 245 return HttpResponse() 246 247 # check if is allowed 248 if repo.encrypted or not ENABLE_THUMBNAIL: 249 return HttpResponse() 250 251 success = True 252 thumbnail_file = os.path.join(THUMBNAIL_ROOT, str(size), obj_id) 253 if not os.path.exists(thumbnail_file): 254 success, status_code = generate_thumbnail(request, repo_id, size, image_path) 255 256 if success: 257 try: 258 with open(thumbnail_file, 'rb') as f: 259 thumbnail = f.read() 260 return HttpResponse(content=thumbnail, 261 content_type='image/' + THUMBNAIL_EXTENSION) 262 except IOError as e: 263 logger.error(e) 264 return HttpResponse() 265 else: 266 return HttpResponse() 267