Esempio n. 1
0
def add_account_menu():
    menu_title("Add account")
    while 1:
        print('------')
        print('Notice')
        print('------')
        print('You are about to search for bank connection information')
        print('on a third party website.  This means you are trusting')
        print('http://ofxhome.com and their security policies.')
        print('')
        print('You will be sending your bank name to this website.')
        print('------')
        query = prompt('bank name eg. "express" (enter to exit)> ')
        if query.lower() in ['']:
            return

        found = OFXHome.search(query)
        if not found:
            error("No banks found")
            continue

        while 1:
            for idx, bank in enumerate(found):
                menu_item(idx, bank['name'])
            choice = prompt().lower()
            if choice in ['q', '']:
                return
            elif int(choice) < len(found):
                bank = OFXHome.lookup(found[int(choice)]['id'])
                if login_check_menu(bank):
                    return
Esempio n. 2
0
def add_account_menu(args):
    menu_title("Add account")
    while 1:
        print("------")
        print("Notice")
        print("------")
        print("You are about to search for bank connection information")
        print("on a third party website.  This means you are trusting")
        print("http://ofxhome.com and their security policies.")
        print("")
        print("You will be sending your bank name to this website.")
        print("------")
        query = prompt('bank name eg. "express" (enter to exit)> ')
        if query.lower() in [""]:
            return

        found = OFXHome.search(query)
        if not found:
            error("No banks found")
            continue

        while 1:
            for idx, bank in enumerate(found):
                menu_item(idx, bank["name"])
            choice = prompt().lower()
            if choice in ["q", ""]:
                return
            elif int(choice) < len(found):
                bank = OFXHome.lookup(found[int(choice)]["id"])
                if login_check_menu(bank, args):
                    return
Esempio n. 3
0
def add_account_menu(args):
    menu_title("Add account")
    while 1:
        print('------')
        print('Notice')
        print('------')
        print('You are about to search for bank connection information')
        print('on a third party website.  This means you are trusting')
        print('http://ofxhome.com and their security policies.')
        print('')
        print('You will be sending your bank name to this website.')
        print('------')
        query = prompt('bank name eg. "express" (enter to exit)> ')
        if query.lower() in ['']:
            return

        found = OFXHome.search(query)
        if not found:
            error("No banks found")
            continue

        while 1:
            for idx, bank in enumerate(found):
                menu_item(idx, bank['name'])
            choice = prompt().lower()
            if choice in ['q', '']:
                return
            elif int(choice) < len(found):
                bank = OFXHome.lookup(found[int(choice)]['id'])
                if login_check_menu(bank, args):
                    return
Esempio n. 4
0
    def add_bank(self, id=None, username=None, password=None):

        cherrypy.response.headers['Content-Type'] = 'application/json'
        cherrypy.response.status = 200

        result = {'status': 'ok', 'message': ''}
        if id and username and password:
            bank = OFXHome.lookup(id)
            i = Institution(id=bank['fid'],
                            org=bank['org'],
                            url=bank['url'],
                            broker_id=bank['brokerid'],
                            description=bank['name'],
                            username=username,
                            password=password)
            try:
                i.authenticate()
            except Exception as e:
                result['status'] = 'error'
                result[
                    'message'] = 'unable to log into bank with those credentials'

            for a in i.accounts():
                GlobalConfig.add_account(a)
            GlobalConfig.save()
        else:
            result['status'] = 'error'
            result['message'] = 'id, username, and password are all required'

        ret = json.dumps(result)
        cherrypy.response.body = ret
        if result['status'] == 'error':
            cherrypy.response.status = 400
        return ret
Esempio n. 5
0
def bank_config(guid):
    if bank_config_cache.has_key(guid):
        return bank_config_cache[guid]
    path = os.path.join( Settings.fi_cache(), '%s.xml' % guid )
    if not os.path.exists(path) or os.path.getsize(path) == 0:
        logging.info("uncached bank config %s" % guid)
        institution = OFXHome.lookup(guid)
        file = open(path,'w')
        file.write(institution.xml)
        file.close()
    logging.info("parsing file %s" % path)
    bank_config_cache[guid] = OFXHomeInstitution.from_file(path).__dict__
    return bank_config_cache[guid]
Esempio n. 6
0
def add_account_menu():
    menu_title("Add account")
    while 1:
        query = prompt('enter part of a bank name eg. express> ')
        if query.lower() in ['']:
            return

        found = OFXHome.search(query)
        if not found:
            error("No banks found")
            continue

        while 1:
            for idx, bank in enumerate(found):
                menu_item(idx, bank['name'])
            choice = prompt().lower()
            if choice in ['q', '']:
                return
            elif int(choice) < len(found):
                bank = OFXHome.lookup(found[int(choice)]['id'])
                if login_check_menu(bank):
                    return
Esempio n. 7
0
def add_account_menu():
    menu_title("Add account")
    while 1:
        query = prompt('enter part of a bank name eg. express> ')
        if query.lower() in ['']:
            return

        found = OFXHome.search(query)
        if not found:
            error("No banks found")
            continue

        while 1:
            for idx, bank in enumerate(found):
                menu_item(idx, bank['name'])
            choice = prompt().lower()
            if choice in ['q', '']:
                return
            elif int(choice) < len(found):
                bank = OFXHome.lookup(found[int(choice)]['id'])
                if login_check_menu(bank):
                    return
Esempio n. 8
0
def add(request, id):
    inst = Institution()
    if request.method == "GET":
        if id:
            info = OFXHome.lookup(int(id))
            inst.name = info.name
            inst.fid = info.fid
            inst.org = info.org
            inst.url = info.url
            inst.clean()
            form = InstitutionForm(instance=inst)
        else:
            pass
    elif request.method == "POST":
        form = InstitutionForm(data=request.POST, instance=inst)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(reverse(show, args=(inst.pk,)))
        else:
            request.user.message_set.create(message='Please check your data.')

    return render(request, "institutions/add.html", {"inst_form": form})
Esempio n. 9
0
    def add_bank(self,id=None,username=None,password=None):

        cherrypy.response.headers['Content-Type'] = 'application/json'
        cherrypy.response.status = 200

        result = {
            'status': 'ok',
            'message': ''
        }
        if id and username and password:
            bank = OFXHome.lookup(id)
            i = Institution(
                    id = bank['fid'],
                    org = bank['org'],
                    url = bank['url'],
                    broker_id = bank['brokerid'],
                    description = bank['name'],
                    username = username,
                    password = password
            )
            try:
                i.authenticate()
            except Exception as e:
                result['status'] = 'error'
                result['message'] = 'unable to log into bank with those credentials'

            for a in i.accounts():
                GlobalConfig.add_account(a)
            GlobalConfig.save()
        else:
            result['status'] = 'error'
            result['message'] = 'id, username, and password are all required'

        ret = json.dumps(result)
        cherrypy.response.body = ret
        if result['status'] == 'error':
            cherrypy.response.status = 400
        return ret
Esempio n. 10
0
def lambda_func(event, context=None):
    beginf = time.time()
    query = event['body']
    gettimes = []
    cmdtimes = []
    result = {}
    if not event['headers'].has_key('Authorization'):
        result['error'] = "Missing Auth Header"
        return result
    token_header_parts = event['headers']['Authorization'].split(" ")
    if len(token_header_parts) != 2 or token_header_parts[0] != "Bearer":
        result['error'] = "Malformed Auth Header"
        return result
    token_string = token_header_parts[1]

    headers = jwt.get_unverified_headers(token_string)

    kid = headers['kid']
    key_index = -1
    for i in range(len(JWT_KEYS)):
        if kid == JWT_KEYS[i]['kid']:
            key_index = i
            break
    if key_index == -1:
        result['error'] = 'Public key not found'
        return result

    try:
        decode = jwt.decode(token_string,
                            JWT_KEYS[key_index],
                            algorithms=['RS256'],
                            issuer=JWT_ISSUER)
    except:
        result['error'] = "Not Authorized"
        return result

    if query['query'] == 'getfile':
        filename = os.path.split(query['filename'])[-1]
        if filename.startswith('online'):
            begin = time.time()
            result['contents'] = get_file_from_s3(filename, query["creds"])
            end = time.time()
            gettimes.append(end - begin)
        else:
            result['error'] = "Filenames must begin with online"
    elif query['query'] == 'savefile':
        filename = os.path.split(query['filename'])[-1]
        if filename.startswith('online'):
            try:
                save_file_to_s3(filename, query['contents'], query["creds"])
                result['success'] = True
            except:
                result['success'] = False
        else:
            result['error'] = "Filenames must begin with online"
    elif query['query'] == 'report':
        command = None
        if query.has_key('name'):
            reportType = None
            historical = "auto"
            if query.has_key('historical'):
                historical = query['historical']

            if query['name'] == "accounts":
                command = ["hledger", "-I", "-f", "-", "accounts"]
                reportType = "accounts"
            elif query['name'] == "budget":
                command = ["hledger", "-I", "-f", "-", "accounts"]
                reportType = "budget"
            else:
                if query['name'] == "balance":
                    command = [
                        "hledger", "-f", "-", "balance", "--tree", "-O", "csv"
                    ]
                    reportType = "balance"
                    if historical == "includehistorical":
                        command.append('-H')
                        historical = None
                elif query['name'] == "register" or query[
                        'name'] == "budgetregister" or query[
                            'name'] == "combinedregister":
                    if query['name'] == "combinedregister":
                        command = [
                            "hledger", "-I", "-f", "-", "register", "-O", "csv"
                        ]
                    else:
                        command = [
                            "hledger", "-f", "-", "register", "-O", "csv"
                        ]
                    if historical == "auto" or historical == "includehistorical":
                        command.append('-H')
                        historical = None
                    reportType = query['name']
                if command and query.has_key('time'):
                    command.append('-p')
                    command.append(query['time'])
                if command and query.has_key('timeperiod'):
                    if query['timeperiod'] in [
                            'monthly', 'weekly', 'yearly', 'quarterly', 'daily'
                    ]:
                        command.append('--' + query['timeperiod'])
                if command and query.has_key('accounts'):
                    parts = query['accounts'].split('_')
                    if len(parts) > 1 and parts[1]:
                        command.append('^' + parts[1])
                        if historical == "auto" and (
                            (parts[1].startswith('Assets:')
                             or parts[1].startswith('Liabailities:'))):
                            command.append('-H')
                    else:
                        if parts[0] == "expenses":
                            command.append('^Expenses:')
                        elif parts[0] == "income":
                            command.append('^Income:')
                        elif parts[0] == "incomeexpenses":
                            command.append('^Income:|^Expenses:')
                        elif parts[0] == "assets":
                            command.append('^Assets:')
                            if historical == "auto":
                                command.append('-H')
                        elif parts[0] == "assetssummary":
                            command.append('^Assets:')
                            command.append('--depth')
                            command.append('2')
                            if historical == "auto":
                                command.append('-H')
                        elif parts[0] == "liabilities":
                            command.append('^Liabilities:')
                            if historical == "auto":
                                command.append('-H')
                        elif parts[0] == "assetsliabilities":
                            command.append('^Assets:|^Liabilities:')
                            if historical == "auto":
                                command.append('-H')
        if command:
            if reportType == "budget" or reportType == "accounts" or reportType == "combinedregister":
                begin = time.time()
                defaultledger = get_file_from_s3("online.ledger",
                                                 query["creds"])
                end = time.time()
                gettimes.append(end - begin)
                begin = time.time()
                budgetledger = get_file_from_s3("onlinebudget.ledger",
                                                query["creds"])
                end = time.time()
                gettimes.append(end - begin)
                begin = time.time()
                output, errors = subprocess.Popen(
                    command,
                    stdin=subprocess.PIPE,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    env=launch_env).communicate(defaultledger + os.linesep +
                                                budgetledger)
                end = time.time()
                cmdtimes.append(end - begin)
            elif reportType == "budgetregister":
                begin = time.time()
                budgetledger = get_file_from_s3("onlinebudget.ledger",
                                                query["creds"])
                end = time.time()
                gettimes.append(end - begin)
                begin = time.time()
                output, errors = subprocess.Popen(
                    command,
                    stdin=subprocess.PIPE,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    env=launch_env).communicate(budgetledger)
                end = time.time()
                cmdtimes.append(end - begin)
            else:
                begin = time.time()
                defaultledger = get_file_from_s3("online.ledger",
                                                 query["creds"])
                end = time.time()
                gettimes.append(end - begin)
                begin = time.time()
                output, errors = subprocess.Popen(
                    command,
                    stdin=subprocess.PIPE,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    env=launch_env).communicate(defaultledger)
                end = time.time()
                cmdtimes.append(end - begin)
            if errors:
                result["error"] = "Report failed: " + errors
            else:
                try:
                    items = []
                    if reportType == "accounts":
                        result = {"result": output.splitlines()}
                    elif reportType == "budget":
                        allaccounts = output.splitlines()
                        transactionfilter = '^' + '$|^'.join(
                            filter(
                                lambda aname: aname.find("Off-Budget") < 0 and
                                not aname.startswith("Expenses:") and not aname
                                .startswith("Income:") and not aname.
                                startswith("Equity:"), allaccounts)) + '$'
                        # Filter and get rid of asset accounts that are part of the budget
                        allaccounts = filter(
                            lambda aname: aname.find("Off-Budget") >= 0 or
                            not aname.startswith("Assets:"), allaccounts)
                        command = [
                            "hledger", "-I", "-f", "-", "print",
                            transactionfilter
                        ]
                        begin = time.time()
                        filteredledger, errors = subprocess.Popen(
                            command,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE,
                            env=launch_env).communicate(defaultledger)
                        end = time.time()
                        cmdtimes.append(end - begin)
                        # Budget report involves 3 reports with various inputs
                        command = [
                            "hledger", "-I", "-f", "-", "balance", "--tree",
                            "-O", "csv", "-E", "-p",
                            query.get('time', ['thismonth'])
                        ]
                        if query.has_key(
                                'budgetperiod') and query['budgetperiod'] in [
                                    'monthly', 'weekly', 'yearly', 'quarterly',
                                    'daily'
                                ]:
                            command.append('--' + query['budgetperiod'])
                        else:
                            command.append('--monthly')
                        begin = time.time()
                        budgetoutput, errors = subprocess.Popen(
                            command,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE,
                            env=launch_env).communicate(budgetledger)
                        end = time.time()
                        cmdtimes.append(end - begin)
                        if errors:
                            result["error"] = "Budget report failed: " + errors
                        else:
                            command = [
                                "hledger", "-f", "-", "balance", "--tree",
                                "-O", "csv", "-E", "-p",
                                query.get('time', ['thismonth'])
                            ]
                            if query.has_key(
                                    'timeperiod') and query['timeperiod'] in [
                                        'monthly', 'weekly', 'yearly',
                                        'quarterly', 'daily'
                                    ]:
                                command.append('--' + query['timeperiod'])
                            else:
                                command.append('--monthly')
                            begin = time.time()
                            spendingoutput, errors = subprocess.Popen(
                                command,
                                stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE,
                                env=launch_env).communicate(filteredledger)
                            end = time.time()
                            cmdtimes.append(end - begin)
                            if errors:
                                result[
                                    "error"] = "Budget spending report failed: " + errors
                            else:
                                command = [
                                    "hledger", "-I", "-f", "-", "balance",
                                    "--tree", "-O", "csv", "-E", "-H", "-p",
                                    query.get('time', ['thismonth'])
                                ]
                                if query.has_key('timeperiod'
                                                 ) and query['timeperiod'] in [
                                                     'monthly', 'weekly',
                                                     'yearly', 'quarterly',
                                                     'daily'
                                                 ]:
                                    command.append('--' + query['timeperiod'])
                                else:
                                    command.append('--monthly')

                                begin = time.time()
                                balanceoutput, errors = subprocess.Popen(
                                    command,
                                    stdin=subprocess.PIPE,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE,
                                    env=launch_env).communicate(
                                        filteredledger + os.linesep +
                                        budgetledger)
                                end = time.time()
                                cmdtimes.append(end - begin)
                                if errors:
                                    result[
                                        "error"] = "Budget balance report failed: " + errors
                                else:
                                    budgetitems = {}
                                    spendingitems = {}
                                    balanceitems = {}
                                    reader = csv.DictReader(
                                        StringIO.StringIO(budgetoutput))
                                    budgetcolumns = []
                                    reportcolumns = []
                                    columns = []
                                    foundbudgetkeys = False
                                    foundspendingkeys = False
                                    foundbalancekeys = False
                                    for row in reader:
                                        if row['Account'] != "total":
                                            if not foundbudgetkeys:
                                                for col in row.keys():
                                                    fixedcol = fix_column_name(
                                                        col)
                                                    if fixedcol[0].isdigit(
                                                    ) and fixedcol not in budgetcolumns:
                                                        budgetcolumns.append(
                                                            fixedcol)
                                                        columns.append(
                                                            (fixedcol, 0,
                                                             "Budget " +
                                                             fixedcol, col))
                                                foundbudgetkeys = True
                                            budgetitems[row['Account']] = row
                                    reader = csv.DictReader(
                                        StringIO.StringIO(spendingoutput))
                                    for row in reader:
                                        if row['Account'] != "total":
                                            if not foundspendingkeys:
                                                for col in row.keys():
                                                    fixedcol = fix_column_name(
                                                        col)
                                                    if fixedcol[0].isdigit(
                                                    ) and fixedcol not in reportcolumns:
                                                        reportcolumns.append(
                                                            fixedcol)
                                                        columns.append(
                                                            (fixedcol, 1,
                                                             "Actual " +
                                                             fixedcol, col))
                                                        columns.append(
                                                            (fixedcol, 2,
                                                             "Balance " +
                                                             fixedcol, col))
                                                foundspendingkeys = True
                                            spendingitems[row['Account']] = row
                                    reader = csv.DictReader(
                                        StringIO.StringIO(balanceoutput))
                                    for row in reader:
                                        if row['Account'] != "total":
                                            if not foundbalancekeys:
                                                for col in row.keys():
                                                    fixedcol = fix_column_name(
                                                        col)
                                                    if col[0].isdigit(
                                                    ) and fixedcol not in reportcolumns:
                                                        reportcolumns.append(
                                                            fixedcol)
                                                        columns.append(
                                                            (fixedcol, 1,
                                                             "Actual " +
                                                             fixedcol, col))
                                                        columns.append(
                                                            (fixedcol, 2,
                                                             "Balance " +
                                                             fixedcol, col))
                                                foundbalancekeys = True
                                            balanceitems[row['Account']] = row
                                    # Now assemble header row
                                    header = ['account']
                                    columns.sort()
                                    firstbudget = -1
                                    firstbudgetidx = 0
                                    for col, order, colname, lookupcol in columns:
                                        if firstbudget < 0:
                                            if order == 0:
                                                firstbudget = firstbudgetidx
                                            else:
                                                firstbudgetidx += 1
                                                continue
                                        header.append(colname)
                                    if firstbudgetidx >= 0:
                                        columns = columns[firstbudgetidx:]
                                    # Now assemble report rows
                                    totals = {'account': 'Total'}
                                    for acct in allaccounts:
                                        if budgetitems.has_key(
                                                acct) or spendingitems.has_key(
                                                    acct
                                                ) or balanceitems.has_key(
                                                    acct):
                                            row = {'account': acct}
                                            for col, order, colname, lookupcol in columns:
                                                if order == 0:  # Budget column
                                                    if budgetitems.has_key(
                                                            acct
                                                    ) and budgetitems[
                                                            acct].has_key(
                                                                lookupcol):
                                                        row[colname] = negateamount(
                                                            budgetitems[acct]
                                                            [lookupcol])
                                                    else:
                                                        row[colname] = "0"
                                                elif order == 1:  # Actual column
                                                    if spendingitems.has_key(
                                                            acct
                                                    ) and spendingitems[
                                                            acct].has_key(
                                                                lookupcol):
                                                        row[colname] = negateamount(
                                                            spendingitems[acct]
                                                            [lookupcol])
                                                    else:
                                                        row[colname] = "0"
                                                elif order == 2:  # Balance column
                                                    if balanceitems.has_key(
                                                            acct
                                                    ) and balanceitems[
                                                            acct].has_key(
                                                                lookupcol):
                                                        row[colname] = negateamount(
                                                            balanceitems[acct]
                                                            [lookupcol])
                                                    else:
                                                        row[colname] = "0"
                                                aggregate_total(
                                                    totals, colname,
                                                    row[colname])
                                            keeprow = False
                                            if row['account'].startswith(
                                                    'Expenses:'
                                            ) or row['account'].startswith(
                                                    'Income:'
                                            ) or row['account'].startswith(
                                                    'Assets:'):
                                                keeprow = True
                                            for colname in row.keys():
                                                if colname != 'account' and row[
                                                        colname] != '0':
                                                    keeprow = True
                                            if keeprow:
                                                items.append(row)
                                    items.append(totals)
                                    result["headers"] = header
                                    result["result"] = items

                    else:
                        reader = csv.DictReader(StringIO.StringIO(output))
                        for row in reader:
                            if reportType == "budgetregister" or reportType == "combinedregister":
                                for k in row.keys():
                                    if k != "txnidx" and k != "date" and k != "description" and k != "account":
                                        row[k] = negateamount(row[k])
                            items.append(row)
                        result["headers"] = reader.fieldnames
                        result["result"] = items
                except:
                    result[
                        "error"] = "Report failed to produce readable results"
        else:
            result["error"] = "Bad report parameters"
    elif query['query'] == 'validate':
        options = ["-I"]
        if query.has_key('assertions') and query['assertions']:
            options = []
        command = ["hledger", "-f", "-"] + options + ["print"]
        ledger = query['contents']
        begin = time.time()
        validateoutput, errors = subprocess.Popen(
            command,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            env=launch_env).communicate(ledger)
        end = time.time()
        cmdtimes.append(end - begin)
        if validateoutput:
            result["output"] = validateoutput
        if errors:
            result["error"] = errors

    elif query['query'] == 'parseofx':
        ofxdata = query['contents']
        parser = OfxParser.parse(StringIO.StringIO(ofxdata))
        convdate = lambda d: ("%0.4d/%0.2d/%0.2d" % (d.year, d.month, d.day)
                              ) if d is not None and hasattr(d, 'year'
                                                             ) else None
        strifnotnone = lambda s: str(s) if s is not None else s

        result["ofxaccounts"] = [{
            "fid":
            getattr(account.institution, "fid", None),
            "organization":
            getattr(account.institution, "organization", None),
            "account_id":
            getattr(account, "account_id", None),
            "number":
            getattr(account, "number", None),
            "routing_number":
            getattr(account, "routing_number", None),
            "type":
            getattr(account, "type", None),
            "account_type":
            getattr(account, "account_type", None),
            "statement": {
                "available_balance":
                strifnotnone(
                    getattr(account.statement, "available_balance", None)),
                "available_balance_date":
                convdate(
                    getattr(account.statement, "available_balance_date",
                            None)),
                "balance":
                strifnotnone(getattr(account.statement, "balance", None)),
                "balance_date":
                convdate(getattr(account.statement, "balance_date", None)),
                "start_date":
                convdate(getattr(account.statement, "start_date", None)),
                "end_date":
                convdate(getattr(account.statement, "end_date", None)),
                "currency":
                getattr(account.statement, "currency", None),
                "transactions": [{
                    "amount": strifnotnone(txn.amount),
                    "checknum": getattr(txn, "checknum", None),
                    "date": convdate(getattr(txn, "date", None)),
                    "id": getattr(txn, "id", None),
                    "mcc": getattr(txn, "mcc", None),
                    "memo": getattr(txn, "memo", None),
                    "payee": getattr(txn, "payee", None),
                    "sic": getattr(txn, "sic", None),
                    "type": getattr(txn, "type", None)
                } for txn in account.statement.transactions]
            }
        } for account in parser.accounts]

    elif query['query'] == 'downloadofx':
        try:
            #    config = ConfigParser.ConfigParser()
            #    config.readfp(StringIO.StringIO(query['ofxconfig']))
            #    ofxclient.config.unflatten_dict(dict(config.items(config.sections()[0])))
            #    acct = ofxclient.account.Account.deserialize(ofxclient.config.unflatten_dict(dict(config.items(config.sections()[0]))))
            acct = ofxclient.account.Account.deserialize(query['ofxconfig'])
            dat = acct.download()
            result["contents"] = dat.read()
        except Exception as ex:
            result["error"] = str(ex)

    elif query['query'] == 'searchofxhome':
        try:
            result["result"] = list(OFXHome.search(query['search']))
        except Exception as ex:
            result["error"] = str(ex)

    elif query['query'] == 'getofxaccounts':
        try:
            version = DEFAULT_OFX_VERSION
            if query.has_key('ofx_version'):
                version = int(query['ofx_version'])
            bank_info = OFXHome.lookup(query['ofxhomeid'])
            if bank_info:
                i = Institution(id=bank_info['fid'],
                                org=bank_info['org'],
                                url=bank_info['url'],
                                broker_id=bank_info['brokerid'],
                                description=bank_info['name'],
                                username=query['username'],
                                password=query['password'],
                                client_args=ofxclient.cli.client_args_for_bank(
                                    bank_info, version))
                failed = False
                try:
                    i.authenticate()
                except Exception as ex:
                    failed = True
                    result["error"] = "Authentication failed: " + str(ex)
                if not failed:
                    accts = i.accounts()
                    result["result"] = [acct.serialize() for acct in accts]
            else:
                result["error"] = "Could not find bank"
        except Exception as ex:
            result["error"] = "Failure: " + str(ex)
    else:
        result["error"] = "Bad query"

    endf = time.time()
    result["log"] = {
        "totaltime": (endf - beginf),
        "gettimes": gettimes,
        "cmdtimes": cmdtimes
    }
    return result