#!/usr/bin/python2 # Copyright 2012 Google Inc. All Rights Reserved. # Author: mrdmnd@ (Matt Redmond) # Based off of code in //depot/google3/experimental/mobile_gwp """Code to transport profile data between a user's machine and the CWP servers. Pages: "/": the main page for the app, left blank so that users cannot access the file upload but left in the code for debugging purposes "/upload": Updates the datastore with a new file. the upload depends on the format which is templated on the main page ("/") input includes: profile_data: the zipped file containing profile data board: the architecture we ran on chromeos_version: the chromeos_version "/serve": Lists all of the files in the datastore. Each line is a new entry in the datastore. The format is key~date, where key is the entry's key in the datastore and date is the file upload time and date. (Authentication Required) "/serve/([^/]+)?": For downloading a file of profile data, ([^/]+)? means any character sequence so to download the file go to '/serve/$key' where $key is the datastore key of the file you want to download. (Authentication Required) "/del/([^/]+)?": For deleting an entry in the datastore. To use go to '/del/$key' where $key is the datastore key of the entry you want to be deleted form the datastore. (Authentication Required) TODO: Add more extensive logging""" import cgi import logging import md5 import urllib from google.appengine.api import users from google.appengine.ext import db from google.appengine.ext import webapp from google.appengine.ext.webapp.util import run_wsgi_app logging.getLogger().setLevel(logging.DEBUG) class FileEntry(db.Model): profile_data = db.BlobProperty() # The profile data date = db.DateTimeProperty(auto_now_add=True) # Date it was uploaded data_md5 = db.ByteStringProperty() # md5 of the profile data board = db.StringProperty() # board arch chromeos_version = db.StringProperty() # ChromeOS version class MainPage(webapp.RequestHandler): """Main page only used as the form template, not actually displayed.""" def get(self, response=''): # pylint: disable-msg=C6409 if response: self.response.out.write('') self.response.out.write("""
""") class Upload(webapp.RequestHandler): """Handler for uploading data to the datastore, accessible by anyone.""" def post(self): # pylint: disable-msg=C6409 """Takes input based on the main page's form.""" getfile = FileEntry() f1 = self.request.get('profile_data') getfile.profile_data = db.Blob(f1) getfile.data_md5 = md5.new(f1).hexdigest() getfile.board = self.request.get('board') getfile.chromeos_version = self.request.get('chromeos_version') getfile.put() self.response.out.write(getfile.key()) #self.redirect('/') class ServeHandler(webapp.RequestHandler): """Given the entry's key in the database, output the profile data file. Only accessible from @google.com accounts.""" def get(self, resource): # pylint: disable-msg=C6409 if Authenticate(self): file_key = str(urllib.unquote(resource)) request = db.get(file_key) self.response.out.write(request.profile_data) class ListAll(webapp.RequestHandler): """Displays all files uploaded. Only accessible by @google.com accounts.""" def get(self): # pylint: disable-msg=C6409 """Displays all information in FileEntry, ~ delimited.""" if Authenticate(self): query_str = 'SELECT * FROM FileEntry ORDER BY date ASC' query = db.GqlQuery(query_str) delimiter = '~' for item in query: display_list = [item.key(), item.date, item.data_md5, item.board, item.chromeos_version] str_list = [cgi.escape(str(i)) for i in display_list] self.response.out.write(delimiter.join(str_list) + '
') class DelEntries(webapp.RequestHandler): """Deletes entries. Only accessible from @google.com accounts.""" def get(self, resource): # pylint: disable-msg=C6409 """A specific entry is deleted, when the key is given.""" if Authenticate(self): fkey = str(urllib.unquote(resource)) request = db.get(fkey) if request: db.delete(fkey) def Authenticate(webpage): """Some urls are only accessible if logged in with a @google.com account.""" user = users.get_current_user() if user is None: webpage.redirect(users.create_login_url(webpage.request.uri)) elif user.email().endswith('@google.com'): return True else: webpage.response.out.write('Not Authenticated') return False def main(): application = webapp.WSGIApplication( [ ('/', MainPage), ('/upload', Upload), ('/serve/([^/]+)?', ServeHandler), ('/serve', ListAll), ('/del/([^/]+)?', DelEntries), ], debug=False) run_wsgi_app(application) if __name__ == '__main__': main()