diff --git a/r2/r2/controllers/api.py b/r2/r2/controllers/api.py index 0cc24ddc0..38262f976 100644 --- a/r2/r2/controllers/api.py +++ b/r2/r2/controllers/api.py @@ -54,6 +54,7 @@ from r2.lib import tracking, cssfilter, emailer from r2.lib.subreddit_search import search_reddits from r2.lib.log import log_text from r2.lib.filters import safemarkdown +from r2.lib.scraper import str_to_image import csv from datetime import datetime, timedelta @@ -1129,11 +1130,13 @@ class ApiController(RedditController): return self.abort(403,'forbidden') if sponsor and c.user_is_admin: c.site.sponsorship_img = None + c.site.sponsorship_size = None c.site._commit() elif c.site.header: # reset the header image on the page jquery('#header-img').attr("src", DefaultSR.header) c.site.header = None + c.site.header_size = None c.site._commit() # hide the button which started this form.find('.delete-img').hide() @@ -1161,7 +1164,7 @@ class ApiController(RedditController): img_type = VImageType('img_type'), form_id = VLength('formid', max_length = 100), header = VInt('header', max=1, min=0), - sponsor = VInt('sponsor', max=1, min=0)) + sponsor = VSubredditSponsorship('sponsor')) def POST_upload_sr_img(self, file, header, sponsor, name, form_id, img_type): """ Called on /about/stylesheet when an image needs to be replaced @@ -1183,8 +1186,7 @@ class ApiController(RedditController): # the response if no error is raised) errors = dict(BAD_CSS_NAME = "", IMAGE_ERROR = "") add_image_to_sr = False - if sponsor and not c.user_is_admin: - return self.abort(403, 'forbidden') + size = None if not sponsor and not header: add_image_to_sr = True @@ -1193,33 +1195,32 @@ class ApiController(RedditController): # this may also fail if a sponsored image was added and the user is not an admin errors['BAD_CSS_NAME'] = _("bad image name") - if c.site.images: + if c.site.images and add_image_to_sr: if c.site.images.has_key(name): - errors['IMAGE_ERROR'] = (_("An image with that name already exists")) + errors['IMAGE_ERROR'] = _("An image with that name already exists") elif c.site.get_num_images() >= g.max_sr_images: - errors['IMAGE_ERROR'] = (_("too many images (you only get %d)") % g.max_sr_images) + errors['IMAGE_ERROR'] = _("too many images (you only get %d)") % g.max_sr_images if any(errors.values()): - return UploadedImage("", "", "", errors = errors).render() - else: - # with the image num, save the image an upload to s3. the - # header image will be of the form "${c.site._fullname}.png" - # while any other image will be ${c.site._fullname}_${resource}.png + return UploadedImage("", "", "", errors=errors).render() + else: try: - new_url = cssfilter.save_sr_image(c.site, file, suffix = '.' + img_type) + new_url = cssfilter.save_sr_image(c.site, file, suffix ='.' + img_type) except cssfilter.BadImage: errors['IMAGE_ERROR'] = _("Invalid image or general image error") - return UploadedImage("", "", "", errors = errors).render() - + return UploadedImage("", "", "", errors=errors).render() + size = str_to_image(file).size if header: c.site.header = new_url + c.site.header_size = size elif sponsor and c.user_is_admin: c.site.sponsorship_img = new_url - - c.site.add_image(name, url = new_url) + c.site.sponsorship_size = size + if add_image_to_sr: + c.site.add_image(name, url = new_url) c.site._commit() return UploadedImage(_('saved'), new_url, name, - errors = errors, form_id = form_id).render() + errors=errors, form_id=form_id).render() @validatedForm(VUser(), diff --git a/r2/r2/lib/media.py b/r2/r2/lib/media.py index f69c60e63..6ac8d72fc 100644 --- a/r2/r2/lib/media.py +++ b/r2/r2/lib/media.py @@ -52,10 +52,9 @@ MEDIA_FILENAME_LENGTH = 12 def thumbnail_url(link): """Given a link, returns the url for its thumbnail based on its fullname""" - res = str() if link.has_thumbnail: if hasattr(link, "thumbnail_url"): - res = link.thumbnail_url + return link.thumbnail_url else: bucket = g.s3_old_thumb_bucket baseurl = "http://%s" % (bucket) @@ -64,8 +63,9 @@ def thumbnail_url(link): res = '%s/%s.png' % (baseurl,link._fullname) if hasattr(link, "thumbnail_version"): res += "?v=%s" % link.thumbnail_version - - return res + return res + else: + return '' def filename_to_s3_bucket(file_name): num = ord(file_name[-1]) % len(g.s3_media_buckets) @@ -86,12 +86,12 @@ def get_filename_from_content(contents): sha = hashlib.sha1(contents).digest() return base64.urlsafe_b64encode(sha[0:MEDIA_FILENAME_LENGTH]) -def upload_media(image, never_expire = True, file_type = ".jpg"): +def upload_media(image, never_expire=True, file_type='.jpg'): """Given a link and an image, uploads the image to s3 into an image based on the link's fullname""" url = str() mime_type = mimetypes.guess_type("file" + file_type)[0] # Requires a filename with the extension - f = tempfile.NamedTemporaryFile(suffix = file_type, delete = False) + f = tempfile.NamedTemporaryFile(suffix=file_type, delete=False) try: img = image if isinstance(img, basestring): @@ -99,29 +99,32 @@ def upload_media(image, never_expire = True, file_type = ".jpg"): if not img.mode == 'RGBA': # Indexed images will not convert properly img = img.convert('RGBA') + if file_type == ".jpg": # PIL does not play nice when converting alpha channels to jpg background = Image.new('RGBA', img.size, (255, 255, 255)) background.paste(img, img) img = background.convert('RGB') img.save(f, quality=85, optimize=True) - + if file_type == ".png": optimize_png(f.name, g.png_optimizer) contents = open(f.name).read() file_name = get_filename_from_content(contents) if g.media_store == "s3": - url = s3_upload_media(contents, file_name = file_name, mime_type = mime_type, file_type = file_type, never_expire = True) + url = s3_upload_media(contents, file_name=file_name, mime_type=mime_type, file_type=file_type, never_expire=True) finally: os.unlink(f.name) return url -def update_link(link, thumbnail, media_object): +def update_link(link, thumbnail, media_object, thumbnail_size=None): """Sets the link's has_thumbnail and media_object attributes iin the database.""" if thumbnail: link.thumbnail_url = thumbnail + link.thumbnail_size = thumbnail_size + g.log.debug("Updated link with thumbnail: %s" % link.thumbnail_url) if media_object: link.media_object = media_object @@ -151,17 +154,17 @@ def set_media(link, force = False): if not res: print "%s made a bad media obj for link %s" % (scraper, link._id36) media_object = None + + thumbnail_url = upload_media(thumbnail) if thumbnail else None + thumbnail_size = thumbnail.size if thumbnail else None - if thumbnail: - thumbnail = upload_media(thumbnail) + update_link(link, thumbnail_url, media_object, thumbnail_size=thumbnail_size) - update_link(link, thumbnail, media_object) - -def force_thumbnail(link, image_data, never_expire = True, file_type=".jpg"): +def force_thumbnail(link, image_data, never_expire=True, file_type=".jpg"): image = str_to_image(image_data) image = prepare_image(image) - thumb_url = upload_media(image, never_expire = never_expire, file_type = file_type) - update_link(link, thumbnail = thumb_url, media_object = None) + thumb_url = upload_media(image, never_expire=never_expire, file_type=file_type) + update_link(link, thumbnail=thumb_url, media_object=None, thumbnail_size=image.size) def run(): def process_link(msg): diff --git a/r2/r2/lib/s3cp.py b/r2/r2/lib/s3cp.py index 3b4426e66..3e2f4549b 100644 --- a/r2/r2/lib/s3cp.py +++ b/r2/r2/lib/s3cp.py @@ -34,7 +34,7 @@ NEVER = 'Thu, 31 Dec 2037 23:59:59 GMT' class S3Exception(Exception): pass -def send_file(bucketname, filename, content, content_type = 'text/plain', never_expire = False, replace = True, reduced_redundancy = False): +def send_file(bucketname, filename, content, content_type='text/plain', never_expire=False, replace=True, reduced_redundancy=False): # this function is pretty low-traffic, but if we start using it a # lot more we'll want to maintain a connection pool across the app # rather than connecting on every invocation @@ -49,7 +49,7 @@ def send_file(bucketname, filename, content, content_type = 'text/plain', never_ if never_expire: headers['Expires'] = NEVER - k.set_contents_from_string(content, policy = 'public-read', - headers = headers, - replace = replace, - reduced_redundancy = reduced_redundancy) + k.set_contents_from_string(content, policy='public-read', + headers=headers, + replace=replace, + reduced_redundancy=reduced_redundancy) diff --git a/r2/r2/lib/template_helpers.py b/r2/r2/lib/template_helpers.py index 9f42d350b..840aa4e4f 100644 --- a/r2/r2/lib/template_helpers.py +++ b/r2/r2/lib/template_helpers.py @@ -67,6 +67,7 @@ def static(path): return os.path.join(c.site.static_path, path) + query def s3_https_if_secure(url): + # In the event that more media sources (other than s3) are added, this function should be corrected if not c.secure: return url replace = "https://" diff --git a/r2/r2/models/link.py b/r2/r2/models/link.py index db77d4b6d..9153a8e26 100644 --- a/r2/r2/models/link.py +++ b/r2/r2/models/link.py @@ -315,7 +315,7 @@ class Link(Thing, Printable): def add_props(cls, user, wrapped): from r2.lib.pages import make_link_child from r2.lib.count import incr_counts - from r2.lib.media import thumbnail_url as get_thumbnail_url + from r2.lib import media from r2.lib.utils import timeago from r2.lib.template_helpers import get_domain from r2.models.subreddit import FakeSubreddit @@ -375,7 +375,7 @@ class Link(Thing, Printable): # always show a promo author their own thumbnail if item.promoted and (user_is_admin or item.is_author) and item.has_thumbnail: - item.thumbnail = get_thumbnail_url(item) + item.thumbnail = media.thumbnail_url(item) elif user.pref_no_profanity and item.over_18 and not c.site.over_18: if show_media: item.thumbnail = "/static/nsfw2.png" @@ -384,7 +384,7 @@ class Link(Thing, Printable): elif not show_media: item.thumbnail = "" elif item.has_thumbnail: - item.thumbnail = get_thumbnail_url(item) + item.thumbnail = media.thumbnail_url(item) elif item.is_self: item.thumbnail = g.self_thumb else: diff --git a/r2/r2/models/subreddit.py b/r2/r2/models/subreddit.py index 25a95439d..ce6811474 100644 --- a/r2/r2/models/subreddit.py +++ b/r2/r2/models/subreddit.py @@ -56,6 +56,7 @@ class Subreddit(Thing, Printable): stylesheet_hash = '0', firsttext = strings.firsttext, header = None, + header_size = None, header_title = "", allow_top = False, # overridden in "_new" description = '', @@ -560,10 +561,10 @@ class Subreddit(Thing, Printable): yield (name, img) def get_num_images(self): - if self.images.has_key('/empties/'): - return len(images) - 1 + if '/empties/' in self.images: + return len(self.images) - 1 else: - return len(images) + return len(self.images) def add_image(self, name, url, max_num = None): """ @@ -578,7 +579,7 @@ class Subreddit(Thing, Printable): The Subreddit will be _dirty if a new image has been added to its images list, and no _commit is called. """ - if(max_num is not None and self.get_num_images() >= max_num): + if max_num is not None and self.get_num_images() >= max_num: raise ValueError, "too many images" if not self.images.has_key(name): diff --git a/r2/r2/templates/createsubreddit.html b/r2/r2/templates/createsubreddit.html index 7eacffb1b..0e2364968 100644 --- a/r2/r2/templates/createsubreddit.html +++ b/r2/r2/templates/createsubreddit.html @@ -216,7 +216,7 @@ <%utils:image_upload post_target="/api/upload_sr_img" current_image="${thing.site.header}" label="${_('upload header image')}" - ask_type="True"> + ask_type="${True}">