if interface['interface'] == 'SPI1' and type == 'CuPIDlights': spilights.updatelightsfromdb(pilib.controldatabase, 'indicators', 1) if interface['interface'] == 'SPI0' and type == 'CuPIDlights': spilights.updatelightsfromdb(pilib.controldatabase, 'indicators', 0) if runi2cowfs or runusbowfs: if runi2cowfs: subprocess.call([ '/opt/owfs/bin/owserver', '-F', '--i2c=/dev/i2c-1:ALL', '-p', '4304' ]) if runusbowfs: subprocess.call(['/opt/owfs/bin/owserver', '-F', '-u', '-p', '4304']) subprocess.call(['/opt/owfs/bin/owfs', '-F', '-s', '4304', '/var/1wire/']) subprocess.call( ['/opt/owfs/bin/owhttpd', '-F', '-s', '4304', '-p', '4305']) # Run netstart script from netconfig import runconfig runconfig(onboot=True) # Run daemon from cupiddaemon import rundaemon rundaemon() # Update hardware version in table from systemstatus import readhardwarefileintoversions readhardwarefileintoversions()
def application(environ, start_response): import cgi import json import os, sys, inspect # Set top folder to allow import of modules top_folder = os.path.split(os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0])))[0] if top_folder not in sys.path: sys.path.insert(0,top_folder) import cupid.pilib as pilib import cupid.controllib as controllib post_env = environ.copy() post_env['QUERY_STRING'] = '' post = cgi.FieldStorage( fp=environ['wsgi.input'], environ=post_env, keep_blank_values=True ) formname=post.getvalue('name') output = {} output['message'] = 'Output Message: ' d = {} for k in post.keys(): d[k] = post.getvalue(k) status = '200 OK' wsgiauth = False authverified = False if wsgiauth: # Verfiy that session login information is legit: hashed password, with salt and username, match # hash stored in database. import hashlib from pilib import salt try: userdata = pilib.datarowtodict(pilib.usersdatabase, 'users', pilib.sqlitequery(pilib.usersdatabase, "select * from users where name='" + d['sessionuser'] + "'")[0]) except: output['message'] += 'error in user sqlite query. ' # unsuccessful authentication # Get session hpass to verify credentials hashedpassword = d['sessionhpass'] hname = hashlib.new('sha1') hname.update(d['sessionuser']) hashedname = hname.hexdigest() hentry = hashlib.new('md5') hentry.update(hashedname + salt + hashedpassword) hashedentry = hentry.hexdigest() if hashedentry == userdata['password']: # successful auth output['message'] += 'Password verified. ' authverified = True else: output['message'] += 'WSGI authorization not enabled. ' if authverified or not wsgiauth: # Perform requested actions if 'action' in d: action = d['action'] output['message'] += 'Found action. ' if action == 'runquery': output['message'] += 'Query keyword found. ' if 'query' in d: # Take plain single query result = pilib.sqlitequery(d['database'], d['query']) output['response'] = result output['message'] += 'Query executed. ' elif 'queryarray[]' in d: # Take query array, won't find result = [] queryarray = d['queryarray[]'] for query in queryarray: result.append(pilib.sqlitequery(d['database'], query)) output['response'] = result output['message'] += 'Query array executed. ' elif action == 'testmodule': output['message'] += 'Testing module: ' if 'modulename' in d: import cupid.cupidunittests output['message'] += d['modulename'] output['data'] = cupid.cupidunittests.testmodule(d['modulename']) else: output['message'] += 'Modulename not found. ' elif action == 'testfunction': output['message'] += 'Testing function: ' if 'testname' in d: import cupid.cupidunittests output['message'] += d['testname'] # output['data'] = cupid.tests.testfunction(d['testname']) output['data'] = cupid.cupidunittests.testfunction(d['testname']) # output['data'] = str(cupid.tests.testfunction('systemstatus')) else: output['message'] += 'Testname not found. ' elif action == 'dump': if 'database' in d and 'tablelist' in d and 'outputfile' in d: pilib.sqlitedatadump(d['database'],d['tablelist'],d['outputfile']) output['message'] = 'data dumped' elif 'database' in d and 'tablename' in d and 'outputfile' in d: pilib.sqlitedatadump(d['database'],[d['tablename']],d['outputfile']) output['message'] = 'data dumped' else: data = 'keys not present for dump' elif action in ['userdelete', 'useradd', 'usermodify']: # Ensure that we are authorized for this action if userdata['authlevel'] >= 4: output['message'] += 'User selected has sufficient authorizations. ' if action == 'userdelete': try: pilib.sqlitequery(pilib.usersdatabase, "delete from users where name='" + d['usertodelete'] + "'") except: output['message'] += 'Error in delete query. ' else: output['message'] += 'Successful delete query. ' elif action == 'usermodify': if 'usertomodify' in d: querylist=[] if 'newpass' in d: # Get session hpass to verify credentials hashedpassword = d['newpass'] hname = hashlib.new('sha1') hname.update(d['usertomodify']) hashedname = hname.hexdigest() hentry = hashlib.new('md5') hentry.update(hashedname + salt + hashedpassword) hashedentry = hentry.hexdigest() querylist.append('update users set password='******'" + d['usertomodify'] + "'") if 'newemail' in d: querylist.append("update users set email='" + d['newemail'] + "' where name='" + d['usertomodify'] + "'") if 'newauthlevel' in d: querylist.append("update users set authlevel='" + d['newauthlevel'] + "' where name='" + d['usertomodify'] + "'") try: pilib.sqlitemultquery(pilib.usersdatabase, querylist) except: output['message'] += 'Error in modify/add query: ' + ",".join(querylist) else: output['message'] += 'Successful modify/add query. ' + ",".join(querylist) else: output['message'] += 'Need usertomodify in query. ' elif action == 'useradd': try: username = d['newusername'] except: username = '******' try: newemail = d['newemail'] except: newemail = '*****@*****.**' try: newauthlevel = d['newauthlevel'] except: newauthlevel = 0 query = "insert into users values(NULL,'" + username + "','','" + newemail + "',''," + str(newauthlevel) + ")" try: pilib.sqlitequery(pilib.usersdatabase, query) except: output['message'] += "Error in useradd sqlite query: " + query + ' . ' else: output['message'] += "Successful query: " + query + ' . ' else: output['message'] += 'Unable to verify password. ' else: output['message'] = 'insufficient authorization level for current user. ' elif action == 'getfiletext': try: filepath = d['filepath'] if 'numlines' in d: numlines = int(d['numlines']) else: numlines = 9999 output['message'] += 'Using numlines: ' + str(numlines) + ' for read action. ' if 'startposition' in d: startposition = d['startposition'] else: startposition = 'end' output['message'] += 'Reading from position ' + startposition + '. ' except KeyError: output['message'] += 'Sufficient keys for action getfile text do not exist. ' except: output['message'] += 'Uncaught error in getfiletext. ' else: try: file = open(filepath) lines = file.readlines() except: output['message'] += 'Error reading file in getfiletext action. ' else: output['data'] = [] if startposition == 'end': try: output['data'] = pilib.tail(file, numlines)[0] except: output['message'] += 'Error in tail read. ' else: linecount = 0 for line in lines: linecount += 1 if linecount > numlines: break else: output['data'].append(line) elif action == 'getmbtcpdata': try: clientIP = d['clientIP'] register = d['register'] length = d['length'] except KeyError: output['message'] += 'Sufficient keys do not exist for the command. Requires clientIP, register, and length. ' else: from cupid.netfun import readMBcodedaddresses # try: output['response'] = readMBcodedaddresses(clientIP, int(register), int(length)) elif action == 'queuemessage': output['message'] += 'Queue message. ' if 'message' in d: try: pilib.sqliteinsertsingle(pilib.motesdatabase, 'queuedmessages', [pilib.gettimestring(), d['message']]) except Exception, e: output['message'] += 'Error in queue insert query: ' + str(e) else: output['message'] += 'Message insert successful' else: output['message'] += 'No message present. ' elif action == 'setsystemflag' and 'systemflag' in d: database = pilib.systemdatadatabase pilib.setsinglevalue(database, 'systemflags', 'value', 1, "name=\'" + d['systemflag'] + "'") elif action == 'rundaemon': from cupiddaemon import rundaemon rundaemon() elif action == 'setvalue': pilib.log(pilib.controllog, "Setting value in wsgi", 1, 1) # we use the auxiliary 'setsinglecontrolvalue' to add additional actions to update if all(k in d for k in ('database', 'table', 'valuename', 'value')): output['message'] += 'Carrying out setvalue. ' if 'condition' in d: pilib.setsinglecontrolvalue(d['database'], d['table'], d['valuename'], d['value'], d['condition']) elif 'index' in d: condition = 'rowid= ' + d['index'] pilib.setsinglecontrolvalue(d['database'], d['table'], d['valuename'], d['value'], condition) else: pilib.setsinglecontrolvalue(d['database'], d['table'], d['valuename'], d['value']) else: output['message'] += 'Insufficient data for setvalue ' elif action == 'updateioinfo': if all(k in d for k in ['database', 'ioid', 'value']): query = pilib.makesqliteinsert('ioinfo', [d['ioid'], d['value']], ['id', 'name']) try: pilib.sqliteinsertsingle(pilib.controldatabase, 'ioinfo', [d['ioid'], d['value']], ['id', 'name']) except: output['message'] += 'Error in updateioinfo query execution: ' + query +'. ' output['message'] += 'ioid: ' + d['ioid'] + ' . ' else: output['message'] += 'Executed updateioinfo query. ' else: output['message'] += 'Insufficient data for updateioinfo query ! ' # These are all very specific actions that could be rolled up or built into classes elif action == 'spchange' and 'database' in d: output['message'] += 'Spchanged. ' if 'subaction' in d: if d['subaction'] == 'incup': controllib.incsetpoint(d['database'], d['channelname']) output['message'] += 'incup. ' if d['subaction'] == 'incdown': controllib.decsetpoint(d['database'], d['channelname']) output['message'] += 'incdown. ' if d['subaction'] == 'setvalue': controllib.setsetpoint(d['database'], d['channelname'], d['value']) output['message'] += 'Setvalue: ' + d['database'] + ' ' + d['channelname'] + ' ' + d['value'] else: output['message'] += 'subaction not found. ' elif action == 'togglemode' and 'database' in d: controllib.togglemode(d['database'], d['channelname']) elif action == 'setmode' and 'database' in d: controllib.setmode(d['database'], d['channelname'], d['mode']) elif action == 'setrecipe': controllib.setrecipe(d['database'], d['channelname'], d['recipe']) elif action == 'setcontrolinput': controllib.setcontrolinput(d['database'], d['channelname'], d['controlinput']) elif action == 'setchannelenabled': controllib.setchannelenabled(d['database'], d['channelname'], d['newstatus']) elif action == 'setchanneloutputsenabled': controllib.setchanneloutputsenabled(d['database'], d['channelname'], d['newstatus']) elif action == 'manualactionchange' and 'database' in d and 'channelname' in d and 'subaction' in d: curchanmode = pilib.controllib.getmode(d['database'], d['channelname']) if curchanmode == 'manual': if d['subaction'] == 'poson': controllib.setaction(d['database'], d['channelname'], '100.0') elif d['subaction'] == 'negon': controllib.setaction(d['database'], d['channelname'], '-100.0') else: controllib.setaction(d['database'], d['channelname'], '0.0') elif action == 'setposoutput' and 'database' in d and 'channelname' in d and 'outputname' in d: controllib.setposout(d['database'], d['channelname'], d['outputname']) elif action == 'setnegoutput' and 'database' in d and 'channelname' in d: controllib.setnegout(d['database'], d['channelname'], d['outputname']) elif action == 'actiondown' and 'database' in d and 'channelname' in d: curchanmode = controllib.getmode(d['database'], d['channelname']) if curchanmode == "manual": curaction = int(controllib.getaction(d['database'], d['channelname'])) if curaction == 100: nextvalue = 0 elif curaction == 0: nextvalue = -100 elif curaction == -100: nextvalue = -100 else: nextvalue = 0 controllib.setaction(d['database'], d['channelname'], d['nextvalue']) elif action == 'actionup' and 'database' in d and 'channelname' in d: curchanmode = controllib.getmode(d['database'], d['channelname']) if curchanmode == "manual": curaction = int(controllib.getaction(d['database'], d['channelname'])) if curaction == 100: nextvalue = 100 elif curaction == 0: nextvalue = 100 elif curaction == -100: nextvalue = 0 else: nextvalue = 0 controllib.setaction(d['database'], d['channelname'], nextvalue) elif action == 'deletechannelbyname' and 'database' in d and 'channelname' in d: pilib.sqlitequery(d['database'], 'delete channelname from channels where name=\"' + d['channelname'] + '\"') else: output['message'] += 'Action keyword present(' + action + '), but not handled. ' else: output['message'] += 'action keyword not present. '
try: subprocess.call(['/opt/owfs/bin/owfs', '-F', '-s', '4304', '/var/1wire/']) except: pilib.log(pilib.syslog, 'boot: error running owfs', 1, pilib.sysloglevel) pilib.log(pilib.syslog, 'boot: Running owhttpd/owserver mount', 3, pilib.sysloglevel) try: subprocess.call(['/opt/owfs/bin/owhttpd', '-F', '-s', '4304', '-p', '4305']) except: pilib.log(pilib.syslog, 'boot: error running owhttpd', 1, pilib.sysloglevel) else: pilib.log(pilib.syslog, 'boot: not running owfs', 3, pilib.sysloglevel) # Run netstart script if enabled if systemstatus['netconfigenabled']: from netconfig import runconfig pilib.log(pilib.syslog, 'boot: running boot netconfig', 2, pilib.sysloglevel) runconfig(onboot=True) # Run daemon from cupiddaemon import rundaemon rundaemon() # Update hardware version in table from systemstatus import readhardwarefileintoversions readhardwarefileintoversions()
def application(environ, start_response): import cgi import json import os, sys, inspect # Set top folder to allow import of modules top_folder = os.path.split( os.path.realpath( os.path.abspath( os.path.split(inspect.getfile(inspect.currentframe()))[0])))[0] if top_folder not in sys.path: sys.path.insert(0, top_folder) from cupid import pilib, controllib from iiutilities import dblib, utility, datalib # post_env = environ.copy() # post_env['QUERY_STRING'] = '' # post = cgi.FieldStorage( # fp=environ['wsgi.input'], # environ=post_env, # keep_blank_values=True # ) # # formname=post.getvalue('name') # output = {} # output['message'] = 'Output Message: ' # for k in post.keys(): # d[k] = post.getvalue(k) try: request_body_size = int(environ.get('CONTENT_LENGTH', 0)) except ValueError: request_body_size = 0 request_body = environ['wsgi.input'].read(request_body_size) post = json.loads(request_body.decode('utf-8')) output = {} output['message'] = '' status = '200 OK' wsgiauth = True authverified = False if wsgiauth: # Verfiy that session login information is legit: hashed password, with salt and username, match # hash stored in database. import hashlib safe_database = dblib.sqliteDatabase(pilib.dirs.dbs.users) if 'username' in post and post['username']: output['message'] += 'Session user is ' + post['username'] + '. ' else: output['message'] += 'No session user found. ' post['username'] = '' if post['username']: try: condition = "name='" + post['username'] + "'" user_data = safe_database.read_table_row( 'users', condition=condition)[0] except: output[ 'message'] += 'Error in user sqlite query for session user "' + post[ 'username'] + '". ' output[ 'message'] += 'Condition: ' + condition + '. Path: ' + pilib.dirs.dbs.safe user_data = {'accesskeywords': 'demo', 'admin': False} else: # Get session hpass to verify credentials hashedpassword = post['hpass'] hname = hashlib.new('sha1') hname.update(post['username']) hashedname = hname.hexdigest() hentry = hashlib.new('md5') hentry.update(hashedname + pilib.salt + hashedpassword) hashedentry = hentry.hexdigest() if hashedentry == user_data['password']: # successful auth output['message'] += 'Password verified. ' authverified = True # TODO: implement usermeta else: # Demo status authverified = True user_data = {'authlevel': 0} else: output['message'] += 'WSGI authorization not enabled. ' if authverified or not wsgiauth: output['authorized'] = True try: action = post['action'] except KeyError: output['message'] = 'no action in request' action = '' else: output['message'] += '{} action keyword found'.format(action) if output['authorized'] and action: output['action_allowed'] = pilib.check_action_auths( action, user_data['authlevel']) else: output['action_allowed'] = False if output['authorized'] and output['action_allowed']: output['message'] += 'Found action. ' if action == 'testdbvn': from iiutilities.dblib import dbvntovalue try: output['data'] = dbvntovalue(post['dbvn']) except: output['message'] += 'Error in dbvn evaluation. ' output['data'] = 'error' else: output['message'] += 'Seems to have worked out. ' elif action == 'testlogical': from iiutilities.datalib import evaldbvnformula try: output['data'] = evaldbvnformula(post['logical']) except: output['message'] += 'Error in logical evaluation. ' output['data'] = 'error' else: output['message'] += 'Seems to have worked out. ' elif action == 'testmodule': output['message'] += 'Testing module: ' if 'modulename' in post: import cupid.cupidunittests output['message'] += post['modulename'] output['data'] = cupid.cupidunittests.testmodule( post['modulename']) else: output['message'] += 'Modulename not found. ' elif action == 'testfunction': output['message'] += 'Testing function: ' if 'testname' in post: import cupid.cupidunittests output['message'] += post['testname'] # output['data'] = cupid.tests.testfunction(d['testname']) output['data'] = cupid.cupidunittests.testfunction( post['testname']) # output['data'] = str(cupid.tests.testfunction('systemstatus')) else: output['message'] += 'Testname not found. ' elif action == 'modifychannelalarm': controllib.handle_modify_channel_alarm(post, output) from cupid.actions import processactions # process only this action. processactions(name=post['actionname']) elif action == 'modifychannel': controllib.handle_modify_channel(post, output) elif action == 'getalarmscount': control_db = dblib.sqliteDatabase(pilib.dirs.dbs.control) actions = control_db.read_table('actions') output['data'] = { 'totalalarms': len(actions), 'channelalarms': 0, 'activealarms': 0, 'activechannelalarms': 0 } for action in actions: if action['conditiontype'] == 'channel': output['data']['channelalarms'] += 1 if action['active']: output['data']['activechannelalarms'] += 1 if action['active']: output['data']['activealarms'] += 1 elif action == 'copy_log_to_archive': pilib.app_copy_log_to_archive(post, output) elif action == 'getlogscount': logtablenames = dblib.sqliteDatabase( pilib.dirs.dbs.log).get_table_names() output['data'] = {'logscount': len(logtablenames)} elif action == 'test_action': output['message'] += 'Testing action. ' controldb = dblib.sqliteDatabase(pilib.dirs.dbs.control) actiondict = controldb.read_table('actions', condition='"name"=\'' + post['actionname'] + "'")[0] from cupid.actions import action test_action = action(actiondict) test_action.test() elif action == 'update_network': safe_database = dblib.sqliteDatabase(pilib.dirs.dbs.safe) safe_database.set_single_value('wireless', 'password', post['password'], "SSID='" + post['ssid'] + "'") elif action == 'add_network': safe_database = dblib.sqliteDatabase(pilib.dirs.dbs.safe) insert = {'SSID': post['ssid'], 'auto': 1, 'priority': 1} if 'password' in post: insert['password'] = post['password'] safe_database.insert('wireless', insert) elif action == 'delete_network': safe_database = dblib.sqliteDatabase(pilib.dirs.dbs.safe) safe_database.delete('wireless', "SSID='" + post['ssid'] + "'") # elif action == 'dump': # # this has to go. # if 'database' in d: # dbpath = pilib.dbnametopath(d['database']) # if dbpath: # if 'tablelist' in d and 'outputfile' in d: # dbpath = pilib.dbnametopath(d['database']) # dblib.sqlitedatadump(dbpath, d['tablelist'], d['outputfile']) # output['message'] = 'data dumped' # elif 'tablename' in d and 'outputfile' in d: # dblib.sqlitedatadump(dbpath, [d['tablename']], d['outputfile']) # output['message'] = 'data dumped. ' # else: # output['message'] += 'keys not present for dump. ' # else: # output['message'] += 'keys not present for dump. ' # else: # output['message'] += 'keys not present for dump. ' elif action in ['userdelete', 'useradd', 'usermodify']: """ This needs to be consolidate with the other useradd, modify algorithm written already. Probably do this when we update the user permissions interface. """ # Ensure that we are authorized for this action if action == 'userdelete': try: dblib.sqlitequery( pilib.dirs.dbs.users, "delete from users where name='" + post['usertodelete'] + "'") except: output['message'] += 'Error in delete query. ' else: output['message'] += 'Successful delete query. ' elif action == 'usermodify': if 'usertomodify' in post: querylist = [] if 'newpass' in post: from pilib import salt # Get session hpass to verify credentials hashedpassword = post['newpass'] hname = hashlib.new('sha1') hname.update(post['usertomodify']) hashedname = hname.hexdigest() hentry = hashlib.new('md5') hentry.update(hashedname + salt + hashedpassword) hashedentry = hentry.hexdigest() querylist.append('update users set password='******'" + post['usertomodify'] + "'") if 'newemail' in post: querylist.append("update users set email='" + post['newemail'] + "' where name='" + post['usertomodify'] + "'") if 'newauthlevel' in post: querylist.append("update users set authlevel='" + post['newauthlevel'] + "' where name='" + post['usertomodify'] + "'") try: dblib.sqlitemultquery(pilib.dirs.dbs.users, querylist) except: output[ 'message'] += 'Error in modify/add query: ' + ",".join( querylist) else: output[ 'message'] += 'Successful modify/add query. ' + ",".join( querylist) else: output['message'] += 'Need usertomodify in query. ' elif action == 'useradd': try: username = post['newusername'] except: username = '******' try: newemail = post['newemail'] except: newemail = '*****@*****.**' try: newauthlevel = post['newauthlevel'] except: newauthlevel = 0 query = "insert into users values(NULL,'" + username + "','','" + newemail + "',''," + str( newauthlevel) + ")" try: dblib.sqlitequery(pilib.dirs.dbs.users, query) except: output[ 'message'] += "Error in useradd sqlite query: " + query + ' . ' else: output['message'] += "Successful query: " + query + ' . ' elif action == 'getfiletext': try: filepath = post['filepath'] if 'numlines' in post: numlines = int(post['numlines']) else: numlines = 9999 output['message'] += 'Using numlines: ' + str( numlines) + ' for read action. ' if 'startposition' in post: startposition = post['startposition'] else: startposition = 'end' output[ 'message'] += 'Reading from position ' + startposition + '. ' except KeyError: output[ 'message'] += 'Sufficient keys for action getfile text do not exist. ' except: output['message'] += 'Uncaught error in getfiletext. ' else: try: file = open(filepath) lines = file.readlines() except: output[ 'message'] += 'Error reading file in getfiletext action. ' else: output['data'] = [] if startposition == 'end': try: output['data'] = datalib.tail(file, numlines)[0] except: output['message'] += 'Error in tail read. ' else: linecount = 0 for line in lines: linecount += 1 if linecount > numlines: break else: output['data'].append(line) elif action == 'getmbtcpdata': try: clientIP = post['clientIP'] register = post['register'] length = post['length'] except KeyError: output[ 'message'] += 'Sufficient keys do not exist for the command. Requires clientIP, register, and length. ' else: from iiutilities.netfun import readMBcodedaddresses # try: output['response'] = readMBcodedaddresses( clientIP, int(register), int(length)) elif action == 'queuemessage': output['message'] += 'Queue message. ' if 'message' in post: try: dblib.sqliteinsertsingle( pilib.dirs.dbs.motes, 'queuedmessages', [datalib.gettimestring(), post['message']]) except: import traceback exc_type, exc_value, exc_traceback = sys.exc_info() output[ 'message'] += 'Error in queue insert query: {}. '.format( traceback.format_exc()) else: output['message'] += 'Message insert successful' else: output['message'] += 'No message present. ' elif action == 'setsystemflag' and 'systemflag' in post: database = pilib.dirs.dbs.system dblib.setsinglevalue(database, 'systemflags', 'value', 1, "name=\'" + post['systemflag'] + "'") elif action == 'rundaemon': from cupiddaemon import rundaemon rundaemon() # TODO: Eliminate this scary thing. elif action == 'setvalue': utility.log(pilib.dirs.logs.control, "Setting value in wsgi", 1, 1) # we use the auxiliary 'setsinglecontrolvalue' to add additional actions to update if all(k in post for k in ('database', 'table', 'valuename', 'value')): dbpath = pilib.dbnametopath(post['database']) if dbpath: output[ 'message'] += 'Carrying out setvalue for value ' + post[ 'valuename'] + ' on ' + post[ 'table'] + ' in ' + dbpath if 'condition' in post: pilib.setsinglecontrolvalue(dbpath, post['table'], post['valuename'], post['value'], post['condition']) elif 'index' in post: condition = 'rowid= ' + post['index'] pilib.setsinglecontrolvalue(dbpath, post['table'], post['valuename'], post['value'], condition) else: pilib.setsinglecontrolvalue(dbpath, post['table'], post['valuename'], post['value']) else: output[ 'message'] += 'Problem translating dbpath from friendly name: ' + post[ 'database'] else: output['message'] += 'Insufficient data for setvalue ' elif action == 'updateioinfo': if all(k in post for k in ['database', 'ioid', 'value']): query = dblib.makesqliteinsert('ioinfo', [post['ioid'], post['value']], ['id', 'name']) try: dblib.sqlitequery(pilib.dirs.dbs.control, query) except: output[ 'message'] += 'Error in updateioinfo query execution: ' + query + '. into database: ' + pilib.dirs.dbs.control output['message'] += 'ioid: ' + post['ioid'] + ' . ' else: output['message'] += 'Executed updateioinfo query. ' else: output[ 'message'] += 'Insufficient data for updateioinfo query ! ' # TODO: properly incorporate and test channel class functions here, and then sub it. elif action == 'modify_channel': controllib.app_modify_channel(post, output) elif action == 'deletechannelbyname' and 'database' in post and 'channelname' in post: dbpath = pilib.dbnametopath(post['database']) dblib.sqlitequery( dbpath, 'delete channelname from channels where name=\"' + post['channelname'] + '\"') elif action == 'updatecameraimage': output['message'] += 'Take camera image keyword. ' import cupid.camera if 'width' in post: width = post['width'] else: width = 800 try: values = cupid.camera.takesnap(width=width) except: output['message'] += 'Error taking image. ' else: output['message'] += 'Appears successful. Path : ' + values[ 'imagepath'] + '. Timestamp : ' + values['timestamp'] + '. ' output['data'] = values elif action == 'getcurrentcamtimestamp': output['message'] += 'getcurrentcamtimestamp keyword found. ' try: with open('/var/www/webcam/images/current.jpg.timestamp') as f: data = f.read() except: output['message'] += 'Error reading file as requested. ' else: output['data'] = data else: output[ 'message'] += 'Action keyword present(' + action + '), but not handled. ' else: output[ 'message'] += 'Authentication unsuccessful or action not authorized.' status = '401 Not Authorized' foutput = json.dumps(output, indent=1) response_headers = [('Content-type', 'application/json')] start_response(status, response_headers) return [foutput]
def application(environ, start_response): import cgi import json import os, sys, inspect # Set top folder to allow import of modules top_folder = os.path.split(os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0])))[0] if top_folder not in sys.path: sys.path.insert(0,top_folder) from cupid import pilib, controllib from iiutilities import dblib, utility, datalib # post_env = environ.copy() # post_env['QUERY_STRING'] = '' # post = cgi.FieldStorage( # fp=environ['wsgi.input'], # environ=post_env, # keep_blank_values=True # ) # # formname=post.getvalue('name') # output = {} # output['message'] = 'Output Message: ' # for k in post.keys(): # d[k] = post.getvalue(k) try: request_body_size = int(environ.get('CONTENT_LENGTH', 0)) except ValueError: request_body_size = 0 request_body = environ['wsgi.input'].read(request_body_size) post = json.loads(request_body.decode('utf-8')) output = {} output['message'] = '' status = '200 OK' wsgiauth = True authverified = False if wsgiauth: # Verfiy that session login information is legit: hashed password, with salt and username, match # hash stored in database. import hashlib safe_database = dblib.sqliteDatabase(pilib.dirs.dbs.users) if 'username' in post and post['username']: output['message'] += 'Session user is ' + post['username'] + '. ' else: output['message'] += 'No session user found. ' post['username'] = '' if post['username']: try: condition = "name='" + post['username'] + "'" user_data = safe_database.read_table_row('users', condition=condition)[0] except: output['message'] += 'Error in user sqlite query for session user "' + post['username'] + '". ' output['message'] += 'Condition: ' + condition + '. Path: ' + pilib.dirs.dbs.safe user_data = {'accesskeywords': 'demo', 'admin': False} else: # Get session hpass to verify credentials hashedpassword = post['hpass'] hname = hashlib.new('sha1') hname.update(post['username']) hashedname = hname.hexdigest() hentry = hashlib.new('md5') hentry.update(hashedname + pilib.salt + hashedpassword) hashedentry = hentry.hexdigest() if hashedentry == user_data['password']: # successful auth output['message'] += 'Password verified. ' authverified = True # TODO: implement usermeta else: # Demo status authverified = True user_data = {'authlevel':0} else: output['message'] += 'WSGI authorization not enabled. ' if authverified or not wsgiauth: output['authorized'] = True try: action = post['action'] except KeyError: output['message'] = 'no action in request' action = '' else: output['message'] += '{} action keyword found'.format(action) if output['authorized'] and action: output['action_allowed'] = pilib.check_action_auths(action, user_data['authlevel']) else: output['action_allowed'] = False if output['authorized'] and output['action_allowed']: output['message'] += 'Found action. ' if action == 'testdbvn': from iiutilities.dblib import dbvntovalue try: output['data'] = dbvntovalue(post['dbvn']) except: output['message'] += 'Error in dbvn evaluation. ' output['data'] = 'error' else: output['message'] += 'Seems to have worked out. ' elif action == 'testlogical': from iiutilities.datalib import evaldbvnformula try: output['data'] = evaldbvnformula(post['logical']) except: output['message'] += 'Error in logical evaluation. ' output['data'] = 'error' else: output['message'] += 'Seems to have worked out. ' elif action == 'testmodule': output['message'] += 'Testing module: ' if 'modulename' in post: import cupid.cupidunittests output['message'] += post['modulename'] output['data'] = cupid.cupidunittests.testmodule(post['modulename']) else: output['message'] += 'Modulename not found. ' elif action == 'testfunction': output['message'] += 'Testing function: ' if 'testname' in post: import cupid.cupidunittests output['message'] += post['testname'] # output['data'] = cupid.tests.testfunction(d['testname']) output['data'] = cupid.cupidunittests.testfunction(post['testname']) # output['data'] = str(cupid.tests.testfunction('systemstatus')) else: output['message'] += 'Testname not found. ' elif action == 'modifychannelalarm': controllib.handle_modify_channel_alarm(post, output) from cupid.actions import processactions # process only this action. processactions(name=post['actionname']) elif action == 'modifychannel': controllib.handle_modify_channel(post, output) elif action == 'getalarmscount': control_db = dblib.sqliteDatabase(pilib.dirs.dbs.control) actions = control_db.read_table('actions') output['data'] = {'totalalarms':len(actions),'channelalarms':0, 'activealarms':0, 'activechannelalarms':0} for action in actions: if action['conditiontype'] == 'channel': output['data']['channelalarms'] += 1 if action['active']: output['data']['activechannelalarms'] += 1 if action['active']: output['data']['activealarms'] += 1 elif action == 'copy_log_to_archive': pilib.app_copy_log_to_archive(post, output) elif action == 'getlogscount': logtablenames = dblib.sqliteDatabase(pilib.dirs.dbs.log).get_table_names() output['data'] = {'logscount':len(logtablenames)} elif action == 'test_action': output['message'] += 'Testing action. ' controldb = dblib.sqliteDatabase(pilib.dirs.dbs.control) actiondict = controldb.read_table('actions',condition='"name"=\'' + post['actionname'] + "'")[0] from cupid.actions import action test_action = action(actiondict) test_action.test() elif action == 'update_network': safe_database = dblib.sqliteDatabase(pilib.dirs.dbs.safe) safe_database.set_single_value('wireless', 'password', post['password'], "SSID='" + post['ssid'] + "'") elif action == 'add_network': safe_database = dblib.sqliteDatabase(pilib.dirs.dbs.safe) insert = {'SSID':post['ssid'], 'auto':1, 'priority':1} if 'password' in post: insert['password'] = post['password'] safe_database.insert('wireless',insert) elif action == 'delete_network': safe_database = dblib.sqliteDatabase(pilib.dirs.dbs.safe) safe_database.delete('wireless', "SSID='" + post['ssid'] + "'") # elif action == 'dump': # # this has to go. # if 'database' in d: # dbpath = pilib.dbnametopath(d['database']) # if dbpath: # if 'tablelist' in d and 'outputfile' in d: # dbpath = pilib.dbnametopath(d['database']) # dblib.sqlitedatadump(dbpath, d['tablelist'], d['outputfile']) # output['message'] = 'data dumped' # elif 'tablename' in d and 'outputfile' in d: # dblib.sqlitedatadump(dbpath, [d['tablename']], d['outputfile']) # output['message'] = 'data dumped. ' # else: # output['message'] += 'keys not present for dump. ' # else: # output['message'] += 'keys not present for dump. ' # else: # output['message'] += 'keys not present for dump. ' elif action in ['userdelete', 'useradd', 'usermodify']: """ This needs to be consolidate with the other useradd, modify algorithm written already. Probably do this when we update the user permissions interface. """ # Ensure that we are authorized for this action if action == 'userdelete': try: dblib.sqlitequery(pilib.dirs.dbs.users, "delete from users where name='" + post['usertodelete'] + "'") except: output['message'] += 'Error in delete query. ' else: output['message'] += 'Successful delete query. ' elif action == 'usermodify': if 'usertomodify' in post: querylist=[] if 'newpass' in post: from pilib import salt # Get session hpass to verify credentials hashedpassword = post['newpass'] hname = hashlib.new('sha1') hname.update(post['usertomodify']) hashedname = hname.hexdigest() hentry = hashlib.new('md5') hentry.update(hashedname + salt + hashedpassword) hashedentry = hentry.hexdigest() querylist.append('update users set password='******'" + post['usertomodify'] + "'") if 'newemail' in post: querylist.append("update users set email='" + post['newemail'] + "' where name='" + post['usertomodify'] + "'") if 'newauthlevel' in post: querylist.append("update users set authlevel='" + post['newauthlevel'] + "' where name='" + post['usertomodify'] + "'") try: dblib.sqlitemultquery(pilib.dirs.dbs.users, querylist) except: output['message'] += 'Error in modify/add query: ' + ",".join(querylist) else: output['message'] += 'Successful modify/add query. ' + ",".join(querylist) else: output['message'] += 'Need usertomodify in query. ' elif action == 'useradd': try: username = post['newusername'] except: username = '******' try: newemail = post['newemail'] except: newemail = '*****@*****.**' try: newauthlevel = post['newauthlevel'] except: newauthlevel = 0 query = "insert into users values(NULL,'" + username + "','','" + newemail + "',''," + str(newauthlevel) + ")" try: dblib.sqlitequery(pilib.dirs.dbs.users, query) except: output['message'] += "Error in useradd sqlite query: " + query + ' . ' else: output['message'] += "Successful query: " + query + ' . ' elif action == 'getfiletext': try: filepath = post['filepath'] if 'numlines' in post: numlines = int(post['numlines']) else: numlines = 9999 output['message'] += 'Using numlines: ' + str(numlines) + ' for read action. ' if 'startposition' in post: startposition = post['startposition'] else: startposition = 'end' output['message'] += 'Reading from position ' + startposition + '. ' except KeyError: output['message'] += 'Sufficient keys for action getfile text do not exist. ' except: output['message'] += 'Uncaught error in getfiletext. ' else: try: file = open(filepath) lines = file.readlines() except: output['message'] += 'Error reading file in getfiletext action. ' else: output['data'] = [] if startposition == 'end': try: output['data'] = datalib.tail(file, numlines)[0] except: output['message'] += 'Error in tail read. ' else: linecount = 0 for line in lines: linecount += 1 if linecount > numlines: break else: output['data'].append(line) elif action == 'getmbtcpdata': try: clientIP = post['clientIP'] register = post['register'] length = post['length'] except KeyError: output['message'] += 'Sufficient keys do not exist for the command. Requires clientIP, register, and length. ' else: from iiutilities.netfun import readMBcodedaddresses # try: output['response'] = readMBcodedaddresses(clientIP, int(register), int(length)) elif action == 'queuemessage': output['message'] += 'Queue message. ' if 'message' in post: try: dblib.sqliteinsertsingle(pilib.dirs.dbs.motes, 'queuedmessages', [datalib.gettimestring(), post['message']]) except: import traceback exc_type, exc_value, exc_traceback = sys.exc_info() output['message'] += 'Error in queue insert query: {}. '.format(traceback.format_exc()) else: output['message'] += 'Message insert successful' else: output['message'] += 'No message present. ' elif action == 'setsystemflag' and 'systemflag' in post: database = pilib.dirs.dbs.system dblib.setsinglevalue(database, 'systemflags', 'value', 1, "name=\'" + post['systemflag'] + "'") elif action == 'rundaemon': from cupiddaemon import rundaemon rundaemon() # TODO: Eliminate this scary thing. elif action == 'setvalue': utility.log(pilib.dirs.logs.control, "Setting value in wsgi", 1, 1) # we use the auxiliary 'setsinglecontrolvalue' to add additional actions to update if all(k in post for k in ('database', 'table', 'valuename', 'value')): dbpath = pilib.dbnametopath(post['database']) if dbpath: output['message'] += 'Carrying out setvalue for value ' + post['valuename'] + ' on ' + post['table'] + ' in ' + dbpath if 'condition' in post: pilib.setsinglecontrolvalue(dbpath, post['table'], post['valuename'], post['value'], post['condition']) elif 'index' in post: condition = 'rowid= ' + post['index'] pilib.setsinglecontrolvalue(dbpath, post['table'], post['valuename'], post['value'], condition) else: pilib.setsinglecontrolvalue(dbpath, post['table'], post['valuename'], post['value']) else: output['message'] += 'Problem translating dbpath from friendly name: ' + post['database'] else: output['message'] += 'Insufficient data for setvalue ' elif action == 'updateioinfo': if all(k in post for k in ['database', 'ioid', 'value']): query = dblib.makesqliteinsert('ioinfo', [post['ioid'], post['value']], ['id', 'name']) try: dblib.sqlitequery(pilib.dirs.dbs.control, query) except: output['message'] += 'Error in updateioinfo query execution: ' + query +'. into database: ' + pilib.dirs.dbs.control output['message'] += 'ioid: ' + post['ioid'] + ' . ' else: output['message'] += 'Executed updateioinfo query. ' else: output['message'] += 'Insufficient data for updateioinfo query ! ' # TODO: properly incorporate and test channel class functions here, and then sub it. elif action == 'modify_channel': controllib.app_modify_channel(post, output) elif action == 'deletechannelbyname' and 'database' in post and 'channelname' in post: dbpath = pilib.dbnametopath(post['database']) dblib.sqlitequery(dbpath, 'delete channelname from channels where name=\"' + post['channelname'] + '\"') elif action == 'updatecameraimage': output['message'] += 'Take camera image keyword. ' import cupid.camera if 'width' in post: width = post['width'] else: width = 800 try: values = cupid.camera.takesnap(width=width) except: output['message'] += 'Error taking image. ' else: output['message'] += 'Appears successful. Path : ' + values['imagepath'] + '. Timestamp : ' + values['timestamp'] + '. ' output['data'] = values elif action == 'getcurrentcamtimestamp': output['message'] += 'getcurrentcamtimestamp keyword found. ' try: with open('/var/www/webcam/images/current.jpg.timestamp') as f: data = f.read() except: output['message'] += 'Error reading file as requested. ' else: output['data'] = data else: output['message'] += 'Action keyword present(' + action + '), but not handled. ' else: output['message'] += 'Authentication unsuccessful or action not authorized.' status = '401 Not Authorized' foutput = json.dumps(output, indent=1) response_headers = [('Content-type', 'application/json')] start_response(status, response_headers) return [foutput]