import sys, os, subprocess, json import configuration, logtool from ExifException import ExifException log = logtool.getLogger("exiftool") class ExifTool: """ Wrapper arround Exiftool. Processes an *existing* media file and print information as json Supports: 1) Reading tags from file 2) Editing + Writing new tags 3) Show supported filetypes/groups/tags Generally methods that return json, do so directly. Text information is not returned but remains in self.stdout NOTE: Each instance of the class has 1-1 relationship with a media file """ # Full path of media file filename = None # exiftool location (for execution) exiftoolpath = None # stdout Output of last execution stdout = None # stderr Output of last execution stderr = None def __init__(self, fname): self.filename = fname self.exiftoolpath = os.path.join(configuration.getExifDir(),
import logtool log = logtool.getLogger("Exiftool", "gtr") class ExifException(Exception): """ This class covers all exceptions thrown during execution of the external perl program exiftool. Should be Thrown *only* by the exiftool class """ # Everything in stderr after executing exiftool msg = None # A user friendlier shorter version of msg shortmsg = None def __init__(self, msg): self.msg = msg # take first line as a short message, which should be just enough. line = msg.split("\n")[0] # extra bodge since exiftool like to put home directories in message idx = line.find(" - /home") if idx != -1: self.shortmsg = line[:idx] else: self.shortmsg = line log.error("Exiftool exception shown to user: " + self.shortmsg) def __str__(self): return repr(self.msg)
import os, time, uuid, json, urllib, shutil import configuration, helper, logtool, exiftool, db import xml.etree.ElementTree as ETree #from ipdb import set_trace log = logtool.getLogger("MediaFactory", "gtr") class MediaFactory: """ Uses a Media interface (e.g. ExifTool/Sqlite (abstracted from helper.py)) to associate Media with users and sessions """ def __init__(self): """ Use one of the loadXXX methods to initialise the class as python does not have multiple constructors """ ######################### ### WEB related stuff ### ######################### # IP self.ip = None # File Object containing uploaded data self.filedata = None # uuid corresponding to request (for sharing). This is permanent and unique self.uuid = None # filename (main file e.g. foo.shp in the filepath to open) self.filename = None # Full path pointing to the saved data directory self.filedir = None # filedir/filename self.filefullpath = None
MK='Marker' XVAL='X Value' YVAL='Y Value' GEOM='geometry' FTS='features' TYPE='type' POINT='Point' DEC='Decision' RIDENT='Record ID' OSV='OS Version' MKM='Make and Model' IWIDTH='Image Width' IHEIGHT='Image Height' FLENGTH='Focal Length' log = logtool.getLogger("Export Variable GeoJSON", "pcapi") def export(path): try: import config, json file = open(config.get("path", "data_dir") + "/"+path,'r') flooddata=file.read() geojflood = json.loads(flooddata) fts=geojflood[FTS] plat=-1000 plon=-1000 img=[] polyCoord=[]
import sys, os, subprocess, json import configuration, logtool from ExifException import ExifException log = logtool.getLogger("exiftool") class ExifTool: """ Wrapper arround Exiftool. Processes an *existing* media file and print information as json Supports: 1) Reading tags from file 2) Editing + Writing new tags 3) Show supported filetypes/groups/tags Generally methods that return json, do so directly. Text information is not returned but remains in self.stdout NOTE: Each instance of the class has 1-1 relationship with a media file """ # Full path of media file filename = None # exiftool location (for execution) exiftoolpath = None # stdout Output of last execution stdout = None # stderr Output of last execution stderr = None def __init__(self, fname): self.filename = fname self.exiftoolpath = os.path.join(configuration.getExifDir(),"exiftool")
import bottle from bottle import route, request, response, static_file ## pcapi imports import logtool log = logtool.getLogger("pcapi") ## Dropbox imports #dboxpath = config.get("path","dropbox_path") #sys.path.append(os.path.join(pwd,dboxpath)) from pcapi_exceptions import * from pcapi_rest import PCAPIRest ################ ROUTES #################### ####################################################### ### Rest Callbacks (can be tested with wget/curl) ### ####################################################### ### Provider capabilities ### @route('/auth/providers',method=["GET"]) def capabilities(): return PCAPIRest(request,response).capabilities() ### /export/ a public URL @route('/export/<provider>/<userid>/<path:path>', method=["GET"]) def export(userid, provider, path="/"): return PCAPIRest(request,response).export(provider, userid, path)
#FS Provider tries to be "loosely" dropbox compliant to make your life a bit easier especially regarding the Metadata object # WARNING!!! # No `/' directory will be created unless you upload a file first. This is to avoid # a mess by clients calling /auth/local repeatedly and creating a new users every time without authentication. # Might revisit once we have authentication in place! import os, time, shutil, re import logtool, config, helper from pcapi_exceptions import FsException log = logtool.getLogger("FsProvider", "pcapi") class Metadata(object): """ metadata of files/dir as returned from local filesystem. This is plain filesystem metadata and NOT high-level pcapi metadata for records or editors""" def __init__ (self, md): self.md = md def __str__(self): return `self.md` def mtime(self, fmt=None): """ Return last modification time of self. Args: fmt (optional): format (s. strftime() system call) for the output date Returns: a date string in format described in "fmt" as in strftime. If no
import bottle from bottle import route, request, response, static_file ## pcapi imports import logtool log = logtool.getLogger("pcapi") ## Dropbox imports #dboxpath = config.get("path","dropbox_path") #sys.path.append(os.path.join(pwd,dboxpath)) from pcapi_exceptions import * from pcapi_rest import PCAPIRest ################ ROUTES #################### ####################################################### ### Rest Callbacks (can be tested with wget/curl) ### ####################################################### ### Provider capabilities ### @route('/auth/providers', method=["GET"]) def capabilities(): return PCAPIRest(request, response).capabilities() ### /export/ a public URL @route('/export/<provider>/<userid>/<path:path>', method=["GET"]) def export(userid, provider, path="/"):
import spatialite, configuration, logtool from DBException import DBException """ High Level GTR Wrapper arround Spatialite Supports: 1) Reading tags from uuid 2) Editing + Writing new tags 3) *temporary* Geograph specific functions (might eventually get merged with exiftool ones) #NOTE: Currently implemented as a module (i.e. Singleton in python) """ log = logtool.getLogger("db", "gtr") # UUID of media file uuid = None # Lon/Lat Coordinates of media file coords = None # Dictionary of tags of media file tags = None # stdout Output of last execution stdout = None def __init__(): pass def get_tags(): """ """ stdout = spatialite.execute(
### Static Variables ### # XXX Fill in your consumer key and secret below # You can find these at http://www.dropbox.com/developers/apps APP_KEY = configuration.get_app_key() APP_SECRET = configuration.get_app_secret() ACCESS_TYPE = 'app_folder' # should be 'dropbox' or 'app_folder' as configured for your app # COOKIES are an immutable hash table with request tokens as keys and request secret, access key, secret tuples as values. They are kept in memory till # we decide to store credentials on a database (do we want this?). # This is a static value and exists for the lifetime of the python interpreter. COOKIES = {} STATE_CODES = {"verify_token": 0, "connected": 1} log = logtool.getLogger("GTRDropbox", "gtr") ######################### class GTRDropbox: """ Create and control Dropbox sessions using oAuth protocol. Sessions are cached internally memory in the static variable COOKIES. Use one of the login or load methods to initialise the class as python does not have multiple constructors Example usage from a site gtr.ac.uk newurl = self.test_new_dropbox_session() print "URL: " + self.wait() self.cookie = self.gtrdb.callback() print "Cookie: " + self.cookie
from db import tokens ### Static Variables ### APP_KEY = config.get("dropbox","app_key") APP_SECRET = config.get("dropbox","app_secret") ACCESS_TYPE = 'app_folder' # should be 'dropbox' or 'app_folder' as configured for your app STATE_CODES = { "verify_token": 0, "connected" : 1 } # CAPABILITIES that this provider supports CAPABILITIES = [ "oauth", "search", "synchronize", "delete" ] log = logtool.getLogger("DropboxProvider", "pcapi") ######################### class Metadata(object): """ metadata of files/dir as returned from dropbox. This is plain filesystem metadata and NOT high-level pcapi metadata for records or editors""" def __init__ (self, md): self.md = md def __str__(self): return `self.md` def mtime(self, fmt=None): """ Return last modification time of self. Args:
## output = spatialite.execute("select HEX(GeomFromText(?));",('POINT(788703.57 4645636.3)',)) ## The output is a a tuple of lists. To get the 2nd field from 3rd row just use output[2][1] (0-based index) ## Devel's python has "surprisingly" disabled sqlite3 support unlike 99.9% of sane python installations. try: # make up for inconsistencies between normal linux distributions, devel.edina, rainbow.edina etc. etc. import pysqlite2.dbapi2 as db from pysqlite2.dbapi2 import OperationalError except ImportError: import sqlite3.dbapi2 as db from sqlite3.dbapi2 import OperationalError import os import config, logtool ### Constants ### log = logtool.getLogger("spatialite", "pcapi") # full path of sqlite3 database DB = config.get("path", "sessionsdb") log.debug(DB) # full path of libspatialite.so.3 SPATIALPLUGIN = config.get("path", "libspatialite") # creating/connecting the test_db. # "check_same_thread" turns off some false alarms from sqlite3. # NOTE: mod_wsgi runs these global variables in *different* processes for each request. con = db.connect(DB, check_same_thread=False) # Revert to plain sqlite3 when libspatialite is missing
# -*- coding: utf-8 -*- import spatialite, logtool #################### Dropbox,flickr etc. credential storage management ############# """ Wrapper functions around SQL command use for reading/writing/seaching access credentials for different providers. The result is normal a list of tuples e.g. [(foo,bar)] for one row and (None,) for no rows. NOTE: req_key (in dropbox lingo) is "userid" for pcapi """ log = logtool.getLogger("tokens", "pcapi") def dump_tokens(): res = spatialite.execute(""" SELECT * FROM tokens; """) # 2D list of lists return res def save_access_tokens(userid, req_secret, acc_key, acc_secret): res = spatialite.execute(""" INSERT OR IGNORE INTO tokens(userid,reqsec,accsec,acckey) VALUES (?,?,?,?) """, (userid,req_secret, acc_key, acc_secret)) return res==[] def get_access_pair(userid): """ return ( acc_key, acc_secret ) for provided userid or None """ res = spatialite.execute("""
sys.path.append(os.path.join(pwd, '../lib')) import bottle from bottle import route, request, static_file, redirect # gtr imports import logtool, mediafactory, configuration, db, helper from ExifException import ExifException #Dropbox imports dbpath = configuration.getDropboxSDK() sys.path.append(os.path.join(pwd, dbpath)) import gtr_dropbox application = bottle.default_app() log = logtool.getLogger("gtr") ################ ROUTES #################### @route('/ws/editfile/:uuid') def editfile(uuid): """ Edit the properties of an already-uploaded media file. This is also usefull for getting rid of extra GET parameters forcibly added by dropbox """ # optional drobox arguments ( currently ignored ) uid = request.GET.get("uid", None) oauth_token = request.GET.get("oauth_token", None) log.info("editfile" + " params: uuid:%s uid:%s oauth_token:%s " %
import spatialite, logtool from DBException import DBException """ High Level PCAPI Wrapper arround Spatialite Supports: 1) Session management 2) GIS ops (nearby etc) NOTE: Currently implemented as a module (i.e. Singleton in python). Could perhaps split into "geo" and "metadata" specific functions """ log = logtool.getLogger("appdb", "db") #################### SESSION / KEYWORD FUNCTIONS ############# def get_tags(userid): """ Get all tags associated with a userid """ stdout = spatialite.execute(""" BEGIN; select group_concat(tag) as tags from sessions LEFT OUTER JOIN tags USING userid LEFT OUTER JOIN tag USING tag_id where userid=? COMMIT;""", (userid,)) if stdout == None: raise DBException("No tags found!") return stdout.split(',') def insert_key(key): """ register a new keyword. Noop if keyword exists. """ res = spatialite.execute(""" INSERT OR IGNORE INTO tag(tag) VALUES (?);
import spatialite, logtool from DBException import DBException """ High Level PCAPI Wrapper arround Spatialite Supports: 1) Session management 2) GIS ops (nearby etc) NOTE: Currently implemented as a module (i.e. Singleton in python). Could perhaps split into "geo" and "metadata" specific functions """ log = logtool.getLogger("appdb", "db") #################### SESSION / KEYWORD FUNCTIONS ############# def get_tags(userid): """ Get all tags associated with a userid """ stdout = spatialite.execute( """ BEGIN; select group_concat(tag) as tags from sessions LEFT OUTER JOIN tags USING userid LEFT OUTER JOIN tag USING tag_id where userid=? COMMIT;""", (userid, )) if stdout == None: raise DBException("No tags found!") return stdout.split(',') def insert_key(key): """ register a new keyword. Noop if keyword exists. """
# You can find these at http://www.dropbox.com/developers/apps APP_KEY = configuration.get_app_key() APP_SECRET = configuration.get_app_secret() ACCESS_TYPE = 'app_folder' # should be 'dropbox' or 'app_folder' as configured for your app # COOKIES are an immutable hash table with request tokens as keys and request secret, access key, secret tuples as values. They are kept in memory till # we decide to store credentials on a database (do we want this?). # This is a static value and exists for the lifetime of the python interpreter. COOKIES = {} STATE_CODES = { "verify_token": 0, "connected" : 1 } log = logtool.getLogger("GTRDropbox", "gtr") ######################### class GTRDropbox: """ Create and control Dropbox sessions using oAuth protocol. Sessions are cached internally memory in the static variable COOKIES. Use one of the login or load methods to initialise the class as python does not have multiple constructors Example usage from a site gtr.ac.uk newurl = self.test_new_dropbox_session() print "URL: " + self.wait() self.cookie = self.gtrdb.callback() print "Cookie: " + self.cookie """
import spatialite, configuration, logtool from DBException import DBException """ High Level GTR Wrapper arround Spatialite Supports: 1) Reading tags from uuid 2) Editing + Writing new tags 3) *temporary* Geograph specific functions (might eventually get merged with exiftool ones) #NOTE: Currently implemented as a module (i.e. Singleton in python) """ log = logtool.getLogger("db", "gtr") # UUID of media file uuid = None # Lon/Lat Coordinates of media file coords = None # Dictionary of tags of media file tags = None # stdout Output of last execution stdout = None def __init__(): pass def get_tags(): """ """ stdout = spatialite.execute(""" BEGIN;
import logtool log = logtool.getLogger("Exiftool", "gtr") class ExifException(Exception): """ This class covers all exceptions thrown during execution of the external perl program exiftool. Should be Thrown *only* by the exiftool class """ # Everything in stderr after executing exiftool msg = None # A user friendlier shorter version of msg shortmsg = None def __init__(self, msg): self.msg = msg # take first line as a short message, which should be just enough. line = msg.split('\n')[0] # extra bodge since exiftool like to put home directories in message idx = line.find( " - /home") if (idx != -1): self.shortmsg = line[:idx] else: self.shortmsg = line log.error("Exiftool exception shown to user: " + self.shortmsg) def __str__(self): return repr(self.msg)
# -*- coding: utf-8 -*- import spatialite, logtool #################### Dropbox,flickr etc. credential storage management ############# """ Wrapper functions around SQL command use for reading/writing/seaching access credentials for different providers. The result is normal a list of tuples e.g. [(foo,bar)] for one row and (None,) for no rows. NOTE: req_key (in dropbox lingo) is "userid" for pcapi """ log = logtool.getLogger("tokens", "pcapi") def dump_tokens(): res = spatialite.execute(""" SELECT * FROM tokens; """) # 2D list of lists return res def save_access_tokens(userid, req_secret, acc_key, acc_secret): res = spatialite.execute( """ INSERT OR IGNORE INTO tokens(userid,reqsec,accsec,acckey) VALUES (?,?,?,?) """, (userid, req_secret, acc_key, acc_secret)) return res == []
import config, logtool, re, time from dropbox import client, session, rest from db import tokens ### Static Variables ### APP_KEY = config.get("dropbox", "app_key") APP_SECRET = config.get("dropbox", "app_secret") ACCESS_TYPE = 'app_folder' # should be 'dropbox' or 'app_folder' as configured for your app STATE_CODES = {"verify_token": 0, "connected": 1} # CAPABILITIES that this provider supports CAPABILITIES = ["oauth", "search", "synchronize", "delete"] log = logtool.getLogger("DropboxProvider", "pcapi") ######################### class Metadata(object): """ metadata of files/dir as returned from dropbox. This is plain filesystem metadata and NOT high-level pcapi metadata for records or editors""" def __init__(self, md): self.md = md def __str__(self): return ` self.md ` def mtime(self, fmt=None): """ Return last modification time of self. Args: fmt (optional): format (s. strftime() system call) for the output date Returns:
sys.path.append(os.path.join(pwd,'../lib')) import bottle from bottle import route, request, static_file, redirect # gtr imports import logtool, mediafactory, configuration, db, helper from ExifException import ExifException #Dropbox imports dbpath = configuration.getDropboxSDK() sys.path.append(os.path.join(pwd,dbpath)) import gtr_dropbox application = bottle.default_app() log = logtool.getLogger("gtr") ################ ROUTES #################### @route('/ws/editfile/:uuid') def editfile( uuid ): """ Edit the properties of an already-uploaded media file. This is also usefull for getting rid of extra GET parameters forcibly added by dropbox """ # optional drobox arguments ( currently ignored ) uid = request.GET.get("uid",None) oauth_token = request.GET.get("oauth_token",None) log.info("editfile" + " params: uuid:%s uid:%s oauth_token:%s " % (uuid,uid, oauth_token)) return redirect('/index.html?uuid=%s' % uuid)
from form_validator import FormValidator, Editor from cobweb_parser import COBWEBFormParser from bottle import Response from StringIO import StringIO from operator import itemgetter import urllib2 try: import threadpool except ImportError: sys.stderr.write("Error: Can't find threadpool...") import dbox_provider, fs_provider, logtool from wand.image import Image from pcapi_exceptions import * log = logtool.getLogger("PCAPIRest", "pcapi") class Record(object): """ Class to store record bodies and metadata in memory for fast access""" def __init__(self, content, metadata): self.content = content # as a parsed json (dict) self.metadata = metadata # as a dbox_provider.Metadata object ################ Decorators #################### def authdec(): def decorator(f): def wrapper(*args, **kwargs): log.debug('%s( *%s )' % (f.__name__, ` args `)) dbox = dbox_provider.DropboxProvider()
MK = 'Marker' XVAL = 'X Value' YVAL = 'Y Value' GEOM = 'geometry' FTS = 'features' TYPE = 'type' POINT = 'Point' DEC = 'Decision' RIDENT = 'Record ID' OSV = 'OS Version' MKM = 'Make and Model' IWIDTH = 'Image Width' IHEIGHT = 'Image Height' FLENGTH = 'Focal Length' log = logtool.getLogger("Export Variable GeoJSON", "pcapi") def export(path): try: import config, json file = open(config.get("path", "data_dir") + "/" + path, 'r') flooddata = file.read() geojflood = json.loads(flooddata) fts = geojflood[FTS] plat = -1000 plon = -1000 img = [] polyCoord = []
## output = spatialite.execute("select HEX(GeomFromText(?));",('POINT(788703.57 4645636.3)',)) ## The output is a a tuple of lists. To get the 2nd field from 3rd row just use output[2][1] (0-based index) ## Devel's python has "surprisingly" disabled sqlite3 support unlike 99.9% of sane python installations. try: # make up for inconsistencies between normal linux distributions, devel.edina, rainbow.edina etc. etc. import pysqlite2.dbapi2 as db from pysqlite2.dbapi2 import OperationalError except ImportError: import sqlite3.dbapi2 as db from sqlite3.dbapi2 import OperationalError import os import config, logtool ### Constants ### log = logtool.getLogger("spatialite", "pcapi") # full path of sqlite3 database DB = config.get("path","sessionsdb") log.debug(DB) # full path of libspatialite.so.3 SPATIALPLUGIN = config.get("path", "libspatialite") # creating/connecting the test_db. # "check_same_thread" turns off some false alarms from sqlite3. # NOTE: mod_wsgi runs these global variables in *different* processes for each request. con = db.connect(DB, check_same_thread=False) # Revert to plain sqlite3 when libspatialite is missing
#FS Provider tries to be "loosely" dropbox compliant to make your life a bit easier especially regarding the Metadata object # WARNING!!! # No `/' directory will be created unless you upload a file first. This is to avoid # a mess by clients calling /auth/local repeatedly and creating a new users every time without authentication. # Might revisit once we have authentication in place! import os, time, shutil, re import logtool, config, helper from pcapi_exceptions import FsException log = logtool.getLogger("FsProvider", "pcapi") class Metadata(object): """ metadata of files/dir as returned from local filesystem. This is plain filesystem metadata and NOT high-level pcapi metadata for records or editors""" def __init__(self, md): self.md = md def __str__(self): return ` self.md ` def mtime(self, fmt=None): """ Return last modification time of self. Args: fmt (optional): format (s. strftime() system call) for the output date Returns: a date string in format described in "fmt" as in strftime. If no format is specified then seconds since unix epoch are returned. This is useful for date comparisons.
from bs4 import BeautifulSoup #from lxml.html.clean import clean_html, Cleaner #from lxml import etree import logtool, config from StringIO import StringIO import html5lib from html5lib import treebuilders, treewalkers, serializer from html5lib.filters import sanitizer log = logtool.getLogger("FormValidator", "pcapi") class Editor(object): def __init__(self, content): self.content = content self.soup = BeautifulSoup(self.content, 'html.parser') self.elements = ["text", "textarea", "checkbox", "radio", "select", "image", "audio", "range"] def findElements(self): elements = [] for tag in self.soup.findAll("div", {"class": "fieldcontain"}): check, elem = self.checkForElements(tag["id"]) if check: log.debug("%s, %s" % (tag["id"], self.get_header(elem, tag["id"]))) elements.append([tag["id"], self.get_header(elem, tag["id"])]) return elements def checkForElements(self, tag): for el in self.elements: if el in tag and "-buttons" not in tag: return (True, el) return (False, None)
from form_validator import FormValidator, Editor from cobweb_parser import COBWEBFormParser from bottle import Response from StringIO import StringIO from operator import itemgetter import urllib2 try: import threadpool except ImportError: sys.stderr.write("Error: Can't find threadpool...") import dbox_provider, fs_provider, logtool from wand.image import Image from pcapi_exceptions import * log = logtool.getLogger("PCAPIRest", "pcapi") class Record(object): """ Class to store record bodies and metadata in memory for fast access""" def __init__(self, content, metadata ): self.content = content # as a parsed json (dict) self.metadata = metadata # as a dbox_provider.Metadata object ################ Decorators #################### def authdec(): def decorator(f): def wrapper(*args, **kwargs): log.debug('%s( *%s )' % (f.__name__, `args`)) dbox = dbox_provider.DropboxProvider() status = dbox.probe(args[1]) # check access token *existence*
from bs4 import BeautifulSoup #from lxml.html.clean import clean_html, Cleaner #from lxml import etree import logtool, config from StringIO import StringIO import html5lib from html5lib import treebuilders, treewalkers, serializer from html5lib.filters import sanitizer log = logtool.getLogger("FormValidator", "pcapi") class Editor(object): def __init__(self, content): self.content = content self.soup = BeautifulSoup(self.content, 'html.parser') self.elements = [ "text", "textarea", "checkbox", "radio", "select", "image", "audio", "range" ] def findElements(self): elements = [] for tag in self.soup.findAll("div", {"class": "fieldcontain"}): check, elem = self.checkForElements(tag["id"]) if check: log.debug("%s, %s" % (tag["id"], self.get_header(elem, tag["id"]))) elements.append([tag["id"], self.get_header(elem, tag["id"])]) return elements