Skip to content

Commit

Permalink
made webcam uploading work (tm)
Browse files Browse the repository at this point in the history
its a bit unstable now but it kinda works
the picture is a little small, may need to scale it better
  • Loading branch information
Jackywathy committed Feb 9, 2017
1 parent 88367ce commit 79db34c
Show file tree
Hide file tree
Showing 12 changed files with 361 additions and 145 deletions.
59 changes: 59 additions & 0 deletions back_end/Imaging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from PIL import Image
import base64
from io import BytesIO
import imghdr
import binascii

class ImageWrapper:
def __init__(self, img, type):
self.img = img
self.type = type

def __str__():
return "ImageWrapper Object of type " + self.type + "size: " + len(self.img)


INVALID_IMAGE = 'INVALID_IMAGE'
iconsize = 256

def is_image(img):
print(ImageWrapper, Image)
return (isinstance(img, ImageWrapper) and isinstance(img.img, Image.Image)) or isinstance(img, Image.Image)


def open_image(data, change_icon=False, b64=False):
"""Returns an image object, given image binary data (gotten from request.get_file) """
if b64:
try:
with open('out.txt', 'w') as f:
f.write(data[22:])
data = base64.b64decode(data[22:] if data.startswith("data:image/png;base64,") else data)
except binascii.Error:
print("unable to decode b64!")
raise
return INVALID_IMAGE

io = BytesIO(data)

with open("hi.png", 'wb') as f:
import copy
for i in (copy.deepcopy(io)):
f.write(i)

image_type = imghdr.what(io)
if image_type:
if change_icon:
return ImageWrapper(to_icon(Image.open(io)), image_type)
else:
return ImageWrapper(Image.open(io), image_type)
else:
return INVALID_IMAGE


def to_icon(img):
"""Takes an Image object, and mutates it into a thumbname with the size iconsize"""
reducerate = 1 # the ratio to times the img height and width
if max(img.height, img.width) > iconsize:
reducerate = 256 / max(img.height, img.width)

return img.resize((int(img.width*reducerate), int(img.height*reducerate)), Image.ANTIALIAS)
4 changes: 2 additions & 2 deletions back_end/ajax.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

def username_handler(request):
user = request.get_field("username")
if isinstance(user, str):
if user is not None:
valid = db_api.User.find(username=user.lower())
# checks if the user already signed up
# if there is no user, it is valid
Expand All @@ -17,7 +17,7 @@ def username_handler(request):

def email_handler(request):
email = request.get_field("email")
if isinstance(email, str):
if email is not None:
valid = db_api.User.find(email=email.lower())
valid = True if valid is None else False
request.write({"email_valid" : valid})
Expand Down
23 changes: 22 additions & 1 deletion back_end/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,27 @@
HASH_SALT = b'1U+q8L!TXEyws+5+OKEzf=q~ffCo>8-u/QJyL}cSqcg~~Ar`C{u{ZPP{Ky6M`l|b'
USER_COOKIE = "current_user"

'''
__all__ = [
'UPLOADS_DIR'
'IMAGE_DIR',
'HASH_SALT',
'USER_COOKIE',
'hash_string',
'get_upload_path',
'get_image_path',
'get_current_time',
'get_secure_username',
'fetch_file',
'get_user_picture',
'reply_malformed',
]'''


# if you add a function, dont forget to put it in the __all__
# its basically a list of all the things that get imported when you do
# from backend.common import *

def hash_string(s):
return hashlib.sha512(HASH_SALT + s.encode()).hexdigest()

Expand Down Expand Up @@ -41,4 +62,4 @@ def get_user_picture(userObj):
def reply_malformed(request, header_text="The request was malformed", text="Sorry!\n It looks like your client has sent a invalid request.\n Please reload the page or contact us."):
"""Sets the header of request to 400 (bad request) and writes the text supplied"""
request.set_status(400, header_text)
request.write(text)
request.write(text)
29 changes: 0 additions & 29 deletions back_end/image.py

This file was deleted.

83 changes: 51 additions & 32 deletions back_end/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,79 @@
from template_engine.parser import render
from back_end.common import *
from db import db_api as db
from back_end import Imaging

NOUSER_PROFILEPIC_FILENAME = 'nouser.png'

def signup_handler(request):
request.write(render('signup.html', {'signed_in':authenticate_cookie(request), 'username': get_secure_username(request), 'unsupported_file_error_msg': ''}))
ident = request.get_field('id')
username = request.get_field('username')
email = request.get_field('email')
password = request.get_field('password')
doc = request.get_field('doc')
gender = request.get_field('gender')
dob = request.get_field('dob')
if username is not None:
request.set_secure_cookie("current_user", username)


def signup_handler_post(request):
ident = request.get_field('id')
UnreadableImage = False

image_type = request.get_field('image-location')

if not image_type in ('profile_img_webcam', 'profile_img_upload', None):
print("gotten image-type", image_type)
reply_malformed(request)
return
else:
# get the image
if image_type == 'profile_img_webcam':
# webcam
print("reading from webcam")
print(request.get_field('webcam-input'))
image = Imaging.open_image(request.get_field('webcam-input'), change_icon=True, b64=True)
elif image_type == 'profile_img_upload':
# file upload
print("Reading from file upload")
image = Imaging.open_image(request.get_file('profile_picture')[2], change_icon=True, b64=False)
else:
print("No file received! img_type=", image_type)
image = None
# the picture is a ImageWrapper obj, None for no image, or Imaging.Invalid if it is invalid


username = request.get_field('username')
nickname = request.get_field('nickname')
password = hash_string(request.get_field('password'))
email = request.get_field('email')
gender = request.get_field('gender')
dob = request.get_field('dob')
profile_pic = request.get_file('profile_picture')
print(username)


if db.User.find(username=username) is not None:
request.write("username already exists!")
return
new_user = db.User.sign_up(username, password, nickname, email)

if image == Imaging.INVALID_IMAGE:
# the image was invalid! send the form back to the user and dont sign'em up
print("Image was invalid :(")
...
else:
new_user = db.User.sign_up(username, password, nickname, email)

# Validation for uploaded image
if profile_pic != (None, None, None):
filename, content_type, data = profile_pic
if content_type.startswith('image/'):
file_path_profile_pic = os.path.join('uploads', 'user_image', str(new_user.id) +'.jpg')
if image is None:
request.set_secure_cookie("current_user", username)
# no image was supplied, do nofin
request.redirect('/')

with open(os.path.join('static', file_path_profile_pic), 'wb') as f:
f.write(data)
db.User.update(new_user.id, new_user.password, new_user.nickname, new_user.email, new_user.gender, new_user.dob, new_user.bio, file_path_profile_pic)
print(new_user.picture)
request.redirect('/')
elif Imaging.is_image(image):
ext = image.type

file_path = os.path.abspath(os.path.join('static', 'uploads', 'user_image', str(new_user.id) + '.' + ext))
print("Saving img to", file_path)
image.img.save(file_path)
db.User.update_some(picture=file_path)
request.set_secure_cookie("current_user", username)
request.redirect('/')

else:
print('Uploaded file type not supported')
request.write(render('signup.html', {'signed_in':authenticate_cookie(request), 'username': get_secure_username(request), 'unsupported_file_error_msg': 'Uploaded file type not supported.'}))
else:
file_path_profile_pic = os.path.join('uploads', 'user_image', NOUSER_PROFILEPIC_FILENAME)
db.User.update(new_user.id, new_user.password, new_user.nickname, new_user.email, new_user.gender, new_user.dob, new_user.bio, file_path_profile_pic)
request.write('We couldn\'t find an uploaded file. So we\'ll assign you a default pic.')
request.redirect('/')
raise ValueError("image cannot be " + str(image))



if username is not None:
request.set_secure_cookie("current_user", username)



Expand Down
1 change: 0 additions & 1 deletion back_end/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,4 @@ def comment_handler_post(request, photo_id):
comment = user.create_comment(post, text, None, get_user_picture(user))
request.redirect("/view/" + str(photo_id))
else:

request.write("You're not logged in!")
12 changes: 11 additions & 1 deletion db/db_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,17 @@ def update(id, password, nickname, email, gender, dob, bio, picture):

@staticmethod
def update_some(**kwargs):
"""Updates one value. Use update_one(nickname='newnick',...)"""
"""
Updates one value. Use update_some(nickname='newnick',...)
Usable fields:
'password',
'nickname',
'email',
'gender',
'dob',
'picture',
'creation_date'
"""
if all((i in User.MUTABLE_COLS for i in kwargs.keys())):
# check if the columns are allowed to be altered
for key in kwargs:
Expand Down
11 changes: 8 additions & 3 deletions server.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

def index_handler(request):
posts = db.Post.find_all()
if not posts: posts=[]
if not posts: posts = []
posts = [{'image':i.file if i.file != [] else 'notfound.jpg',
'question':i.title, 'id': i.id} for i in posts]
request.write(render('index.html',
Expand Down Expand Up @@ -91,10 +91,13 @@ def validate_absolute_path(self, root, absolute_path):
render_error(self, e.status_code)
return None

def handle_favicon(request):
request.redirect('/static/images/favicon.png')

# we need to handle both errors on the default RequestHandlers (server.register(blah)) and
# also from the static RequestHandler (/static/blah)
server = Server( default_write_error=exception_handler, static_handler_class=CustomStaticFileHandler) # sets the default exception handler

server = Server(default_write_error=exception_handler, static_handler_class=CustomStaticFileHandler) # sets the default exception handler
# URL GET POST
server.register(r'/' , index_handler )
server.register(r'/view/(\d+)/?' , check_valid_question_id_handler )
Expand All @@ -110,7 +113,9 @@ def validate_absolute_path(self, root, absolute_path):
server.register(r'/ajax/user_validate' , _405_handler , post=ajax.username_handler )
server.register(r'/ajax/email_validate' , _405_handler , post=ajax.email_handler )
server.register(r'/ajax/logged_in_validate' , _405_handler , post=ajax.user_logged_in_handler)
server.register(r'/monkey' , monkey_handler)
server.register(r'/favicon.ico', handle_favicon)

server.register(r'/.+', _404_handler)

server.register(r'/monkey' , monkey_handler)
server.run()
1 change: 1 addition & 0 deletions static/js/signup.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ function openDiv(evt, idOfElement) {
// show element by setting it to block
document.getElementById(idOfElement).style.display = "block";
evt.currentTarget.className += " active";
document.getElementById("image-location").value = idOfElement;
}
Loading

0 comments on commit 79db34c

Please sign in to comment.