Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hw12 #101

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open

Hw12 #101

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
76 changes: 76 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,79 @@
2014-01-07 Titus Brown <[email protected]>

* Initialized repository, created server.py and README.

2014-01-15 Jenny <[email protected]>

* Deleted previous c.send lines and replaced with HTTP response msg

2014-01-23 Jenny <[email protected]>

* Added Test file from ctb cse491 github hw2
* Broke code into functions, and then expanded functions
* Handles POST and GET requests
* Test functions for each case

2014-02-12 Jenny <[email protected]>
*Templates
*Fixed previous problems.


* PROJECT: Add a URL that provides a list of images, resized to thumbnails (you can just img size, not
actual resizing – that will be a separate project ;).

- Summary: There's a link on the index page to see a list of all the images that were uploaded. It shows
the most recently updated image first.

- I added a check in get_image_raw() to see if the request included a query parameter "num". If so,
rather than getting the most recent image, it gets the image at images[num]. I also added a method to
return the count of images. Using these two things, I can make a few ajax calls in the image list page
to iterate over images and display every image.

* PROJECT: Add the ability to comment on images
- You can post a comment on an image from the /image page.

- I made an Image class that has a list of comments for that string.

- A request to the get_comments url provided an image number returns XML containing all of its comments.
If the image number is not included it defaults to the latest image

* PROJECT: Add url handler to refer to each image by its number.
- /image_raw?imageNum=# will return the image with num = #.

- If # is not numeric, or is off the end of the list, it defaults to the latest image.

- If you go to the images list ( /image_list ) each image is a link to the URL for that image (so the
second to the bottom image links to /image?imageNum=1 for example)

* Implement cookie app
* Utilize SQLite to store images
* PROJECT: Add data persistence in sqlite

- I decided to expand on the SQLite stuff and utilize SQlite to store my
comments and other stuff as well. It's an actual website now omg. :)

* PROJECT: Add starring, ranking, and a simple recommendation system for
your image app image list.

- I added a field in the image_store table to hold the image's score.

- On the image page you can upvote/downvote images. Once I have
authentication I can change this so each user can only upvote/downvote
once. For now, you can just click it as much as you want.

* PROJECT: Swipe a template from oswd.org and put it in place on your
imageapp server.


- I reference the css file in base.html, so it is referenced in all pages.

* PROJECT: Implement AJAX image upload with JQuery.

- I replaced upload2 because I hated it and never used it with the ajax
upload, and changed the title to reflect that.

- When you upload the image, it will show the uploaded image on that page,
put it in the database, and display a success message. If it fails an
error message appears.

I kind of just copied some of this. Sorry.
144 changes: 144 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# from http://docs.python.org/2/library/wsgiref.html

import cgi
import urlparse
import jinja2
from wsgiref.util import setup_testing_defaults
from StringIO import StringIO

def app(environ, start_response):
loader = jinja2.FileSystemLoader('./templates')
env = jinja2.Environment(loader=loader)

# By default, set up the 404 page response. If it's
# a valid page, we change this. If some weird stuff
# happens, it'll default to 404.
status = '404 Not Found'
response_content = not_found('', env)
headers = [('Content-type', 'text/html')]

try:
http_method = environ['REQUEST_METHOD']
path = environ['PATH_INFO']
except:
pass

if http_method == 'POST':
if path == '/':
# I feel like there's a better way of doing this
# than spamming status = '200 OK'. But it's almost 10
# and we have to catch up because our capstone group
# member just didn't do anything the past week. /rant
status = '200 OK'
response_content = handle_index(environ, env)
elif path == '/submit':
status = '200 OK'
response_content = handle_submit_post(environ, env)
elif http_method == 'GET':
if path == '/':
status = '200 OK'
response_content = handle_index(environ, env)
elif path == '/content':
status = '200 OK'
response_content = handle_content(environ, env)
elif path == '/file':
headers = [('Content-type', 'text/plain')]
status = '200 OK'
response_content = handle_file(environ, env)
elif path == '/image':
headers = [('Content-type', 'image/jpeg')]
status = '200 OK'
response_content = handle_image(environ, env)
elif path == '/submit':
status = '200 OK'
response_content = handle_submit_get(environ, env)

start_response(status, headers)
response = []
response.append(response_content)
return response

def make_app():
return app

def handle_index(params, env):
return str(env.get_template("index_result.html").render())

def handle_content(params, env):
return str(env.get_template("content_result.html").render())

def readFile(filepath):
''' Reads a file and returns its contents as a string '''
f = open(filepath, 'rb')
data = f.read()
f.close()

return data

def handle_file(params, env):
return readFile('./files/butts.txt')

def handle_image(params, env):
return readFile('./images/doge.jpeg')

def not_found(params, env):
return str(env.get_template("not_found.html").render())

def handle_submit_post(environ, env):
''' Handle a connection given path /submit '''

headers = {}
for k in environ.keys():
headers[k.lower()] = environ[k]

headers['content-type'] = environ['CONTENT_TYPE']
headers['content-length'] = environ['CONTENT_LENGTH']

firstNameFieldName = 'firstnamePOST2'
lastNameFieldName = 'lastnamePOST2'

# Kludgey workaround
if "multipart/form-data" in environ['CONTENT_TYPE']:
cLen = int(environ['CONTENT_LENGTH'])
data = environ['wsgi.input'].read(cLen)
environ['wsgi.input'] = StringIO(data)

firstNameFieldName = 'firstnamePOST1'
lastNameFieldName = 'lastnamePOST1'

form = cgi.FieldStorage(headers = headers, fp = environ['wsgi.input'],
environ = environ)

try:
firstname = form[firstNameFieldName].value
except KeyError:
firstname = ''

try:
lastname = form[lastNameFieldName].value
except KeyError:
lastname = ''

vars = dict(firstname = firstname, lastname = lastname)
return str(env.get_template("submit_result.html").render(vars))

def handle_submit_get(environ, env):
''' Handle a connection given path /submit '''
# submit needs to know about the query field, so more
# work needs to be done here.

# we want the first element of the returned list
params = environ['QUERY_STRING']
params = urlparse.parse_qs(params)

try:
firstname = params['firstname'][0]
except KeyError:
firstname = ''
try:
lastname = params['lastname'][0]
except KeyError:
lastname = ''

vars = dict(firstname = firstname, lastname = lastname)
return str(env.get_template("submit_result.html").render(vars))
4 changes: 4 additions & 0 deletions chat/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from apps import ChatApp

def create_chat_app(files_path):
return ChatApp(files_path)
130 changes: 130 additions & 0 deletions chat/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import os
import os.path
import mimetypes
import traceback
import random
import time
import cgi

class Message(object):
def __init__(self, timestamp, user, message):
self.timestamp = timestamp
self.user = user
self.message = message

class ChatApp(object):
def __init__(self, files_path):
self.file_server = FileServer(files_path)
self.messages = []

def get_messages_since(self, timestamp):
"""Retrieve any messages received since the given timestamp."""
x = []
for m in self.messages:
if m.timestamp > timestamp:
x.append(m)

return x

def format_response(self, new_messages, timestamp):
x = []
for m in new_messages:
x.append("""\
<message>
<author>%s</author>
<text>%s</text>
</message>
""" % (m.user, m.message))

if x: # new messages received?
# yes
status = 1
else:
status = 2 # no new messages

xml = """
<?xml version="1.0"?>
<response>
<status>%d</status>
<time>%f</time>
%s
</response>
""" % (status, timestamp, "".join(x))

return xml

def __call__(self, environ, start_response):
url = environ['PATH_INFO']
if url == '/get_messages':
# last_time
form = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)
last_time = float(form['last_time'].value)

new_messages = self.get_messages_since(last_time)
xml = self.format_response(new_messages, time.time())

# done; return whatever we've got.
start_response("200 OK", [('Content-type', 'text/html')])

print xml
return [xml]
elif url == '/post_message':
form = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)

# retrieve submitted data
last_time = float(form['last_time'].value)
author = form['user'].value
message = form['message'].value

# create and add new message:
timestamp = time.time()
m = Message(timestamp, author, message)
self.messages.append(m)

# return any new messages:
new_messages = self.get_messages_since(last_time)
xml = self.format_response(new_messages, timestamp)

# done; return whatever we've got.
start_response("200 OK", [('Content-type', 'text/html')])

print xml
return [xml]

# by default, just return a file
return self.file_server(environ, start_response)

class FileServer(object):
def __init__(self,path):
self.path = os.path.abspath(path)

def __call__(self, environ, start_response):
url = environ['PATH_INFO']

print 'url:' + url
if url.endswith('/'):
url += 'index.html'

fullpath = self.path + url
fullpath = os.path.abspath(fullpath)
assert fullpath.startswith(self.path)

extension=mimetypes.guess_type(fullpath)
extension=extension[0]

if extension is None:
extension = 'text/plain'

status = '200 OK'
headers = [('Content-type', extension )]

try:
fp = open(fullpath)
contents = fp.read()
start_response(status, headers)
return [contents]
except:
status = '404 Not Found'
headers = [('Content-type', 'text/html')]
start_response(status, headers)
return ['404 Not Found']
10 changes: 10 additions & 0 deletions chat/chat-server
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import sys
from webserve import Server

port = sys.argv[1]
port = int(port)

from apps import ChatApp
chat_app = ChatApp('./html')

Server(port, chat_app).serve_forever()
Loading