Commit f3572c71 by Vik Paruchuri

Fix image checking logic

parent 42b9a121
...@@ -39,7 +39,7 @@ MAX_SCORE = 1 ...@@ -39,7 +39,7 @@ MAX_SCORE = 1
MAX_SCORE_ALLOWED = 3 MAX_SCORE_ALLOWED = 3
IS_SCORED = False IS_SCORED = False
ACCEPT_FILE_UPLOAD = False ACCEPT_FILE_UPLOAD = True
#Contains all reasonable bool and case combinations of True #Contains all reasonable bool and case combinations of True
TRUE_DICT = ["True", True, "TRUE", "true"] TRUE_DICT = ["True", True, "TRUE", "true"]
......
...@@ -3,7 +3,12 @@ This contains functions and classes used to evaluate if images are acceptable (d ...@@ -3,7 +3,12 @@ This contains functions and classes used to evaluate if images are acceptable (d
to send them to S3. to send them to S3.
""" """
from PIL import Image try:
from PIL import Image
ENABLE_PIL = True
except:
ENABLE_PIL = False
from urlparse import urlparse from urlparse import urlparse
import requests import requests
from boto.s3.connection import S3Connection from boto.s3.connection import S3Connection
...@@ -46,13 +51,13 @@ class ImageProperties(object): ...@@ -46,13 +51,13 @@ class ImageProperties(object):
""" """
Class to check properties of an image and to validate if they are allowed. Class to check properties of an image and to validate if they are allowed.
""" """
def __init__(self, image): def __init__(self, image_data):
""" """
Initializes class variables Initializes class variables
@param image: Image object (from PIL) @param image: Image object (from PIL)
@return: None @return: None
""" """
self.image = image self.image = Image.open(image_data)
image_size = self.image.size image_size = self.image.size
self.image_too_large = False self.image_too_large = False
if image_size[0] > MAX_ALLOWED_IMAGE_DIM or image_size[1] > MAX_ALLOWED_IMAGE_DIM: if image_size[0] > MAX_ALLOWED_IMAGE_DIM or image_size[1] > MAX_ALLOWED_IMAGE_DIM:
...@@ -158,10 +163,6 @@ class URLProperties(object): ...@@ -158,10 +163,6 @@ class URLProperties(object):
@return: True if URL passes tests, false if not. @return: True if URL passes tests, false if not.
""" """
url_is_okay = self.check_suffix() and self.check_if_parses() and self.check_domain() url_is_okay = self.check_suffix() and self.check_if_parses() and self.check_domain()
log.debug(self.url_string)
log.debug("Suffix : {0}".format(self.check_suffix()))
log.debug("Parses:{0}".format(self.check_if_parses()))
log.debug("Check Domain:{0}".format(self.check_domain()))
return url_is_okay return url_is_okay
def check_domain(self): def check_domain(self):
...@@ -191,8 +192,14 @@ def run_image_tests(image): ...@@ -191,8 +192,14 @@ def run_image_tests(image):
@param image: PIL Image object @param image: PIL Image object
@return: Boolean indicating whether or not all tests have been passed @return: Boolean indicating whether or not all tests have been passed
""" """
image_properties = ImageProperties(image) success = False
return image_properties.run_tests() try:
image_properties = ImageProperties(image)
success = image_properties.run_tests()
except:
log.exception("Cannot run image tests in combined open ended xmodule. May be an issue with a particular image,"
"or an issue with the deployment configuration of PIL/Pillow")
return success
def upload_to_s3(file_to_upload, keyname): def upload_to_s3(file_to_upload, keyname):
......
...@@ -27,8 +27,6 @@ import open_ended_image_submission ...@@ -27,8 +27,6 @@ import open_ended_image_submission
from datetime import datetime from datetime import datetime
from PIL import Image
log = logging.getLogger("mitx.courseware") log = logging.getLogger("mitx.courseware")
# Set the default number of max attempts. Should be 1 for production # Set the default number of max attempts. Should be 1 for production
...@@ -290,25 +288,20 @@ class OpenEndedChild(object): ...@@ -290,25 +288,20 @@ class OpenEndedChild(object):
s3_public_url = "" s3_public_url = ""
try: try:
image_data.seek(0) image_data.seek(0)
image = Image.open(image_data) image_ok = open_ended_image_submission.run_image_tests(image_data)
image_ok = open_ended_image_submission.run_image_tests(image)
log.debug("Image ok: {0}".format(image_ok))
success = True
except: except:
log.exception("Could not create image and check it.") log.exception("Could not create image and check it.")
if success and image_ok: if image_ok:
image_key = image_data.name + datetime.now().strftime("%Y%m%d%H%M%S") image_key = image_data.name + datetime.now().strftime("%Y%m%d%H%M%S")
try: try:
image_data.seek(0) image_data.seek(0)
success, s3_public_url = open_ended_image_submission.upload_to_s3(image_data, image_key) success, s3_public_url = open_ended_image_submission.upload_to_s3(image_data, image_key)
except: except:
success = False
log.exception("Could not upload image to S3.") log.exception("Could not upload image to S3.")
log.debug(s3_public_url) return success, image_ok, s3_public_url
return success, s3_public_url
def check_for_image_and_upload(self, get_data): def check_for_image_and_upload(self, get_data):
""" """
...@@ -320,15 +313,16 @@ class OpenEndedChild(object): ...@@ -320,15 +313,16 @@ class OpenEndedChild(object):
has_file_to_upload = False has_file_to_upload = False
uploaded_to_s3 = False uploaded_to_s3 = False
image_tag = "" image_tag = ""
image_ok = False
if 'can_upload_files' in get_data: if 'can_upload_files' in get_data:
if get_data['can_upload_files'] == 'true': if get_data['can_upload_files'] == 'true':
has_file_to_upload = True has_file_to_upload = True
file = get_data['student_file'][0] file = get_data['student_file'][0]
uploaded_to_s3, s3_public_url = self.upload_image_to_s3(file) uploaded_to_s3, image_ok, s3_public_url = self.upload_image_to_s3(file)
if uploaded_to_s3: if uploaded_to_s3:
image_tag = self.generate_image_tag_from_url(s3_public_url, file.name) image_tag = self.generate_image_tag_from_url(s3_public_url, file.name)
return has_file_to_upload, uploaded_to_s3, image_tag return has_file_to_upload, uploaded_to_s3, image_ok, image_tag
def generate_image_tag_from_url(self, s3_public_url, image_name): def generate_image_tag_from_url(self, s3_public_url, image_name):
""" """
...@@ -353,11 +347,11 @@ class OpenEndedChild(object): ...@@ -353,11 +347,11 @@ class OpenEndedChild(object):
#If the question does not accept file uploads, do not do anything #If the question does not accept file uploads, do not do anything
return True, get_data return True, get_data
has_file_to_upload, uploaded_to_s3, image_tag = self.check_for_image_and_upload(get_data) has_file_to_upload, uploaded_to_s3, image_ok, image_tag = self.check_for_image_and_upload(get_data)
if uploaded_to_s3 and has_file_to_upload: if uploaded_to_s3 and has_file_to_upload:
get_data['student_answer'] += image_tag get_data['student_answer'] += image_tag
overall_success = True overall_success = True
elif has_file_to_upload and not uploaded_to_s3: elif has_file_to_upload and not uploaded_to_s3 and image_ok:
#In this case, an image was submitted by the student, but the image could not be uploaded to S3. Likely #In this case, an image was submitted by the student, but the image could not be uploaded to S3. Likely
#a config issue (development vs deployment). For now, just treat this as a "success" #a config issue (development vs deployment). For now, just treat this as a "success"
log.warning("Student AJAX post to combined open ended xmodule indicated that it contained an image, " log.warning("Student AJAX post to combined open ended xmodule indicated that it contained an image, "
...@@ -365,7 +359,7 @@ class OpenEndedChild(object): ...@@ -365,7 +359,7 @@ class OpenEndedChild(object):
"issue with this deployment, but it could also indicate a problem with S3 or with the" "issue with this deployment, but it could also indicate a problem with S3 or with the"
"student image itself.") "student image itself.")
overall_success = True overall_success = True
else: elif not has_file_to_upload:
#If there is no file to upload, probably the student has embedded the link in the answer text #If there is no file to upload, probably the student has embedded the link in the answer text
success, get_data['student_answer'] = self.check_for_url_in_text(get_data['student_answer']) success, get_data['student_answer'] = self.check_for_url_in_text(get_data['student_answer'])
overall_success = success overall_success = success
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment