Пример #1
0
def parsedbvn(dbvn):

    from cupid import pilib
    # print('DBVN: ')
    # print(dbvn)
    """
    databasename:tablename:valuename:condition
    """

    split = dbvn.split(':')
    dbname = split[0].strip()
    dbpath = pilib.dbnametopath(dbname)
    if not dbpath:
        # print("error getting dbpath, for dbname: " + dbname)
        return None

    tablename = split[1].strip()
    valuename = split[2].strip()

    # Have to beware of conditions with colons in them.
    if len(split) == 4:
        condition = split[3]
    elif len(split) > 4:
        condition = ':'.join(split[3:])
    else:
        condition = None

    return {
        'dbname': dbname,
        'dbpath': dbpath,
        'tablename': tablename,
        'valuename': valuename,
        'condition': condition
    }
Пример #2
0
def parsedbvn(dbvn):

    from cupid import pilib
    # print('DBVN: ')
    # print(dbvn)
    """
    databasename:tablename:valuename:condition
    """

    split = dbvn.split(':')
    dbname = split[0].strip()
    dbpath = pilib.dbnametopath(dbname)
    if not dbpath:
        # print("error getting dbpath, for dbname: " + dbname)
        return None

    tablename = split[1].strip()
    valuename = split[2].strip()

    # Have to beware of conditions with colons in them.
    if len(split) == 4:
        condition = split[3]
    elif len(split) > 4:
        condition = ':'.join(split[3:])
    else:
        condition = None

    return {'dbname':dbname,'dbpath':dbpath,'tablename':tablename,'valuename':valuename,'condition':condition}
Пример #3
0
def updatehardwareinfo(databasename='systemdb'):
    from subprocess import check_output
    from cupid import pilib
    from iiutilities import datalib
    from iiutilities import dblib
    import json

    data = check_output(['cat', '/proc/cpuinfo']).decode('utf-8')
    items = data.split('\n')
    hw_dict = {}
    for item in items:
        try:
            hw_dict[item.split(':')[0].strip()] = item.split(':')[1].strip()
        except:
            pass

    # print('HW DICT')
    # print(hw_dict)

    dictstring = json.dumps(hw_dict)
    dbpath = None
    try:
        dbpath = pilib.dbnametopath(databasename)
        # print(dbpath)
    except:
        pass

    if dbpath:
        time = datalib.gettimestring()
        dblib.sqliteinsertsingle(
            dbpath,
            'versions',
            ['cpuinfo', dictstring, time, ''],
            ['item', 'version', 'updatetime', 'versiontime'],
        )

    if 'Revision' in hw_dict and dbpath:
        versiondetail = piversiontoversionname(hw_dict['Revision'])
        dblib.sqliteinsertsingle(
            dbpath,
            'versions',
            ['versionname', versiondetail['versionname'], time, ''],
            ['item', 'version', 'updatetime', 'versiontime'],
        )
        dblib.sqliteinsertsingle(
            dbpath,
            'versions',
            ['memory', versiondetail['memory'], time, ''],
            ['item', 'version', 'updatetime', 'versiontime'],
        )
    return dictstring
Пример #4
0
def updatehardwareinfo(databasename='systemdb'):
    from subprocess import check_output
    from cupid import pilib
    from iiutilities import datalib
    from iiutilities import dblib
    import json

    data = check_output(['cat','/proc/cpuinfo']).decode('utf-8')
    items = data.split('\n')
    hw_dict = {}
    for item in items:
        try:
            hw_dict[item.split(':')[0].strip()] = item.split(':')[1].strip()
        except:
            pass

    # print('HW DICT')
    # print(hw_dict)

    dictstring = json.dumps(hw_dict)
    dbpath = None
    try:
        dbpath = pilib.dbnametopath(databasename)
        # print(dbpath)
    except:
        pass

    if dbpath:
        time = datalib.gettimestring()
        dblib.sqliteinsertsingle(dbpath,'versions',['cpuinfo', dictstring, time, ''],['item', 'version', 'updatetime', 'versiontime'],)

    if 'Revision' in hw_dict and dbpath:
        versiondetail = piversiontoversionname(hw_dict['Revision'])
        dblib.sqliteinsertsingle(dbpath, 'versions', ['versionname', versiondetail['versionname'], time, ''],['item', 'version', 'updatetime', 'versiontime'],)
        dblib.sqliteinsertsingle(dbpath, 'versions', ['memory', versiondetail['memory'], time, ''],['item', 'version', 'updatetime', 'versiontime'],)
    return dictstring
Пример #5
0
def application(environ, start_response):
    import cgi
    import json
    import hashlib

    # Set top folder to allow import of modules

    import os, sys, inspect

    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.pilib import dynamicsqliteread, gettablenames, sqlitequery, switchtablerows, dbnametopath
    from time import time

    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 = {}
    d = {}
    for k in post.keys():
        d[k] = post.getvalue(k)

    status = '200 OK'
    # Run stuff as requested
    # We use the dynamic function to allow various  
    # types of queries
    output['data'] = []
    output['message'] = ''


    # Need to do auths in here.

    try:
        action = d['action']
    except KeyError:
        output['message'] = 'no action in request'
    else:
        if action == 'gettablenames':
            dbpath = dbnametopath(d['database'])
            try:
                output['data'] = gettablenames(dbpath)
            except:
                output['message'] += 'Error getting table names'
        elif action == 'switchtablerows':
            dbpath = dbnametopath(d['database'])
            switchtablerows(dbpath, d['tablename'], d['row1'], d['row2'], d['uniqueindex'])
        elif action == 'modwsgistatus':
            output['processgroup'] = repr(environ['mod_wsgi.process_group'])
            output['multithread'] = repr(environ['wsgi.multithread'])
        elif action == 'gettabledata':
            output['message']+='Gettabledata. '
            if 'database' in d:
                dbpath = dbnametopath(d['database'])
                if dbpath:
                    output['message'] += 'Friendly name ' + d['database'] + ' translated to path ' + dbpath + ' successfully. '

                    if 'tablenames[]' in d:  # Get multiple tables
                        output['message'] += 'Multiple tables. '
                        data = []
                        if 'start' in d:
                            fixedstart = int(d['start'])
                        else:
                            fixedstart = 0
                        if 'length' in d:
                            fixedlength = int(d['length'])
                        else:
                            fixedlength = 1
                        if 'lengths[]' in d:
                            lengths = map(int, d['lengths[]'])
                        else:
                            lengths = []
                        if 'starts[]' in d:
                            starts = map(int, d['starts'])
                        else:
                            starts = []

                        for index, table in enumerate(d['tablenames[]']):
                            try:
                                length = lengths[index]
                            except IndexError:
                                length = fixedlength
                            try:
                                start = starts[index]
                            except IndexError:
                                start = fixedstart

                            data.append(dynamicsqliteread(dbpath, table, start, length))
                            output['data']=data
                    elif 'length' in d:  # Handle table row subset
                        output['message']+='Length keyword. '
                        if not 'start' in d:
                            d['start'] = 0
                        thetime = time();
                        output['data'] = dynamicsqliteread(dbpath, d['tablename'], d['start'], d['length'])
                        output['querytime'] = time() - thetime
                    elif 'row' in d:  # Handle table row
                        output['message'] += 'Row keyword. ' + str(d['row'])
                        thetime = time();
                        output['data'] = dynamicsqliteread(dbpath, d['tablename'], d['row'])
                        output['querytime'] = time() - thetime
                    elif 'tablename' in d:  # Handle entire table
                        output['message'] += 'Tablename keyword: ' + d['tablename']
                        thetime = time();
                        if 'condition' in d:
                            if not d['condition'] == '':
                                output['data'] = dynamicsqliteread(dbpath, d['tablename'], condition=d['condition'])
                            else:
                                output['data'] = dynamicsqliteread(dbpath, d['tablename'])
                        else:
                            try:
                                output['data'] = dynamicsqliteread(dbpath, d['tablename'])
                            except:
                                output['message'] += 'Error retrieving data. '
                            else:
                                output['message'] += 'Data query appears successful. '
                        output['querytime'] = time() - thetime
                else:
                    output['message'] += 'Friendly name ' + d['database'] + ' unsuccessfully translated. '
            else:
                output['message'] += 'No database present in action request'
        else:
            output['message'] = 'no command matched for action ' + action

    if output['data']:
        newetag = hashlib.md5(str(output['data'])).hexdigest()
        if 'etag' in d:
            if newetag == d['etag']:
                status = '304 Not Modified'
                output['data'] = ''
    else:
        newetag=''

    if 'datasize' in d:
        output['datasize'] = sys.getsizeof(output['data'])

    output['etag'] = newetag

    foutput = json.dumps(output, indent=1)

    response_headers = [('Content-type', 'application/json')]
    response_headers.append(('Etag',newetag))
    start_response(status, response_headers)

    return [foutput]
Пример #6
0
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]
Пример #7
0
def application(environ, start_response):
    import cgi
    import json
    import hashlib

    # Set top folder to allow import of modules

    import os, sys, inspect

    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
    from iiutilities import dblib
    from time import time

    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)
    try:
        post = json.loads(request_body.decode('utf-8'))
    except:
        print('Error decoding: ')
        print(request_body.decode('utf-8'))
        post = {}

    output = {'message': ''}

    status = '200 OK'
    # Run stuff as requested
    # We use the dynamic function to allow various
    # types of queries
    output['data'] = []
    output['message'] = ''

    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']:
            condition = "name='" + post['username'] + "'"
            user_data = safe_database.read_table_row('users',
                                                     condition=condition)[0]

            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 {}'.format(condition)
                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:
        output['message'] += 'WSGI authorization not enabled. '
    if authverified or not wsgiauth:
        try:
            action = post['action']
        except KeyError:
            output['message'] = 'no action in request'
        else:
            if action == 'gettablenames':
                dbpath = pilib.dbnametopath(post['database'])
                try:
                    output['data'] = dblib.gettablenames(dbpath)
                except:
                    output['message'] += 'Error getting table names'
            elif action == 'modwsgistatus':
                output['processgroup'] = repr(
                    environ['mod_wsgi.process_group'])
                output['multithread'] = repr(environ['wsgi.multithread'])
            elif action == 'gettabledata':
                output['message'] += 'Gettabledata. '
                if 'database' in post:
                    dbpath = pilib.dbnametopath(post['database'])
                    if dbpath:
                        output['message'] += 'Friendly name ' + post[
                            'database'] + ' translated to path ' + dbpath + ' successfully. '

                        the_database = dblib.sqliteDatabase(dbpath)
                        if 'tablenames' in post:  # Get multiple tables
                            output['message'] += 'Multiple tables. '
                            data = []
                            if 'start' in post:
                                fixedstart = int(post['start'])
                            else:
                                fixedstart = 0
                            if 'length' in post:
                                fixedlength = int(post['length'])
                            else:
                                fixedlength = 0
                            if 'lengths' in post:
                                lengths = map(int, post['lengths[]'])
                            else:
                                lengths = []
                            if 'starts' in post:
                                starts = map(int, post['starts'])
                            else:
                                starts = []

                            for index, table in enumerate(post['tablenames']):
                                output[
                                    'message'] += 'Reading table {}. '.format(
                                        table)
                                try:
                                    length = lengths[index]
                                except IndexError:
                                    length = fixedlength
                                try:
                                    start = starts[index]
                                except IndexError:
                                    start = fixedstart
                                if not fixedlength:  # get all rows if length not specified
                                    db_data = the_database.read_table(table)
                                else:
                                    db_data = the_database.read_table_rows(
                                        table, start, length)
                                output[
                                    'message'] += 'Read {} rows of data. '.format(
                                        len(db_data))
                                data.append(db_data)
                                output['data'] = data

                        elif 'length' in post:  # Handle table row subset
                            output['message'] += 'Length keyword. '
                            if not 'start' in post:
                                post['start'] = 0
                            thetime = time()
                            output['data'] = the_database.read_table_rows(
                                post['tablename'], post['start'],
                                post['length'])
                            output['querytime'] = time() - thetime
                        elif 'row' in post:  # Handle table row
                            output['message'] += 'Row keyword. ' + str(
                                post['row'])
                            thetime = time()
                            output['data'] = the_database.read_table_rows(
                                post['tablename'], post['row'])
                            output['querytime'] = time() - thetime
                        elif 'tablename' in post:  # Handle entire table
                            output[
                                'message'] += 'Tablename keyword: {}. '.format(
                                    post['tablename'])
                            thetime = time()
                            if 'condition' in post:
                                if not post['condition'] == '':
                                    output[
                                        'message'] += 'Condition : "{}" .'.format(
                                            post['condition'])
                                    output['data'] = the_database.read_table(
                                        post['tablename'],
                                        condition=post['condition'])
                                else:
                                    output['data'] = the_database.read_table(
                                        post['tablename'])
                            else:
                                try:
                                    output['data'] = the_database.read_table(
                                        post['tablename'])
                                except:
                                    output[
                                        'message'] += 'Error retrieving data. '
                                else:
                                    output[
                                        'message'] += 'Data query appears successful. '
                                    # output['message'] += str(output['data'][0])
                            output['querytime'] = time() - thetime

                    else:
                        output['message'] += 'Friendly name ' + post[
                            'database'] + ' unsuccessfully translated. '
                else:
                    output[
                        'message'] += 'No database present in action request'

            elif action == 'get_archive_info':
                from iiutilities.utility import get_directory_listing
                directory_list = get_directory_listing(pilib.dirs.archive)
                output['data'] = {}
                output['data']['lognames'] = []
                for filename in directory_list['filenames']:
                    if filename[-3:] == '.db':
                        output['data']['lognames'].append(filename[:-3])
                    else:
                        directory_list['filenames'].remove(filename)

                output['data']['metadata'] = []
                output['message'] += 'Retrieved db logs {}. '.format(
                    directory_list['filenames'])
                for filename, logname in zip(directory_list['filenames'],
                                             output['data']['lognames']):

                    archive_db = dblib.sqliteDatabase(pilib.dirs.archive +
                                                      filename)
                    try:
                        metadata = archive_db.read_table('metadata')[0]
                    except:
                        output[
                            'message'] += 'Error retrieving metadata for log table {}. '.format(
                                filename)
                        output['data']['metadata'].append({})
                    else:
                        metadata['name'] = logname
                        output['data']['metadata'].append(metadata)

            else:
                output['message'] = 'no command matched for action ' + action
    else:
        output['message'] += 'Authentication unsuccessful'

    if output['data']:
        newetag = hashlib.md5(str(output['data'])).hexdigest()
        if 'etag' in post:
            if newetag == post['etag']:
                status = '304 Not Modified'
                output['data'] = ''
    else:
        newetag = ''

    if 'datasize' in post:
        output['datasize'] = sys.getsizeof(output['data'])

    output['etag'] = newetag

    try:
        foutput = json.dumps(output, indent=1)
    except:
        print('*** THERE WAS AN ERROR DECODING DATA ***')
        print(output)
        foutput = json.dumps({'message': 'Error in json dumps'})

    response_headers = [('Content-type', 'application/json')]
    response_headers.append(('Etag', newetag))
    start_response(status, response_headers)

    return [foutput]
Пример #8
0
    def offact(self):
        from iiutilities import dblib, datalib, utility
        from cupid import pilib
        if self.actiontype == 'email':
            # process email action
            # TODO: This really needs to queue the email action in case we are not online.
            self.statusmsg +='Processing email alert.'
            email = self.actiondetail
            # message = 'Alert has gone inactive for ' + self.name + '. Criterion ' + self.variablename + ' in ' + self.tablename + ' has value ' + str(self.variablevalue) + ' with a criterion of ' + str(self.criterion) + ' with an operator of ' + self.operator + '. This alarm status has been of since ' + self.offtime + '.'
            message = 'Alert for alarm ' + self.name + ' . Off time of ' + self.offtime + '. Current time of ' \
                      + datalib.gettimestring()
            if self.conditiontype == 'value':
                message += ' Value: ' + str(self.value) + self.actiondatadict['operator'] + str(
                    self.actiondatadict['criterion'])

            import socket
            hostname = socket.gethostname()

            subject = 'CuPID ' + hostname + ' Alert : Alarm Off - ' + self.name
            try:
                actionmail = utility.gmail(message=message, subject=subject, recipient=email)
                actionmail.send()
            except:
                self.statusmsg += 'Error sending email. '
            else:
                self.statusmsg += 'Mail sent. '

        elif self.actiontype == 'indicator':
            # process indicator action
            self.statusmsg +='Processing indicator off action.'
            indicatorname = self.actiondetail
            dblib.setsinglevalue(pilib.dirs.dbs.control, 'indicators', 'status', 0, 'name=\'' + indicatorname+ '\'')
            print('INDICATORNAME = "' + indicatorname + '"')
            # dblib.sqlitequery(pilib.dirs.dbs.control, 'update indicators set status=0 where name = ' + indicatorname)

        elif self.actiontype == 'output':
            self.statusmsg += 'Processing output off action. '
            dblib.setsinglevalue(pilib.dirs.dbs.control, 'outputs', 'value', '0', condition='"id"=\'' + self.actiondetail + "'")

        # This should be the generic handler that we migrate to
        elif self.actiontype == 'setvalue':
            # to set a value, we need at minimum:
            #   dbname, tablename, valuename, setmethod and either:
            #   setmethod = increment, incrementvalue=1
            #   setmethod = value
            dbvndict = datalib.parsedbvn(self.actiondetail)
            dbpath = pilib.dbnametopath(dbvndict['dbname'])
            # Special set formula?

            if 'setvalueformula' in self.actiondatadict:
                # Stuff that we don't know yet.
                dblib.setsinglevalue(dbpath, dbvndict['tablename'], dbvndict['valuename'], 'formulastuff here', dbvndict['condition'])
            else:

                """ TODO: Fix this hack. We cannot currently single quote in the database entry because it breaks the reinsert.
                So for now, we have to add quotes on either side of the string literal before executing the sqlite query. """
                if dbvndict['condition']:
                    querycondition = dbvndict['condition'].split('=')[0] + "='" + dbvndict['condition'].split('=')[1] + "'"
                    # print('FIXED CONDITION')
                    # print(querycondition)
                else:
                    querycondition = None
                dblib.setsinglevalue(dbpath, dbvndict['tablename'], dbvndict['valuename'], '0', querycondition)
Пример #9
0
    def onact(self):
        from iiutilities import dblib, datalib, utility
        from cupid import pilib

        if self.actiontype == 'email':
            # process email action
            self.statusmsg += 'Processing email alert. '
            email = self.actiondetail

            # Special messages
            if self.conditiontype == 'channel':
                message = 'Channel alarm for ' + self.name + ' is active with value of ' + str(self.value) + '. '
                if 'PV_low' in self.actiondatadict:
                    message += 'Low alarm: ' + str(self.actiondatadict['PV_low'] + '. ')
                if 'PV_high' in self.actiondatadict:
                    message += 'High alarm: ' + str(self.actiondatadict['PV_high'] + '. ')


            elif self.conditiontype == 'value':

                # message = 'Alert is active for ' + self.name + '. Criterion ' + self.variablename + ' in ' + self.tablename + ' has value ' + str(self.variablevalue) + ' with a criterion of ' + str(self.criterion) + ' with an operator of ' + self.operator + '. This alarm status has been on since ' + self.ontime + '.'
                message = 'Alert for alarm ' + self.name + ' . On time of ' + self.ontime + '. Current time of ' \
                          + datalib.gettimestring()

                message += ' Value: ' + str(self.value) + self.actiondatadict['operator'] + str(self.actiondatadict['criterion'])

            else:
                # message = 'Alert is active for ' + self.name + '. Criterion ' + self.variablename + ' in ' + self.tablename + ' has value ' + str(self.variablevalue) + ' with a criterion of ' + str(self.criterion) + ' with an operator of ' + self.operator + '. This alarm status has been on since ' + self.ontime + '.'
                message = 'Alert for alarm ' + self.name + ' . On time of ' + self.ontime + '. Current time of ' \
                          + datalib.gettimestring()
            import socket
            hostname = socket.gethostname()

            subject = 'CuPID ' + hostname + ' Alert : Alarm On - ' + self.name
            try:
                actionmail = utility.gmail(message=message, subject=subject, recipient=email)
                actionmail.send()
            except:
                self.statusmsg += 'Error sending email. '
            else:
                self.statusmsg += 'Mail sent. '

        elif self.actiontype == 'indicator':
            # process indicator action
            self.statusmsg += 'Processing indicator on action. '
            indicatorname = self.actiondetail
            dblib.sqlitequery(pilib.dirs.dbs.control, 'update indicators set status=1 where name = \'' + indicatorname + '\'')

        elif self.actiontype == 'output':
            self.statusmsg += 'Processing output on action. '
            dblib.setsinglevalue(pilib.dirs.dbs.control, 'outputs', 'value', '1', condition='"id"=\'' + self.actiondetail + "'")

        elif self.actiontype == 'mote_command':
            settings = {
                'no_duplicates':True,
                'retries':5
            }
            settings.update(self.actiondatadict)
            self.statusmsg += 'Processing command on action. '

            destination = self.actiondatadict['destination']
            message = self.actiondatadict['message']

            command_id = '{}_{}'.format(destination, message)
            command = {'queuedtime': datalib.gettimestring(), 'destination': destination,
                       'status': 'new', 'message': message, 'commandid':command_id,
                       }

            command['options'] = json.dumps({'retries':settings['retries']})

            insert = True
            if settings['no_duplicates']:
                # Check to see if commands exist with our command id.
                condition = "commandid='{}'".format(command_id)
                matching_commands = pilib.dbs.motes.read_table('commands',condition=condition)
                if matching_commands:
                    self.statusmsg += '{} matching commands are already queued. Not inserting. '.format(len(matching_commands))
                    insert = False

            if insert:
                self.statusmsg += 'Inserting command. '
                pilib.dbs.motes.settings['quiet'] = False
                pilib.dbs.motes.insert('commands',command)

        # This should be the generic handler that we migrate to
        elif self.actiontype == 'setvalue':
            # to set a value, we need at minimum:
            #   dbname, tablename, valuename, setmethod and either:
            #   setmethod = increment, incrementvalue=1
            #   setmethod = value
            dbvndict = datalib.parsedbvn(self.actiondetail)
            dbpath = pilib.dbnametopath(dbvndict['dbname'])
            # Special set formula?

            if 'setvalueformula' in self.actiondatadict:
                # Stuff that we don't know yet.
                dblib.setsinglevalue(dbpath, dbvndict['tablename'], dbvndict['valuename'], 'formulastuff here', dbvndict['condition'])
            else:

                """ TODO: Fix this hack. We cannot currently single quote in the database entry because it breaks the reinsert.
                So for now, we have to add quotes on either side of the string literal before executing the sqlite query. """
                if dbvndict['condition']:
                    querycondition = dbvndict['condition'].split('=')[0] + "='" + dbvndict['condition'].split('=')[1] + "'"
                    # print('FIXED CONDITION')
                    # print(querycondition)
                else:
                    querycondition = None
                dblib.setsinglevalue(dbpath, dbvndict['tablename'], dbvndict['valuename'], '1', querycondition)
Пример #10
0
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]