User:Eleanorg/1.3/Dissolute Image/Code2

From XPUB & Lens-Based wiki

(re-writing the code for the Dissolute Image so that users get an actual image file instead of a string, which is embedded on the page. It'll be better. Promise.) << And now it works with facebook, no API shizzle required!

create an image file

This script grabs an unadopted pixel randomly from the DB, creates an image file on the fly and gives it to the user. It also creates a hash for that file to ensure that users can't tamper with it.

#!/usr/bin/python
#-*- coding:utf-8 -*-
 
import cgi
import cgitb; cgitb.enable()
import hashlib
import os
import pymongo, random  
from pymongo import Connection
 
## grab a random unadopted pixel from the database and create an image out of it

connection = Connection()
myDB = connection['pixelDbQuery1']
collection = myDB.collection

##--------- choose pixel randomly from DB ------------#
# 
# find all entries where url is empty:
unadopted = []
for entry in collection.find({"url": ""}):
    unadopted.append(entry)			# add this pixel's hash as an item to the 'unadopted' dictionary
#print unadopted
 
howMany = len(unadopted)			# find out how many items in 'unadopted' list
#print howMany
random = random.randint(0,howMany)		# pick a random number in this range
#print random
pixelHash = unadopted[random]			# ...and choose the pixel at this index
#print pixelHash

#color = "#333"
#xpos = str(10)
#ypos = str(20)
pixelId = pixelHash['ID']
color = pixelHash['color']
xpos = pixelHash['xpos']
ypos = pixelHash['ypos']
image = "../../forbiddenPixels/images/" + xpos + "_" + ypos + ".jpg"
#print image

#--------- create an image with it ------------#

# creates new image and saves to images folder
command = "convert -size 1x1 xc:" + color + " " + image   
#print command	           	
os.popen(command, 'r').read()


#--------- create hash for img and put in DB ------------#
 
# md5sum -- create an hex digest of a file's md5 hash
# usage: print md5sum(open('filename','rb'))


# define hashing function
def md5sum(f, block_size=8192):
    md5 = hashlib.md5()
    while True:
        data = f.read(block_size)
        if not data:
            break
        md5.update(data)
    return md5.hexdigest()

# run hashing function, assigning to var 'hash'
pixelHash = md5sum(open(image,'rb'))
# insert hash for this pixel into its array in DB
collection.update( {"ID": pixelId}, {"$set":{"hash": pixelHash}})

#--------- give user link to the image ------------#
 
htmlHeader = """<!DOCTYPE html>
<html>
  <head>
    <title>Adopt a Pixel</title>
        <link <link rel="stylesheet" href="">
  </head>
  <body>"""
 
 
print "Content-Type: text/html"
print 
print htmlHeader
print """
<h1>the DISSOLUTE IMAGE</h1>
Right click & 'save as' to download your pixel: <br />

<a href=" """ + image + """ ">Download Pixel</a>
<br />
The hash is """ + pixelHash + """
</body>
</html>"""

input form for user to give url

  • HTML form to recieve image URL
  • Linked from above script - 'upload your img, then give the url /here/'

extract image file from url submitted

  • use urlLib to read the page
  • Get the image file, check its hash against the db
  • if correct, put url into db for that pixel


rough outline. This script currently only checks that an image exists at a given url, everything else commented out:

#!/usr/bin/python
#-*- coding:utf-8 -*-

import pymongo
from pymongo import Connection
import urllib
from urllib2 import urlopen, Request, HTTPError, URLError

# check url given by user for correct image file


##--------- connect to DB ------------#

# TODO connection to pymongo on pzwart3 seems to be broken.
# error 5 sept 2012: 
# File "1checkUrl.cgi", line 14, in <module>
#    connection = Connection()
#  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.2-py2.7-linux-x86_64.egg/pymongo/connection.py", line 290, in __init__
#    self.__find_node()
#  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.2-py2.7-linux-x86_64.egg/pymongo/connection.py", line 586, in __find_node
#    raise AutoReconnect(', '.join(errors))
#pymongo.errors.AutoReconnect: could not connect to localhost:27017: [Errno 111] Connection refused

#connection = Connection()
#myDB = connection['pixelDbQuery1']
#collection = myDB.collection


##--------- recieve url from input form ------------#

#form = cgi.FieldStorage()			# Grabs whatever input comes from form
#pixelHash = form.getvalue("pixelHash")		# pixel info is sent invisibly with the form? --> no, hash generated below then looked for in db
#TODO check if valid url/protocol given. urllib2 bit breaks if not.

#url = form.getvalue("url", "http://ox4.org/~nor/trials/hostedString.html") 
#for testing:
#url = "http://pzwart3.wdka.hro.nl/~egreenhalgh/forbiddenPixels/updated.png"
url ="http://a7.sphotos.ak.fbcdn.net/hphotos-ak-ash4/429841_10150741640794703_1625941_n.jpg"

## ------ ascertain correct hash for this pixel-------------------#

# get xpos & ypos from image file given by user
# lookup in db to find its hash?
# correctHash = (db query goes here)


##--------- retrieve user image from url & check its hash against hash in db ------------#


## define error/success-printing functions----------------#

# This would print an error to their browser. For now just print the
#string it is passed
def sayErr(err):
	print err
# This would tell them when they had been successful (after checking the
#picture was OK)
def greatSuccess(msg):
	print msg
	

## check that an image exists at this url ----------------#

# this function only gets called if the url is valid, no 404s etc
# can't these print statements be integrated into the imageOK function?

def parseHTML(url):
	if imageOK:
		greatSuccess("Correct image found at " + url)
	else:
		sayErr("Coulnd't find correct image at " + url)


## define func to get image hash & check it against correct hash ---------#


#def imageOK(img):
#	# gets hash of user's image
#	def md5sum(f, block_size=8192):
#   		md5 = hashlib.md5()
#    		while True:
#      			data = f.read(block_size)
#        		if not data:
#            			break
#        		md5.update(data)
#   		return md5.hexdigest()
#	userHash = md5sum(open(image,'rb'))
#	# TODO compare it to correct pixel hash - if same, add url to db
#	# if userHash == correctHash:
#		return True
#		# TODO add url to db
#	else:
#		return False


# Try and fetch our URL ---------------------------------#
# If there is a 404 or 500, throw error
def getURL(url):
	# make request object
	req = Request(url)
	try:
		response = urlopen(req) # assign output of urlopen function to var 'request'
	# httpError comes with urllib2 for exception handling
	# if unable to create Response Object:
	except HTTPError, e:
		# This is a 404 or 500 or something
		sayErr("The server couldn't fulfill the request.\nError code: " +
str(e.code))
	except URLError, e:
		# This is a problem with your network or something
		sayErr("We failed to reach a server.\nReason: " + e.reason)
	# otherwise, if response is ok:
	else:
		# Got the page. Look at the content-type header
		# .info() is one of the methods you can use on the Response Object (stored in var 'response')
		info = response.info()
		#print info['Content-Type']
		if info['Content-Type'].startswith("text/html") or info['Content-Type'].startswith("text/plain") or info['Content-Type'].startswith("application/xml"):
			parseHTML(url)
		elif info['Content-Type'].startswith("image/png"):
			# call imageOK()
			# if imageOK() returns true - ie 'if imageOK():'
			print "got your image!"
			# TODO now you know url is valid, run imageOK
#			if imageOK:
#				greatSuccess("Got image d'reckly from " + url)
#			else:
#				sayErr("Oh dear, wrong image found")
		else:

			sayErr("Sorry, " + info['Content-Type'] + " isn't a valid image format")

#now call the above func to check it's working			
getURL(url)

create html doc with embedded images

TODO next: create a simple html doc that just shows 1 pixel from the db.

  • embeds images as per database urls
  • Q: how to load quickly, not having to go thru db on each load?
  • Q: how to position pixels correctly on page?
  • Q: Is it realistic to embed images or could I use Canvas to draw pixels on, and have a tooltip for each pixel on the canvas?