diff options
author | Mike Macgirvin <mike@macgirvin.com> | 2018-10-31 15:56:08 +1100 |
---|---|---|
committer | Mike Macgirvin <mike@macgirvin.com> | 2018-10-31 15:56:08 +1100 |
commit | 7e1f431eca7a8aa68fc0badfaa88e88de3ba094c (patch) | |
tree | 16beba352cd4ace4aa6eb13c7f9c1c82c92013b4 /library/blueimp_upload/server/gae-python/main.py | |
parent | 70c55da1df69d90dcbeb5a78c994b23a8456bfc9 (diff) | |
download | volse-hubzilla-7e1f431eca7a8aa68fc0badfaa88e88de3ba094c.tar.gz volse-hubzilla-7e1f431eca7a8aa68fc0badfaa88e88de3ba094c.tar.bz2 volse-hubzilla-7e1f431eca7a8aa68fc0badfaa88e88de3ba094c.zip |
yet another blueimp vulnerability. Move to composer.
Diffstat (limited to 'library/blueimp_upload/server/gae-python/main.py')
-rw-r--r-- | library/blueimp_upload/server/gae-python/main.py | 204 |
1 files changed, 0 insertions, 204 deletions
diff --git a/library/blueimp_upload/server/gae-python/main.py b/library/blueimp_upload/server/gae-python/main.py deleted file mode 100644 index 1955ac00a..000000000 --- a/library/blueimp_upload/server/gae-python/main.py +++ /dev/null @@ -1,204 +0,0 @@ -# -*- coding: utf-8 -*- -# -# jQuery File Upload Plugin GAE Python Example -# https://github.com/blueimp/jQuery-File-Upload -# -# Copyright 2011, Sebastian Tschan -# https://blueimp.net -# -# Licensed under the MIT license: -# https://opensource.org/licenses/MIT -# - -from google.appengine.api import memcache, images -import json -import os -import re -import urllib -import webapp2 - -DEBUG=os.environ.get('SERVER_SOFTWARE', '').startswith('Dev') -WEBSITE = 'https://blueimp.github.io/jQuery-File-Upload/' -MIN_FILE_SIZE = 1 # bytes -# Max file size is memcache limit (1MB) minus key size minus overhead: -MAX_FILE_SIZE = 999000 # bytes -IMAGE_TYPES = re.compile('image/(gif|p?jpeg|(x-)?png)') -ACCEPT_FILE_TYPES = IMAGE_TYPES -THUMB_MAX_WIDTH = 80 -THUMB_MAX_HEIGHT = 80 -THUMB_SUFFIX = '.'+str(THUMB_MAX_WIDTH)+'x'+str(THUMB_MAX_HEIGHT)+'.png' -EXPIRATION_TIME = 300 # seconds -# If set to None, only allow redirects to the referer protocol+host. -# Set to a regexp for custom pattern matching against the redirect value: -REDIRECT_ALLOW_TARGET = None - -class CORSHandler(webapp2.RequestHandler): - def cors(self): - headers = self.response.headers - headers['Access-Control-Allow-Origin'] = '*' - headers['Access-Control-Allow-Methods'] =\ - 'OPTIONS, HEAD, GET, POST, DELETE' - headers['Access-Control-Allow-Headers'] =\ - 'Content-Type, Content-Range, Content-Disposition' - - def initialize(self, request, response): - super(CORSHandler, self).initialize(request, response) - self.cors() - - def json_stringify(self, obj): - return json.dumps(obj, separators=(',', ':')) - - def options(self, *args, **kwargs): - pass - -class UploadHandler(CORSHandler): - def validate(self, file): - if file['size'] < MIN_FILE_SIZE: - file['error'] = 'File is too small' - elif file['size'] > MAX_FILE_SIZE: - file['error'] = 'File is too big' - elif not ACCEPT_FILE_TYPES.match(file['type']): - file['error'] = 'Filetype not allowed' - else: - return True - return False - - def validate_redirect(self, redirect): - if redirect: - if REDIRECT_ALLOW_TARGET: - return REDIRECT_ALLOW_TARGET.match(redirect) - referer = self.request.headers['referer'] - if referer: - from urlparse import urlparse - parts = urlparse(referer) - redirect_allow_target = '^' + re.escape( - parts.scheme + '://' + parts.netloc + '/' - ) - return re.match(redirect_allow_target, redirect) - return False - - def get_file_size(self, file): - file.seek(0, 2) # Seek to the end of the file - size = file.tell() # Get the position of EOF - file.seek(0) # Reset the file position to the beginning - return size - - def write_blob(self, data, info): - key = urllib.quote(info['type'].encode('utf-8'), '') +\ - '/' + str(hash(data)) +\ - '/' + urllib.quote(info['name'].encode('utf-8'), '') - try: - memcache.set(key, data, time=EXPIRATION_TIME) - except: #Failed to add to memcache - return (None, None) - thumbnail_key = None - if IMAGE_TYPES.match(info['type']): - try: - img = images.Image(image_data=data) - img.resize( - width=THUMB_MAX_WIDTH, - height=THUMB_MAX_HEIGHT - ) - thumbnail_data = img.execute_transforms() - thumbnail_key = key + THUMB_SUFFIX - memcache.set( - thumbnail_key, - thumbnail_data, - time=EXPIRATION_TIME - ) - except: #Failed to resize Image or add to memcache - thumbnail_key = None - return (key, thumbnail_key) - - def handle_upload(self): - results = [] - for name, fieldStorage in self.request.POST.items(): - if type(fieldStorage) is unicode: - continue - result = {} - result['name'] = urllib.unquote(fieldStorage.filename) - result['type'] = fieldStorage.type - result['size'] = self.get_file_size(fieldStorage.file) - if self.validate(result): - key, thumbnail_key = self.write_blob( - fieldStorage.value, - result - ) - if key is not None: - result['url'] = self.request.host_url + '/' + key - result['deleteUrl'] = result['url'] - result['deleteType'] = 'DELETE' - if thumbnail_key is not None: - result['thumbnailUrl'] = self.request.host_url +\ - '/' + thumbnail_key - else: - result['error'] = 'Failed to store uploaded file.' - results.append(result) - return results - - def head(self): - pass - - def get(self): - self.redirect(WEBSITE) - - def post(self): - if (self.request.get('_method') == 'DELETE'): - return self.delete() - result = {'files': self.handle_upload()} - s = self.json_stringify(result) - redirect = self.request.get('redirect') - if self.validate_redirect(redirect): - return self.redirect(str( - redirect.replace('%s', urllib.quote(s, ''), 1) - )) - if 'application/json' in self.request.headers.get('Accept'): - self.response.headers['Content-Type'] = 'application/json' - self.response.write(s) - -class FileHandler(CORSHandler): - def normalize(self, str): - return urllib.quote(urllib.unquote(str), '') - - def get(self, content_type, data_hash, file_name): - content_type = self.normalize(content_type) - file_name = self.normalize(file_name) - key = content_type + '/' + data_hash + '/' + file_name - data = memcache.get(key) - if data is None: - return self.error(404) - # Prevent browsers from MIME-sniffing the content-type: - self.response.headers['X-Content-Type-Options'] = 'nosniff' - content_type = urllib.unquote(content_type) - if not IMAGE_TYPES.match(content_type): - # Force a download dialog for non-image types: - content_type = 'application/octet-stream' - elif file_name.endswith(THUMB_SUFFIX): - content_type = 'image/png' - self.response.headers['Content-Type'] = content_type - # Cache for the expiration time: - self.response.headers['Cache-Control'] = 'public,max-age=%d' \ - % EXPIRATION_TIME - self.response.write(data) - - def delete(self, content_type, data_hash, file_name): - content_type = self.normalize(content_type) - file_name = self.normalize(file_name) - key = content_type + '/' + data_hash + '/' + file_name - result = {key: memcache.delete(key)} - content_type = urllib.unquote(content_type) - if IMAGE_TYPES.match(content_type): - thumbnail_key = key + THUMB_SUFFIX - result[thumbnail_key] = memcache.delete(thumbnail_key) - if 'application/json' in self.request.headers.get('Accept'): - self.response.headers['Content-Type'] = 'application/json' - s = self.json_stringify(result) - self.response.write(s) - -app = webapp2.WSGIApplication( - [ - ('/', UploadHandler), - ('/(.+)/([^/]+)/([^/]+)', FileHandler) - ], - debug=DEBUG -) |