Exemple #1
0
def mn(m, n, num_layers=2, overlay=False):
    assert num_layers >= 1
    bases = [cint(m**(1. / num_layers))] * num_layers
    k = m

    result = []
    for i in range(num_layers):
        layer = []
        next_base = cint(bases[i] * ((n * 1. / k)**(1. / (num_layers - i))))
        next_bases = bases[:i] + [next_base] + bases[i + 1:]
        for x in xrange(reduce(lambda x, y: x * y, bases, 1)):
            xseq = num_to_seq(x, bases)
            if not overlay:
                out = set([
                    seq_to_num(xseq[:i] + [j] + xseq[i + 1:], next_bases)
                    for j in xrange(next_bases[i])
                ])
            else:
                out = set([
                    seq_to_num(xseq[:l] + [j] + xseq[l + 1:], next_bases)
                    for l in xrange(num_layers) for j in xrange(next_bases[l])
                ])
            layer.append(list(out))
        k = max_idx(layer)
        bases = next_bases
        result.append(layer)

    return result
Exemple #2
0
def mn(m, n, stages=3, strict_nonblocking=False, augment=False):
    assert stages % 2 == 1
    if stages == 1:
        # return mxn full connection
        return [[range(n)] * m]

    # otherwise, build the network recursively
    n1, n2 = _solve(m, n, strict_nonblocking)
    k = (n1 + n2 - 1) if strict_nonblocking else max(n1, n2)
    r1 = cint(m * 1. / n1)
    r2 = cint(n * 1. / n2)
    layers = []

    # Build the first stage
    blocks = [[[range(k)] * n1]] * r1
    layers.extend(stack(*blocks))

    # Connect the first stage with the core switch network
    layers.append(_xlink(r1, k))

    # Recursively build the core switch network
    blocks = [mn(r1, r2, stages - 2, strict_nonblocking)] * k
    layers.extend(stack(*blocks))

    # Connect the core switch network with the last stage
    layers.append(_xlink(k, r2))

    # Build the last stage
    blocks = [[[range(n2)] * k]] * r2
    layers.extend(stack(*blocks))

    return layers
Exemple #3
0
def gkd(dbo, m, f, usetoday = False):
    """ reads field f from map m, returning a display date. 
        string is empty if key not present or date is invalid.
        If usetoday is set to True, then today's date is returned
        if the date is blank.
    """
    if not m.has_key(f): return ""
    lv = str(m[f])
    # If there's a space, then I guess we have time info - throw it away
    if lv.find(" ") > 0:
        lv = lv[0:lv.find(" ")]
    # Now split it by either / or -
    b = lv.split("/")
    if lv.find("-") != -1:
        b = lv.split("-")
    # We should have three date bits now
    if len(b) != 3:
        # We don't have a valid date, if use today is on return that
        if usetoday:
            return i18n.python2display(dbo.locale, i18n.now(dbo.timezone))
        else:
            return ""
    else:
        # Which of our 3 bits is the year?
        if utils.cint(b[0]) > 1900:
            # it's Y/M/D
            d = datetime.datetime(utils.cint(b[0]), utils.cint(b[1]), utils.cint(b[2]))
        elif dbo.locale == "en":
            # Assume it's M/D/Y for US
            d = datetime.datetime(utils.cint(b[2]), utils.cint(b[0]), utils.cint(b[1]))
        else:
            # Assume it's D/M/Y
            d = datetime.datetime(utils.cint(b[2]), utils.cint(b[1]), utils.cint(b[0]))
        return i18n.python2display(dbo.locale, d)
Exemple #4
0
def parse_time(d, t):
    """
    Parses the time t and combines it with python date d
    """
    if d is None: return None
    tbits = t.split(":")
    hour = 0
    minute = 0
    second = 0
    if len(tbits) > 0: hour = utils.cint(tbits[0])
    if len(tbits) > 1: minute = utils.cint(tbits[1])
    if len(tbits) > 2: second = utils.cint(tbits[2])
    t = datetime.time(hour, minute, second)
    d = d.combine(d, t)
    return d
Exemple #5
0
def get_animalcontrol_find_simple(dbo, query = "", limit = 0):
    """
    Returns rows for simple animal control searches.
    query: The search criteria
    """
    ors = []
    query = query.replace("'", "`")
    def add(field):
        return utils.where_text_filter(dbo, field, query)
    # If no query has been given, show open animal control records
    # from the last 30 days
    if query == "":
        ors.append("ac.IncidentDateTime > %s AND ac.CompletedDate Is Null" % db.dd(subtract_days(now(dbo.timezone), 30)))
    else:
        if utils.is_numeric(query):
            ors.append("ac.ID = " + str(utils.cint(query)))
        ors.append(add("co.OwnerName"))
        ors.append(add("ti.IncidentName"))
        ors.append(add("ac.DispatchAddress"))
        ors.append(add("ac.DispatchPostcode"))
        ors.append(add("o1.OwnerName"))
        ors.append(add("o2.OwnerName"))
        ors.append(add("o3.OwnerName"))
        ors.append(add("vo.OwnerName"))
        ors.append(u"EXISTS(SELECT ad.Value FROM additional ad " \
            "INNER JOIN additionalfield af ON af.ID = ad.AdditionalFieldID AND af.Searchable = 1 " \
            "WHERE ad.LinkID=ac.ID AND ad.LinkType IN (%s) AND LOWER(ad.Value) LIKE '%%%s%%')" % (additional.INCIDENT_IN, query.lower()))
        if not dbo.is_large_db:
            ors.append(add("ac.CallNotes"))
            ors.append(add("ac.AnimalDescription"))
    sql = get_animalcontrol_query(dbo) + " WHERE " + " OR ".join(ors)
    if limit > 0: sql += " LIMIT " + str(limit)
    return db.query(dbo, sql)
Exemple #6
0
def get_foundanimal_find_simple(dbo, query = "", limit = 0):
    """
    Returns rows for simple found animal searches.
    query: The search criteria
    """
    ors = []
    query = query.replace("'", "`")
    def add(field):
        return utils.where_text_filter(dbo, field, query)
    # If no query has been given, show unreturned found animal records
    # for the last 30 days
    if query == "":
        ors.append("a.DateFound > %s AND a.ReturnToOwnerDate Is Null" % db.dd(subtract_days(now(dbo.timezone), 30)))
    else:
        if utils.is_numeric(query):
            ors.append("a.ID = " + str(utils.cint(query)))
        ors.append(add("o.OwnerName"))
        ors.append(add("a.AreaFound"))
        ors.append(add("a.AreaPostcode"))
        ors.append(u"EXISTS(SELECT ad.Value FROM additional ad " \
            "INNER JOIN additionalfield af ON af.ID = ad.AdditionalFieldID AND af.Searchable = 1 " \
            "WHERE ad.LinkID=a.ID AND ad.LinkType IN (%s) AND LOWER(ad.Value) LIKE '%%%s%%')" % (additional.FOUNDANIMAL_IN, query.lower()))
        if not dbo.is_large_db:
            ors.append(add("x.Sex"))
            ors.append(add("b.BreedName"))
            ors.append(add("c.BaseColour"))
            ors.append(add("s.SpeciesName"))
            ors.append(add("a.AgeGroup"))
            ors.append(add("a.DistFeat"))
            ors.append(add("a.Comments"))
    sql = get_foundanimal_query(dbo) + " WHERE " + " OR ".join(ors)
    if limit > 0: sql += " LIMIT " + str(limit)
    return db.query(dbo, sql)
def get_lostanimal_find_simple(dbo, query="", limit=0, onlyindexed=False):
    """
    Returns rows for simple lost animal searches.
    query: The search criteria
    """
    ors = []
    query = query.replace("'", "`")

    def add(field):
        return utils.where_text_filter(dbo, field, query)

    # If no query has been given, show unfound lost animal records
    # for the last 30 days
    if query == "":
        ors.append("a.DateLost > %s AND a.DateFound Is Null" %
                   db.dd(subtract_days(now(dbo.timezone), 30)))
    else:
        if utils.is_numeric(query):
            ors.append("a.ID = " + str(utils.cint(query)))
        ors.append(add("o.OwnerName"))
        ors.append(add("a.AreaLost"))
        ors.append(add("a.AreaPostcode"))
        if not onlyindexed:
            ors.append(add("x.Sex"))
            ors.append(add("b.BreedName"))
            ors.append(add("c.BaseColour"))
            ors.append(add("s.SpeciesName"))
            ors.append(add("a.AgeGroup"))
            ors.append(add("a.DistFeat"))
            ors.append(add("a.Comments"))
    sql = get_lostanimal_query(dbo) + " WHERE " + " OR ".join(ors)
    if limit > 0: sql += " LIMIT " + str(limit)
    return db.query(dbo, sql)
Exemple #8
0
 def housenumber(s):
     # Return the full address if the first word is not numeric
     bits = s.strip().split(" ")
     houseno = s
     if len(bits) > 0 and utils.cint(bits[0]) > 0:
         houseno = bits[0]
     return houseno
Exemple #9
0
def get_treatments_outstanding(dbo, offset="m31", locationfilter=""):
    """
    Returns a recordset of shelter animals awaiting medical treatments:
    offset is m to go backwards, or p to go forwards with a number of days.
    ANIMALID, SHELTERCODE, ANIMALNAME, LOCATIONNAME, WEBSITEMEDIANAME,
    TREATMENTNAME, COST, COMMENTS, NAMEDFREQUENCY, NAMEDNUMBEROFTREATMENTS,
    NAMEDSTATUS, DOSAGE, STARTDATE, TREATMENTSGIVEN, TREATMENTSREMAINING,
    TIMINGRULE, TIMINGRULEFREQUENCY, TIMINGRULENOFREQUENCIES, TREATMENTRULE
    TOTALNUMBEROFTREATMENTS, DATEREQUIRED, DATEGIVEN, TREATMENTCOMMENTS,
    TREATMENTNUMBER, TOTALTREATMENTS, GIVENBY, REGIMENID, TREATMENTID
    """
    ec = ""
    offsetdays = utils.cint(offset[1:])
    if offset.startswith("m"):
        ec = " AND DateRequired >= %s AND DateRequired <= %s" % (db.dd(
            subtract_days(now(dbo.timezone),
                          offsetdays)), db.dd(now(dbo.timezone)))
    if offset.startswith("p"):
        ec = " AND DateRequired >= %s AND DateRequired <= %s" % (db.dd(
            now(dbo.timezone)), db.dd(add_days(now(dbo.timezone), offsetdays)))
    if locationfilter != "":
        locationfilter = " AND ShelterLocation IN (%s)" % locationfilter
    return embellish_regimen(dbo.locale, db.query(dbo, "SELECT * FROM v_animalmedicaltreatment " \
        "WHERE DateRequired Is Not Null AND DateGiven Is Null " \
        "AND Status = 0 " \
        "AND DeceasedDate Is Null AND (Archived = 0 OR ActiveMovementType = 2) %s %s " \
        "ORDER BY DateRequired, AnimalName" % (ec, locationfilter)))
Exemple #10
0
def get_lostanimal_find_simple(dbo, query = "", limit = 0, onlyindexed = False):
    """
    Returns rows for simple lost animal searches.
    query: The search criteria
    """
    ors = []
    query = query.replace("'", "`")
    def add(field):
        return utils.where_text_filter(dbo, field, query)
    # If no query has been given, show unfound lost animal records
    # for the last 30 days
    if query == "":
        ors.append("a.DateLost > %s AND a.DateFound Is Null" % db.dd(subtract_days(now(dbo.timezone), 30)))
    else:
        if utils.is_numeric(query):
            ors.append("a.ID = " + str(utils.cint(query)))
        ors.append(add("OwnerName"))
        ors.append(add("AreaLost"))
        ors.append(add("AreaPostcode"))
        if not onlyindexed:
            ors.append(add("SexName"))
            ors.append(add("BreedName"))
            ors.append(add("BaseColourName"))
            ors.append(add("SpeciesName"))
            ors.append(add("AgeGroup"))
            ors.append(add("DistFeat"))
            ors.append(add("Comments"))
    sql = get_lostanimal_query() + " WHERE " + " OR ".join(ors)
    if limit > 0: sql += " LIMIT " + str(limit)
    return db.query(dbo, sql)
def get_animalcontrol_find_simple(dbo, query="", limit=0, onlyindexed=False):
    """
    Returns rows for simple animal control searches.
    query: The search criteria
    """
    ors = []
    query = query.replace("'", "`")

    def add(field):
        return utils.where_text_filter(dbo, field, query)

    # If no query has been given, show open animal control records
    # from the last 30 days
    if query == "":
        ors.append("ac.IncidentDateTime > %s AND ac.CompletedDate Is Null" %
                   db.dd(subtract_days(now(dbo.timezone), 30)))
    else:
        if utils.is_numeric(query):
            ors.append("ac.ID = " + str(utils.cint(query)))
        ors.append(add("co.OwnerName"))
        ors.append(add("ti.IncidentName"))
        ors.append(add("ac.DispatchAddress"))
        ors.append(add("ac.DispatchPostcode"))
        ors.append(add("o1.OwnerName"))
        ors.append(add("o2.OwnerName"))
        ors.append(add("o3.OwnerName"))
        ors.append(add("vo.OwnerName"))
        if not onlyindexed:
            ors.append(add("ac.CallNotes"))
            ors.append(add("ac.AnimalDescription"))
    sql = get_animalcontrol_query(dbo) + " WHERE " + " OR ".join(ors)
    if limit > 0: sql += " LIMIT " + str(limit)
    return db.query(dbo, sql)
Exemple #12
0
 def housenumber(s):
     # Return the full address if the first word is not numeric
     bits = s.strip().split(" ")
     houseno = s
     if len(bits) > 0 and utils.cint(bits[0]) > 0:
         houseno = bits[0]
     return houseno
Exemple #13
0
def get_donations(dbo, offset="m31"):
    """
    Returns a recordset of donations
    offset is m to go backwards, or p to go forwards with a number of days.
    ID, DONATIONTYPEID, DONATIONNAME, DATE, DATEDUE, DONATION,
    ISGIFTAID, FREQUENCY, FREQUENCYNAME, NEXTCREATED, COMMENTS, OWNERNAME, 
    ANIMALNAME, SHELTERCODE, OWNERID, ANIMALID
    """
    ec = ""
    order = ""
    offsetdays = utils.cint(offset[1:])
    if offset.startswith("m"):
        ec = "Date >= %s AND Date <= %s" % (db.dd(
            i18n.subtract_days(i18n.now(dbo.timezone),
                               offsetdays)), db.dd(i18n.now(dbo.timezone)))
        order = "Date DESC"
    elif offset.startswith("p"):
        ec = "Date Is Null AND DateDue >= %s AND DateDue <= %s" % (
            db.dd(i18n.now(dbo.timezone)),
            db.dd(i18n.add_days(i18n.now(dbo.timezone), offsetdays)))
        order = "DateDue DESC"
    elif offset.startswith("d"):
        ec = "Date Is Null AND DateDue <= %s" % (db.dd(i18n.now(dbo.timezone)))
        order = "DateDue"
    return db.query(dbo, "SELECT * FROM v_ownerdonation " \
        "WHERE %s "
        "ORDER BY %s" % (ec, order))
Exemple #14
0
def get_foundanimal_find_simple(dbo, query = "", limit = 0, siteid = 0):
    """
    Returns rows for simple found animal searches.
    query: The search criteria
    """
    ss = utils.SimpleSearchBuilder(dbo, query)

    sitefilter = ""
    if siteid != 0: sitefilter = " AND (o.SiteID = 0 OR o.SiteID = %d)" % siteid

    # If no query has been given, show unfound lost animal records
    # for the last 30 days
    if query == "":
        ss.ors.append("a.DateFound > ? AND a.ReturnToOwnerDate Is Null %s" % sitefilter)
        ss.values.append(dbo.today(offset=-30))
    else:
        if utils.is_numeric(query): ss.add_field_value("a.ID", utils.cint(query))
        ss.add_fields([ "o.OwnerName", "a.AreaFound", "a.AreaPostcode" ])
        ss.add_clause("EXISTS(SELECT ad.Value FROM additional ad " \
            "INNER JOIN additionalfield af ON af.ID = ad.AdditionalFieldID AND af.Searchable = 1 " \
            "WHERE ad.LinkID=a.ID AND ad.LinkType IN (%s) AND LOWER(ad.Value) LIKE ?)" % additional.FOUNDANIMAL_IN)
        ss.add_large_text_fields([ "b.BreedName", "a.DistFeat", "a.Comments" ])

    sql = "%s WHERE a.ID > 0 %s AND (%s)" % (get_foundanimal_query(dbo), sitefilter, " OR ".join(ss.ors))
    return dbo.query(sql, ss.values, limit=limit, distincton="ID")
Exemple #15
0
def get_waitinglist_find_simple(dbo, query="", limit=0, siteid=0):
    """
    Returns rows for simple waiting list searches.
    query: The search criteria
    """
    ss = utils.SimpleSearchBuilder(dbo, query)

    sitefilter = ""
    if siteid != 0:
        sitefilter = " AND (o.SiteID = 0 OR o.SiteID = %d)" % siteid

    # If no query has been given, do a current waitinglist search
    if query == "":
        return get_waitinglist(dbo)
    if utils.is_numeric(query): ss.add_field_value("a.ID", utils.cint(query))
    ss.add_field("o.OwnerName")
    ss.add_clause("EXISTS(SELECT ad.Value FROM additional ad " \
        "INNER JOIN additionalfield af ON af.ID = ad.AdditionalFieldID AND af.Searchable = 1 " \
        "WHERE ad.LinkID=a.ID AND ad.LinkType IN (%s) AND LOWER(ad.Value) LIKE ?)" % additional.WAITINGLIST_IN)
    ss.add_large_text_fields([
        "a.AnimalDescription", "a.ReasonForWantingToPart", "a.ReasonForRemoval"
    ])

    sql = "%s WHERE a.ID > 0 %s AND (%s) ORDER BY a.ID" % (
        get_waitinglist_query(dbo), sitefilter, " OR ".join(ss.ors))
    return dbo.query(sql, ss.values, limit=limit, distincton="ID")
Exemple #16
0
def update_movement_donation(dbo, movementid):
    """
    Goes through all donations attached to a particular movement and updates
    the denormalised movement total.
    """
    if utils.cint(movementid) == 0: return
    dbo.execute("UPDATE adoption SET Donation = " \
        "(SELECT SUM(Donation) FROM ownerdonation WHERE MovementID = ?) WHERE ID = ?", (movementid, movementid))
Exemple #17
0
 def now(self, timenow=True, offset=0, settime=""):
     """ Returns now as a Python date, adjusted for the database timezone.
         timenow: if True, includes the current time
         offset:  Add this many days to now (negative values supported)
         settime: A time in HH:MM:SS format to set
     """
     d = i18n.now(self.timezone)
     if not timenow:
         d = d.replace(hour = 0, minute = 0, second = 0, microsecond = 0)
     if offset > 0:
         d = i18n.add_days(d, offset)
     if offset < 0:
         d = i18n.subtract_days(d, abs(offset))
     if settime != "":
         timebits = settime.split(":")
         d = d.replace(hour = utils.cint(timebits[0]), minute = utils.cint(timebits[1]), second = utils.cint(timebits[2]), microsecond = 0)
     return d
Exemple #18
0
def mn(m, n, num_layers=2, direct=False, overlay=False, augment=False, exchange_func=pm2iplus0):
    assert num_layers >= 1
    # num_layers == 1 means fully connected NN
    bases = [cint(m ** (1./num_layers))] * num_layers
    k = m

    result = []
    for i in range(num_layers):
        next_base = cint(bases[-1] * ((n*1./k) ** (1./(num_layers-i))))
        # print "[n%d][k%d][num_layers%d][i%d][next_base%d]" % (n, k, num_layers, i, next_base)
        # print "BASES: ", bases
        layer = _build_layer(k, bases, direct, overlay, augment, exchange_func, next_base)
        result.extend(layer)
        k = max_idx(layer[1])
        bases = [next_base] + bases[:-1]

    return result
Exemple #19
0
def lookingfor_last_match_count(dbo):
    """
    Inspects the cached version of the looking for report and
    returns the number of animal matches.
    """
    s = dbfs.get_string_filepath(dbo, "/reports/daily/lookingfor.html")
    sp = s.find("$AM")
    if sp == -1: return 0
    return utils.cint(s[sp+3:s.find("^", sp)])
Exemple #20
0
def update_movement_donation(dbo, movementid):
    """
    Goes through all donations attached to a particular movement and updates
    the denormalised movement total.
    """
    if utils.cint(movementid) == 0: return
    db.execute(dbo, "UPDATE adoption SET Donation = " \
        "(SELECT SUM(Donation) FROM ownerdonation WHERE MovementID = %d) WHERE ID = %d" % \
        (int(movementid), int(movementid)))
Exemple #21
0
def lookingfor_last_match_count(dbo):
    """
    Inspects the cached version of the looking for report and
    returns the number of animal matches.
    """
    s = dbfs.get_string_filepath(dbo, "/reports/daily/lookingfor.html")
    sp = s.find("$AM")
    if sp == -1: return 0
    return utils.cint(s[sp + 3:s.find("^", sp)])
Exemple #22
0
def gkd(dbo, m, f, usetoday=False):
    """ reads field f from map m, returning a display date. 
        string is empty if key not present or date is invalid.
        If usetoday is set to True, then today's date is returned
        if the date is blank.
    """
    if f not in m: return ""
    lv = str(m[f])
    # If there's a space, then I guess we have time info - throw it away
    if lv.find(" ") > 0:
        lv = lv[0:lv.find(" ")]
    # Now split it by either / or -
    b = lv.split("/")
    if lv.find("-") != -1:
        b = lv.split("-")
    # We should have three date bits now
    if len(b) != 3:
        # We don't have a valid date, if use today is on return that
        if usetoday:
            return i18n.python2display(dbo.locale, i18n.now(dbo.timezone))
        else:
            return ""
    else:
        try:
            # Which of our 3 bits is the year?
            if utils.cint(b[0]) > 1900:
                # it's Y/M/D
                d = datetime.datetime(utils.cint(b[0]), utils.cint(b[1]),
                                      utils.cint(b[2]))
            elif dbo.locale == "en":
                # Assume it's M/D/Y for US
                d = datetime.datetime(utils.cint(b[2]), utils.cint(b[0]),
                                      utils.cint(b[1]))
            else:
                # Assume it's D/M/Y
                d = datetime.datetime(utils.cint(b[2]), utils.cint(b[1]),
                                      utils.cint(b[0]))
            return i18n.python2display(dbo.locale, d)
        except:
            # We've got an invalid date - return today
            if usetoday:
                return i18n.python2display(dbo.locale, i18n.now(dbo.timezone))
            else:
                return ""
Exemple #23
0
def insert_onlineformincoming_from_form(dbo, post, remoteip):
    """
    Create onlineformincoming records from posted data. We 
    create a row for every key/value pair in the posted data
    with a unique collation ID.
    """
    IGNORE_FIELDS = [ "formname", "flags", "redirect", "account", "filechooser", "method" ]
    collationid = db.query_int(dbo, "SELECT MAX(CollationID) FROM onlineformincoming") + 1
    formname = post["formname"]
    posteddate = i18n.now(dbo.timezone)
    flags = post["flags"]
    for k, v in post.data.iteritems():
        if k not in IGNORE_FIELDS:
            label = ""
            displayindex = 0
            fieldname = k
            # Form fields should have a _ONLINEFORMFIELD.ID suffix we can use to get the
            # original label and display position
            if k.find("_") != -1:
                fid = utils.cint(k[k.rfind("_")+1:])
                fieldname = k[0:k.rfind("_")]
                if fid != 0:
                    fld = db.query(dbo, "SELECT Label, DisplayIndex FROM onlineformfield WHERE ID = %d" % fid)
                    if len(fld) > 0:
                        label = fld[0]["LABEL"]
                        displayindex = fld[0]["DISPLAYINDEX"]

            sql = db.make_insert_sql("onlineformincoming", ( 
                ( "CollationID", db.di(collationid)),
                ( "FormName", db.ds(formname)),
                ( "PostedDate", db.ddt(posteddate)),
                ( "Flags", db.ds(flags)),
                ( "FieldName", db.ds(fieldname)),
                ( "Label", db.ds(label)),
                ( "DisplayIndex", db.di(displayindex)),
                ( "Host", db.ds(remoteip)),
                ( "Value", post.db_string(k))
                ))
            db.execute(dbo, sql)
    # Sort out the preview of the first few fields
    fieldssofar = 0
    preview = []
    for fld in get_onlineformincoming_detail(dbo, collationid):
        if fieldssofar < 3:
            fieldssofar += 1
            preview.append( fld["LABEL"] + ": " + fld["VALUE"] )
    db.execute(dbo, "UPDATE onlineformincoming SET Preview = %s WHERE CollationID = %s" % ( db.ds(", ".join(preview)), db.di(collationid) ))
    # Did the original form specify some email addresses to send 
    # incoming submissions to?
    email = db.query_string(dbo, "SELECT o.EmailAddress FROM onlineform o " \
        "INNER JOIN onlineformincoming oi ON oi.FormName = o.Name " \
        "WHERE oi.CollationID = %d" % int(collationid))
    if email is not None and email.strip() != "":
        utils.send_email(dbo, configuration.email(dbo), email, "", "%s - %s" % (formname, ", ".join(preview)), get_onlineformincoming_plain(dbo, collationid))
    return collationid
Exemple #24
0
def insert_onlineformincoming_from_form(dbo, data, remoteip):
    """
    Create onlineformincoming records from posted data. We 
    create a row for every key/value pair in the posted data
    with a unique collation ID.
    """
    IGNORE_FIELDS = [
        "formname", "flags", "redirect", "account", "filechooser", "method"
    ]
    collationid = db.query_int(
        dbo, "SELECT MAX(CollationID) FROM onlineformincoming") + 1
    formname = utils.df_ks(data, "formname")
    posteddate = i18n.now(dbo.timezone)
    flags = utils.df_ks(data, "flags")
    for k, v in data.iteritems():
        if k not in IGNORE_FIELDS:
            label = ""
            displayindex = 0
            fieldname = k
            # Form fields should have a _ONLINEFORMFIELD.ID suffix we can use to get the
            # original label and display position
            if k.find("_") != -1:
                fid = utils.cint(k[k.rfind("_") + 1:])
                fieldname = k[0:k.rfind("_")]
                if fid != 0:
                    fld = db.query(
                        dbo,
                        "SELECT Label, DisplayIndex FROM onlineformfield WHERE ID = %d"
                        % fid)
                    if len(fld) > 0:
                        label = fld[0]["LABEL"]
                        displayindex = fld[0]["DISPLAYINDEX"]

            sql = db.make_insert_sql(
                "onlineformincoming",
                (("CollationID", db.di(collationid)),
                 ("FormName", db.ds(formname)),
                 ("PostedDate", db.ddt(posteddate)), ("Flags", db.ds(flags)),
                 ("FieldName", db.ds(fieldname)), ("Label", db.ds(label)),
                 ("DisplayIndex", db.di(displayindex)),
                 ("Host", db.ds(remoteip)), ("Value", db.ds(v))))
            db.execute(dbo, sql)
    # Sort out the preview of the first few fields
    fieldssofar = 0
    preview = []
    for fld in get_onlineformincoming_detail(dbo, collationid):
        if fieldssofar < 3:
            fieldssofar += 1
            preview.append(fld["LABEL"] + ": " + fld["VALUE"])
    db.execute(
        dbo,
        "UPDATE onlineformincoming SET Preview = %s WHERE CollationID = %s" %
        (db.ds(", ".join(preview)), db.di(collationid)))
    return collationid
Exemple #25
0
def update_appointment_total(dbo, appointmentid):
    """
    Calculates the amount and VAT on an appointment/invoice
    """
    a = get_appointment(dbo, appointmentid)
    total = dbo.query_int(
        "SELECT SUM(Amount) FROM clinicinvoiceitem WHERE ClinicAppointmentID = ? AND Amount Is Not Null AND Amount > 0",
        [appointmentid])
    vatamount = 0
    if a.ISVAT == 1 and a.VATRATE > 0:
        vatamount = utils.cint(total * (a.VATRATE / 100.0))
    dbo.update("clinicappointment", appointmentid, {
        "Amount": total,
        "VATAmount": vatamount
    })
Exemple #26
0
def insert_onlineformincoming_from_form(dbo, data, remoteip):
    """
    Create onlineformincoming records from posted data. We 
    create a row for every key/value pair in the posted data
    with a unique collation ID.
    """
    IGNORE_FIELDS = [ "formname", "flags", "redirect", "account", "filechooser", "method" ]
    collationid = db.query_int(dbo, "SELECT MAX(CollationID) FROM onlineformincoming") + 1
    formname = utils.df_ks(data, "formname")
    posteddate = i18n.now(dbo.timezone)
    flags = utils.df_ks(data, "flags")
    for k, v in data.iteritems():
        if k not in IGNORE_FIELDS:
            label = ""
            displayindex = 0
            fieldname = k
            # Form fields should have a _ONLINEFORMFIELD.ID suffix we can use to get the
            # original label and display position
            if k.find("_") != -1:
                fid = utils.cint(k[k.rfind("_")+1:])
                fieldname = k[0:k.rfind("_")]
                if fid != 0:
                    fld = db.query(dbo, "SELECT Label, DisplayIndex FROM onlineformfield WHERE ID = %d" % fid)
                    if len(fld) > 0:
                        label = fld[0]["LABEL"]
                        displayindex = fld[0]["DISPLAYINDEX"]

            sql = db.make_insert_sql("onlineformincoming", ( 
                ( "CollationID", db.di(collationid)),
                ( "FormName", db.ds(formname)),
                ( "PostedDate", db.ddt(posteddate)),
                ( "Flags", db.ds(flags)),
                ( "FieldName", db.ds(fieldname)),
                ( "Label", db.ds(label)),
                ( "DisplayIndex", db.di(displayindex)),
                ( "Host", db.ds(remoteip)),
                ( "Value", db.ds(v))
                ))
            db.execute(dbo, sql)
    # Sort out the preview of the first few fields
    fieldssofar = 0
    preview = []
    for fld in get_onlineformincoming_detail(dbo, collationid):
        if fieldssofar < 3:
            fieldssofar += 1
            preview.append( fld["LABEL"] + ": " + fld["VALUE"] )
    db.execute(dbo, "UPDATE onlineformincoming SET Preview = %s WHERE CollationID = %s" % ( db.ds(", ".join(preview)), db.di(collationid) ))
    return collationid
Exemple #27
0
def stock_take_from_mobile_form(dbo, username, post):
    """
    Post should contain sl{ID} values for new balances.
    """
    if post.integer("usagetype") == 0:
        raise utils.ASMValidationError("No usage type passed")
    for k in post.data.iterkeys():
        if k.startswith("sl"):
            slid = utils.cint(k.replace("sl", ""))
            sl = get_stocklevel(dbo, slid)
            slb = utils.cfloat(sl["BALANCE"]) # balance
            sln = post.floating(k)            # new balance
            # If the balance hasn't changed, do nothing
            if slb == sln: continue
            # Update the level
            db.execute(dbo, "UPDATE stocklevel SET Balance = %f WHERE ID = %d" % ( sln, slid ))
            # Write a stock usage record for the difference
            insert_stockusage(dbo, username, slid, sln - slb, now(dbo.timezone), post.integer("usagetype"), "")
Exemple #28
0
def get_tests_outstanding(dbo, offset = "m31", locationfilter = ""):
    """
    Returns a recordset of animals awaiting tests:
    offset is m to go backwards, or p to go forwards with a number of days.
    ID, ANIMALID, SHELTERCODE, ANIMALNAME, LOCATIONNAME, WEBSITEMEDIANAME, DATEREQUIRED, DATEOFTEST, COMMENTS, TESTNAME, RESULTNAME, TESTTYPEID
    """
    ec = ""
    offsetdays = utils.cint(offset[1:])
    if offset.startswith("m"):
        ec = " AND DateRequired >= %s AND DateRequired <= %s" % (db.dd( subtract_days(now(dbo.timezone), offsetdays)), db.dd(now(dbo.timezone)))
    if offset.startswith("p"):
        ec = " AND DateRequired >= %s AND DateRequired <= %s" % (db.dd(now(dbo.timezone)), db.dd( add_days(now(dbo.timezone), offsetdays)))
    if locationfilter != "":
        locationfilter = " AND ShelterLocation IN (%s)" % locationfilter
    return db.query(dbo, "SELECT * FROM v_animaltest " \
        "WHERE DateRequired Is Not Null AND DateOfTest Is Null " \
        "AND DeceasedDate Is Null AND (Archived = 0 OR ActiveMovementType = 2) %s %s " \
        "ORDER BY DateRequired, AnimalName" % (ec, locationfilter))
Exemple #29
0
def get_vaccinations_outstanding(dbo, offset = "m31", locationfilter = ""):
    """
    Returns a recordset of animals awaiting vaccinations:
    offset is m to go backwards, or p to go forwards with a number of days.
    locationfilter is a comma separated list of internal locations to include animals in
    ID, ANIMALID, SHELTERCODE, ANIMALNAME, LOCATIONNAME, WEBSITEMEDIANAME, DATEREQUIRED, DATEOFVACCINATION, COMMENTS, VACCINATIONTYPE, VACCINATIONID
    """
    ec = ""
    offsetdays = utils.cint(offset[1:])
    if offset.startswith("m"):
        ec = " AND DateRequired >= %s AND DateRequired <= %s" % (db.dd( subtract_days(now(dbo.timezone), offsetdays)), db.dd(now(dbo.timezone)))
    if offset.startswith("p"):
        ec = " AND DateRequired >= %s AND DateRequired <= %s" % (db.dd(now(dbo.timezone)), db.dd( add_days(now(dbo.timezone), offsetdays)))
    if locationfilter != "":
        locationfilter = " AND ShelterLocation IN (%s)" % locationfilter
    return db.query(dbo, "SELECT * FROM v_animalvaccination " \
        "WHERE DateRequired Is Not Null AND DateOfVaccination Is Null " \
        "AND DeceasedDate Is Null AND (Archived = 0 OR ActiveMovementType = 2) %s %s " \
        "ORDER BY DateRequired, AnimalName" % (ec, locationfilter))
Exemple #30
0
def stock_take_from_mobile_form(dbo, username, post):
    """
    Post should contain sl{ID} values for new balances.
    """
    if post.integer("usagetype") == 0:
        raise utils.ASMValidationError("No usage type passed")

    for k in post.data.iterkeys():
        if k.startswith("sl"):
            slid = utils.cint(k.replace("sl", ""))
            sl = get_stocklevel(dbo, slid)
            slb = utils.cfloat(sl.BALANCE)  # balance
            sln = post.floating(k)  # new balance
            # If the balance hasn't changed, do nothing
            if slb == sln: continue
            # Update the level
            dbo.update("stocklevel", slid, {"Balance": sln})
            # Write a stock usage record for the difference
            insert_stockusage(dbo, username, slid, sln - slb,
                              now(dbo.timezone), post.integer("usagetype"), "")
def get_waitinglist_find_simple(dbo, query = "", limit = 0, onlyindexed = False):
    """
    Returns rows for simple waiting list searches.
    query: The search criteria
    """
    # If no query has been given, do a current waitinglist search
    if query == "":
        return get_waitinglist(dbo)

    ors = []
    add = lambda f: "LOWER(%s) LIKE '%%%s%%'" % (f, query.lower())
    if utils.is_numeric(query):
        ors.append("a.ID = " + str(utils.cint(query)))
    ors.append(add("a.OwnerName"))
    ors.append(add("a.AnimalDescription"))
    if not onlyindexed:
        ors.append(add("a.ReasonForWantingToPart"))
        ors.append(add("a.ReasonForRemoval"))
    sql = get_waitinglist_query() + " WHERE " + " OR ".join(ors)
    if limit > 0: sql += " LIMIT " + str(limit)
    return db.query(dbo, sql)
Exemple #32
0
def get_waitinglist_find_simple(dbo, query="", limit=0, onlyindexed=False):
    """
    Returns rows for simple waiting list searches.
    query: The search criteria
    """
    # If no query has been given, do a current waitinglist search
    if query == "":
        return get_waitinglist(dbo)

    ors = []
    add = lambda f: "LOWER(%s) LIKE '%%%s%%'" % (f, query.lower())
    if utils.is_numeric(query):
        ors.append("a.ID = " + str(utils.cint(query)))
    ors.append(add("a.OwnerName"))
    ors.append(add("a.AnimalDescription"))
    if not onlyindexed:
        ors.append(add("a.ReasonForWantingToPart"))
        ors.append(add("a.ReasonForRemoval"))
    sql = get_waitinglist_query() + " WHERE " + " OR ".join(ors)
    if limit > 0: sql += " LIMIT " + str(limit)
    return db.query(dbo, sql)
Exemple #33
0
def get_tests_outstanding(dbo, offset="m31", locationfilter=""):
    """
    Returns a recordset of animals awaiting tests:
    offset is m to go backwards, or p to go forwards with a number of days.
    ID, ANIMALID, SHELTERCODE, ANIMALNAME, LOCATIONNAME, WEBSITEMEDIANAME, DATEREQUIRED, DATEOFTEST, COMMENTS, TESTNAME, RESULTNAME, TESTTYPEID
    """
    ec = ""
    offsetdays = utils.cint(offset[1:])
    if offset.startswith("m"):
        ec = " AND DateRequired >= %s AND DateRequired <= %s" % (db.dd(
            subtract_days(now(dbo.timezone),
                          offsetdays)), db.dd(now(dbo.timezone)))
    if offset.startswith("p"):
        ec = " AND DateRequired >= %s AND DateRequired <= %s" % (db.dd(
            now(dbo.timezone)), db.dd(add_days(now(dbo.timezone), offsetdays)))
    if locationfilter != "":
        locationfilter = " AND ShelterLocation IN (%s)" % locationfilter
    return db.query(dbo, "SELECT * FROM v_animaltest " \
        "WHERE DateRequired Is Not Null AND DateOfTest Is Null " \
        "AND DeceasedDate Is Null AND (Archived = 0 OR ActiveMovementType = 2) %s %s " \
        "ORDER BY DateRequired, AnimalName" % (ec, locationfilter))
Exemple #34
0
def get_vaccinations_outstanding(dbo, offset="m31", locationfilter=""):
    """
    Returns a recordset of animals awaiting vaccinations:
    offset is m to go backwards, or p to go forwards with a number of days.
    locationfilter is a comma separated list of internal locations to include animals in
    ID, ANIMALID, SHELTERCODE, ANIMALNAME, LOCATIONNAME, WEBSITEMEDIANAME, DATEREQUIRED, DATEOFVACCINATION, COMMENTS, VACCINATIONTYPE, VACCINATIONID
    """
    ec = ""
    offsetdays = utils.cint(offset[1:])
    if offset.startswith("m"):
        ec = " AND DateRequired >= %s AND DateRequired <= %s" % (db.dd(
            subtract_days(now(dbo.timezone),
                          offsetdays)), db.dd(now(dbo.timezone)))
    if offset.startswith("p"):
        ec = " AND DateRequired >= %s AND DateRequired <= %s" % (db.dd(
            now(dbo.timezone)), db.dd(add_days(now(dbo.timezone), offsetdays)))
    if locationfilter != "":
        locationfilter = " AND ShelterLocation IN (%s)" % locationfilter
    return db.query(dbo, "SELECT * FROM v_animalvaccination " \
        "WHERE DateRequired Is Not Null AND DateOfVaccination Is Null " \
        "AND DeceasedDate Is Null AND (Archived = 0 OR ActiveMovementType = 2) %s %s " \
        "ORDER BY DateRequired, AnimalName" % (ec, locationfilter))
Exemple #35
0
def get_animalcontrol_find_simple(dbo,
                                  query="",
                                  username="",
                                  limit=0,
                                  siteid=0):
    """
    Returns rows for simple animal control searches.
    query: The search criteria
    """
    ss = utils.SimpleSearchBuilder(dbo, query)

    sitefilter = ""
    if siteid != 0:
        sitefilter = " AND (ac.SiteID = 0 OR ac.SiteID = %d)" % siteid

    # If no query has been given, show open animal control records
    # from the last 30 days
    if query == "":
        ss.ors.append(
            "ac.IncidentDateTime > %s AND ac.CompletedDate Is Null %s" %
            (dbo.sql_date(dbo.today(offset=-30)), sitefilter))
    else:
        if utils.is_numeric(query):
            ss.add_field_value("ac.ID", utils.cint(query))
        ss.add_fields([
            "co.OwnerName", "ti.IncidentName", "ac.DispatchAddress",
            "ac.DispatchPostcode", "o1.OwnerName", "o2.OwnerName",
            "o3.OwnerName", "vo.OwnerName"
        ])
        ss.add_clause(u"EXISTS(SELECT ad.Value FROM additional ad " \
            "INNER JOIN additionalfield af ON af.ID = ad.AdditionalFieldID AND af.Searchable = 1 " \
            "WHERE ad.LinkID=ac.ID AND ad.LinkType IN (%s) AND LOWER(ad.Value) LIKE ?)" % (additional.INCIDENT_IN))
        ss.add_large_text_fields(["ac.CallNotes", "ac.AnimalDescription"])

    sql = "%s WHERE ac.ID > 0 %s AND (%s) ORDER BY ac.ID" % (
        get_animalcontrol_query(dbo), sitefilter, " OR ".join(ss.ors))
    return reduce_find_results(
        dbo, username, dbo.query(sql, ss.values, limit=limit, distincton="ID"))
Exemple #36
0
def get_donations(dbo, offset = "m31"):
    """
    Returns a recordset of donations
    offset is m to go backwards, or p to go forwards with a number of days.
    ID, DONATIONTYPEID, DONATIONNAME, DATE, DATEDUE, DONATION,
    ISGIFTAID, FREQUENCY, FREQUENCYNAME, NEXTCREATED, COMMENTS, OWNERNAME, 
    ANIMALNAME, SHELTERCODE, OWNERID, ANIMALID
    """
    ec = ""
    order = ""
    offsetdays = utils.cint(offset[1:])
    if offset.startswith("m"):
        ec = "Date >= %s AND Date <= %s" % (db.dd( i18n.subtract_days(i18n.now(dbo.timezone), offsetdays)), db.dd(i18n.now(dbo.timezone)))
        order = "Date DESC"
    elif offset.startswith("p"):
        ec = "Date Is Null AND DateDue >= %s AND DateDue <= %s" % (db.dd(i18n.now(dbo.timezone)), db.dd(i18n.add_days(i18n.now(dbo.timezone), offsetdays)))
        order = "DateDue DESC"
    elif offset.startswith("d"):
        ec = "Date Is Null AND DateDue <= %s" % (db.dd(i18n.now(dbo.timezone)))
        order = "DateDue"
    return db.query(dbo, "SELECT * FROM v_ownerdonation " \
        "WHERE %s "
        "ORDER BY %s" % (ec, order))
Exemple #37
0
def get_onlineformincoming_html_print(dbo, ids):
    """
    Returns a complete printable version of the online form
    (header/footer wrapped around the html call above)
    ids: A list of integer ids
    """
    header = get_onlineform_header(dbo)
    headercontent = header[header.find("<body>")+6:]
    header = header[0:header.find("<body>")+6]
    footer = get_onlineform_footer(dbo)
    footercontent = footer[0:footer.find("</body>")]
    h = []
    h.append(header)
    for collationid in ids:
        h.append(headercontent)
        formheader = get_onlineformincoming_formheader(dbo, collationid)
        h.append(formheader)
        h.append(get_onlineformincoming_html(dbo, utils.cint(collationid)))
        formfooter = get_onlineformincoming_formfooter(dbo, collationid)
        h.append(formfooter)
        h.append(footercontent)
        h.append('<div style="page-break-before: always;"></div>')
    h.append("</body></html>")
    return "\n".join(h)
Exemple #38
0
def get_treatments_outstanding(dbo, offset = "m31", locationfilter = ""):
    """
    Returns a recordset of shelter animals awaiting medical treatments:
    offset is m to go backwards, or p to go forwards with a number of days.
    ANIMALID, SHELTERCODE, ANIMALNAME, LOCATIONNAME, WEBSITEMEDIANAME,
    TREATMENTNAME, COST, COMMENTS, NAMEDFREQUENCY, NAMEDNUMBEROFTREATMENTS,
    NAMEDSTATUS, DOSAGE, STARTDATE, TREATMENTSGIVEN, TREATMENTSREMAINING,
    TIMINGRULE, TIMINGRULEFREQUENCY, TIMINGRULENOFREQUENCIES, TREATMENTRULE
    TOTALNUMBEROFTREATMENTS, DATEREQUIRED, DATEGIVEN, TREATMENTCOMMENTS,
    TREATMENTNUMBER, TOTALTREATMENTS, GIVENBY, REGIMENID, TREATMENTID
    """
    ec = ""
    offsetdays = utils.cint(offset[1:])
    if offset.startswith("m"):
        ec = " AND DateRequired >= %s AND DateRequired <= %s" % (db.dd( subtract_days(now(dbo.timezone), offsetdays)), db.dd(now(dbo.timezone)))
    if offset.startswith("p"):
        ec = " AND DateRequired >= %s AND DateRequired <= %s" % (db.dd(now(dbo.timezone)), db.dd( add_days(now(dbo.timezone), offsetdays)))
    if locationfilter != "":
        locationfilter = " AND ShelterLocation IN (%s)" % locationfilter
    return embellish_regimen(dbo.locale, db.query(dbo, "SELECT * FROM v_animalmedicaltreatment " \
        "WHERE DateRequired Is Not Null AND DateGiven Is Null " \
        "AND Status = 0 " \
        "AND DeceasedDate Is Null AND (Archived = 0 OR ActiveMovementType = 2) %s %s " \
        "ORDER BY DateRequired, AnimalName" % (ec, locationfilter)))
Exemple #39
0
def get_foundanimal_find_advanced(dbo, criteria, limit = 0):
    """
    Returns rows for advanced lost animal searches.
    criteria: A dictionary of criteria
       number - string partial pattern
       contact - string partial pattern
       area - string partial pattern
       postcode - string partial pattern
       features - string partial pattern
       agegroup - agegroup text to match
       sex - -1 for all or ID
       species - -1 for all or ID
       breed - -1 for all or ID
       colour - -1 for all or ID
       excludecomplete - 1 for yes
       datefrom - lost date from in current display locale format
       dateto - lost date to in current display locale format
       completefrom - returned date from in current display locale format
       completeto - returned date to in current display locale format
    """
    c = []
    l = dbo.locale
    post = utils.PostedData(criteria, l)

    def hk(cfield):
        return post[cfield] != ""

    def crit(cfield):
        return post[cfield]

    def addid(cfield, field): 
        if hk(cfield) and int(crit(cfield)) != -1: 
            c.append("%s = %s" % (field, crit(cfield)))

    def addstr(cfield, field): 
        if hk(cfield) and crit(cfield) != "": 
            c.append("LOWER(%s) LIKE '%%%s%%'" % ( field, crit(cfield).lower().replace("'", "`")))

    def adddate(cfieldfrom, cfieldto, field): 
        if hk(cfieldfrom) and hk(cfieldto): 
            c.append("%s >= %s AND %s <= %s" % ( 
            field, db.dd(display2python(l, crit(cfieldfrom))), 
            field, db.dd(display2python(l, crit(cfieldto)))))

    c.append("a.ID > 0")
    if crit("number") != "": c.append("a.ID = %s" % utils.cint(crit("number")))
    addstr("contact", "o.OwnerName")
    addstr("area", "a.AreaFound")
    addstr("postcode", "a.AreaPostcode")
    addstr("features", "a.DistFeat")
    if (crit("agegroup") != "-1"): addstr("agegroup", "a.AgeGroup")
    addid("sex", "a.Sex")
    addid("species", "a.AnimalTypeID")
    addid("breed", "a.BreedID")
    addid("colour", "a.BaseColourID")
    adddate("datefrom", "dateto", "a.DateFound")
    if crit("excludecomplete") == "1":
        c.append("a.ReturnToOwnerDate Is Null")
    elif crit("completefrom") != "" and crit("completeto") != "":
        adddate("completefrom", "completeto", "a.ReturnToOwnerDate")
    where = " WHERE " + " AND ".join(c)
    sql = get_foundanimal_query(dbo) + where + " ORDER BY a.ID"
    if limit > 0: sql += " LIMIT " + str(limit)
    return db.query(dbo, sql)
Exemple #40
0
def handler(post, path, remoteip, referer, querystring):
    """ Handles the various service method types.
    post:        The GET/POST parameters
    path:        The current system path/code.PATH
    remoteip:    The IP of the caller
    referer:     The referer HTTP header
    querystring: The complete querystring
    return value is a tuple containing MIME type, max-age, content
    """
    # Get service parameters
    account = post["account"]
    username = post["username"]
    password = post["password"]
    method = post["method"]
    animalid = post.integer("animalid")
    formid = post.integer("formid")
    seq = post.integer("seq")
    title = post["title"]
    strip_personal = post.integer("sensitive") == 0

    cache_key = querystring.replace(" ", "")

    # Do we have a cached response for these parameters?
    cached_response = get_cached_response(cache_key)
    if cached_response is not None:
        al.debug("cache hit for %s" % (cache_key), "service.handler")
        return cached_response

    # Are we dealing with multiple databases, but no account was specified?
    if account == "" and MULTIPLE_DATABASES:
        return ("text/plain", 0, 0, "ERROR: No database/alias specified")

    dbo = db.get_database(account)

    if dbo.database in ("FAIL", "DISABLED", "WRONGSERVER"):
        al.error(
            "auth failed - invalid smaccount %s from %s (%s)" %
            (account, remoteip, dbo.database), "service.handler", dbo)
        return ("text/plain", 0, 0,
                "ERROR: Invalid database (%s)" % dbo.database)

    # If the database has disabled the service API, stop now
    if not configuration.service_enabled(dbo):
        al.error("Service API is disabled (%s)" % method, "service.handler",
                 dbo)
        return ("text/plain", 0, 0, "ERROR: Service API is disabled")

    # Do any database updates need doing in this db?
    dbo.installpath = path
    if dbupdate.check_for_updates(dbo):
        dbupdate.perform_updates(dbo)

    # Does the method require us to authenticate? If so, do it.
    user = None
    securitymap = ""
    if method in AUTH_METHODS:
        # If the database has authenticated service methods disabled, stop now
        if not configuration.service_auth_enabled(dbo):
            al.error("Service API for auth methods is disabled (%s)" % method,
                     "service.handler", dbo)
            return ("text/plain", 0, 0,
                    "ERROR: Service API for authenticated methods is disabled")
        user = users.authenticate(dbo, username, password)
        if user is None:
            al.error(
                "auth failed - %s/%s is not a valid username/password from %s"
                % (username, password, remoteip), "service.handler", dbo)
            return ("text/plain", 0, 0, "ERROR: Invalid username and password")
        securitymap = users.get_security_map(dbo, user["USERNAME"])

    # Get the preferred locale and timezone for the site
    l = configuration.locale(dbo)
    dbo.locale = l
    dbo.timezone = configuration.timezone(dbo)
    al.info("call %s->%s [%s %s]" % (username, method, str(animalid), title),
            "service.handler", dbo)

    if method == "animal_image":
        hotlink_protect("animal_image", referer)
        if utils.cint(animalid) == 0:
            al.error(
                "animal_image failed, %s is not an animalid" % str(animalid),
                "service.handler", dbo)
            return ("text/plain", 0, 0, "ERROR: Invalid animalid")
        else:
            mediadate, data = media.get_image_file_data(
                dbo, "animal", utils.cint(animalid), seq)
            if data == "NOPIC":
                mediadate, data = media.get_image_file_data(dbo, "nopic", 0)
            return set_cached_response(cache_key, "image/jpeg", 86400, 3600,
                                       data)

    elif method == "animal_thumbnail":
        if utils.cint(animalid) == 0:
            al.error(
                "animal_thumbnail failed, %s is not an animalid" %
                str(animalid), "service.handler", dbo)
            return ("text/plain", 0, 0, "ERROR: Invalid animalid")
        else:
            mediadate, data = media.get_image_file_data(
                dbo, "animalthumb", utils.cint(animalid), seq)
            if data == "NOPIC":
                mediadate, data = media.get_image_file_data(dbo, "nopic", 0)
            return set_cached_response(cache_key, "image/jpeg", 86400, 86400,
                                       data)

    elif method == "animal_view":
        if utils.cint(animalid) == 0:
            al.error(
                "animal_view failed, %s is not an animalid" % str(animalid),
                "service.handler", dbo)
            return ("text/plain", 0, 0, "ERROR: Invalid animalid")
        else:
            return set_cached_response(
                cache_key, "text/html", 86400, 120,
                publishers.html.get_animal_view(dbo, utils.cint(animalid)))

    elif method == "animal_view_adoptable_js":
        return set_cached_response(
            cache_key, "application/javascript", 10800, 600,
            publishers.html.get_animal_view_adoptable_js(dbo))

    elif method == "animal_view_adoptable_html":
        return set_cached_response(
            cache_key, "text/html", 86400, 120,
            publishers.html.get_animal_view_adoptable_html(dbo))

    elif method == "dbfs_image":
        hotlink_protect("dbfs_image", referer)
        return set_cached_response(
            cache_key, "image/jpeg", 86400, 86400,
            utils.iif(title.startswith("/"),
                      dbfs.get_string_filepath(dbo, title),
                      dbfs.get_string(dbo, title)))

    elif method == "extra_image":
        hotlink_protect("extra_image", referer)
        return set_cached_response(cache_key, "image/jpeg", 86400, 86400,
                                   dbfs.get_string(dbo, title, "/reports"))

    elif method == "json_adoptable_animal":
        if utils.cint(animalid) == 0:
            al.error(
                "json_adoptable_animal failed, %s is not an animalid" %
                str(animalid), "service.handler", dbo)
            return ("text/plain", 0, 0, "ERROR: Invalid animalid")
        else:
            users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                       users.VIEW_ANIMAL)
            rs = publishers.base.get_animal_data(
                dbo,
                None,
                utils.cint(animalid),
                include_additional_fields=True)
            return set_cached_response(cache_key, "application/json", 3600,
                                       3600, utils.json(rs))

    elif method == "html_adoptable_animals":
        return set_cached_response(cache_key, "text/html", 10800, 1800, \
            publishers.html.get_adoptable_animals(dbo, style=post["template"], \
                speciesid=post.integer("speciesid"), animaltypeid=post.integer("animaltypeid"), locationid=post.integer("locationid")))

    elif method == "html_adopted_animals":
        return set_cached_response(cache_key, "text/html", 10800, 1800, \
            publishers.html.get_adopted_animals(dbo, daysadopted=post.integer("days"), style=post["template"], \
                speciesid=post.integer("speciesid"), animaltypeid=post.integer("animaltypeid")))

    elif method == "html_deceased_animals":
        return set_cached_response(cache_key, "text/html", 10800, 1800, \
            publishers.html.get_deceased_animals(dbo, daysdeceased=post.integer("days"), style=post["template"], \
                speciesid=post.integer("speciesid"), animaltypeid=post.integer("animaltypeid")))

    elif method == "html_held_animals":
        return set_cached_response(cache_key, "text/html", 10800, 1800, \
            publishers.html.get_held_animals(dbo, style=post["template"], \
                speciesid=post.integer("speciesid"), animaltypeid=post.integer("animaltypeid")))

    elif method == "json_adoptable_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_ANIMAL)
        rs = publishers.base.get_animal_data(dbo,
                                             None,
                                             include_additional_fields=True)
        if strip_personal: rs = strip_personal_data(rs)
        return set_cached_response(cache_key, "application/json", 3600, 3600,
                                   utils.json(rs))

    elif method == "jsonp_adoptable_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_ANIMAL)
        rs = publishers.base.get_animal_data(dbo,
                                             None,
                                             include_additional_fields=True)
        if strip_personal: rs = strip_personal_data(rs)
        return ("application/javascript", 0, 0,
                "%s(%s);" % (post["callback"], utils.json(rs)))

    elif method == "xml_adoptable_animal":
        if utils.cint(animalid) == 0:
            al.error(
                "xml_adoptable_animal failed, %s is not an animalid" %
                str(animalid), "service.handler", dbo)
            return ("text/plain", 0, 0, "ERROR: Invalid animalid")
        else:
            users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                       users.VIEW_ANIMAL)
            rs = publishers.base.get_animal_data(
                dbo,
                None,
                utils.cint(animalid),
                include_additional_fields=True)
            return set_cached_response(cache_key, "application/xml", 3600,
                                       3600, html.xml(rs))

    elif method == "xml_adoptable_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_ANIMAL)
        rs = publishers.base.get_animal_data(dbo,
                                             None,
                                             include_additional_fields=True)
        if strip_personal: rs = strip_personal_data(rs)
        return set_cached_response(cache_key, "application/xml", 3600, 3600,
                                   html.xml(rs))

    elif method == "json_found_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_FOUND_ANIMAL)
        rs = lostfound.get_foundanimal_last_days(dbo)
        return set_cached_response(cache_key, "application/json", 3600, 3600,
                                   utils.json(rs))

    elif method == "jsonp_found_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_FOUND_ANIMAL)
        rs = lostfound.get_foundanimal_last_days(dbo)
        return ("application/javascript", 0, 0,
                "%s(%s);" % (post["callback"], utils.json(rs)))

    elif method == "xml_found_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_FOUND_ANIMAL)
        rs = lostfound.get_foundanimal_last_days(dbo)
        return set_cached_response(cache_key, "application/json", 3600, 3600,
                                   html.xml(rs))

    elif method == "json_lost_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_LOST_ANIMAL)
        rs = lostfound.get_lostanimal_last_days(dbo)
        return set_cached_response(cache_key, "application/json", 3600, 3600,
                                   utils.json(rs))

    elif method == "jsonp_lost_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_LOST_ANIMAL)
        rs = lostfound.get_lostanimal_last_days(dbo)
        return ("application/javascript", 0, 0,
                "%s(%s);" % (post["callback"], utils.json(rs)))

    elif method == "xml_lost_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_LOST_ANIMAL)
        rs = lostfound.get_lostanimal_last_days(dbo)
        return set_cached_response(cache_key, "application/json", 3600, 3600,
                                   html.xml(rs))

    elif method == "json_recent_adoptions":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_ANIMAL)
        rs = movement.get_recent_adoptions(dbo)
        return set_cached_response(cache_key, "application/json", 3600, 3600,
                                   utils.json(rs))

    elif method == "jsonp_recent_adoptions":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_ANIMAL)
        rs = movement.get_recent_adoptions(dbo)
        return ("application/javascript", 0, 0,
                "%s(%s);" % (post["callback"], utils.json(rs)))

    elif method == "xml_recent_adoptions":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_ANIMAL)
        rs = movement.get_recent_adoptions(dbo)
        return set_cached_response(cache_key, "application/xml", 3600, 3600,
                                   html.xml(rs))

    elif method == "html_report":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_REPORT)
        crid = reports.get_id(dbo, title)
        p = reports.get_criteria_params(dbo, crid, post)
        rhtml = reports.execute(dbo, crid, username, p)
        return set_cached_response(cache_key, "text/html", 600, 600, rhtml)

    elif method == "csv_mail" or method == "csv_report":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_REPORT)
        crid = reports.get_id(dbo, title)
        p = reports.get_criteria_params(dbo, crid, post)
        rows, cols = reports.execute_query(dbo, crid, username, p)
        mcsv = utils.csv(l, rows, cols, True)
        return set_cached_response(cache_key, "text/csv", 600, 600, mcsv)

    elif method == "jsonp_recent_changes":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_ANIMAL)
        sa = animal.get_recent_changes(dbo)
        return ("application/javascript", 0, 0,
                "%s(%s);" % (post["callback"], utils.json(sa)))

    elif method == "json_recent_changes":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_ANIMAL)
        sa = animal.get_recent_changes(dbo)
        return set_cached_response(cache_key, "application/json", 3600, 3600,
                                   utils.json(sa))

    elif method == "xml_recent_changes":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_ANIMAL)
        sa = animal.get_recent_changes(dbo)
        return set_cached_response(cache_key, "application/xml", 3600, 3600,
                                   html.xml(sa))

    elif method == "jsonp_shelter_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_ANIMAL)
        sa = animal.get_shelter_animals(dbo)
        if strip_personal: sa = strip_personal_data(sa)
        return ("application/javascript", 0, 0,
                "%s(%s);" % (post["callback"], utils.json(sa)))

    elif method == "json_shelter_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_ANIMAL)
        sa = animal.get_shelter_animals(dbo)
        if strip_personal: sa = strip_personal_data(sa)
        return set_cached_response(cache_key, "application/json", 3600, 3600,
                                   utils.json(sa))

    elif method == "xml_shelter_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_ANIMAL)
        sa = animal.get_shelter_animals(dbo)
        if strip_personal: sa = strip_personal_data(sa)
        return set_cached_response(cache_key, "application/xml", 3600, 3600,
                                   html.xml(sa))

    elif method == "rss_timeline":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.VIEW_ANIMAL)
        return set_cached_response(cache_key, "application/rss+xml", 3600,
                                   3600, html.timeline_rss(dbo))

    elif method == "upload_animal_image":
        users.check_permission_map(l, user["SUPERUSER"], securitymap,
                                   users.ADD_MEDIA)
        media.attach_file_from_form(dbo, username, media.ANIMAL, int(animalid),
                                    post)
        return ("text/plain", 0, 0, "OK")

    elif method == "online_form_html":
        if formid == 0:
            raise utils.ASMError(
                "method online_form_html requires a valid formid")
        return set_cached_response(cache_key, "text/html; charset=utf-8", 120,
                                   120,
                                   onlineform.get_onlineform_html(dbo, formid))

    elif method == "online_form_json":
        if formid == 0:
            raise utils.ASMError(
                "method online_form_json requires a valid formid")
        return set_cached_response(cache_key,
                                   "application/json; charset=utf-8", 30, 30,
                                   onlineform.get_onlineform_json(dbo, formid))

    elif method == "online_form_post":
        flood_protect("online_form_post", remoteip, 15)
        onlineform.insert_onlineformincoming_from_form(dbo, post, remoteip)
        redirect = post["redirect"]
        if redirect == "":
            redirect = BASE_URL + "/static/pages/form_submitted.html"
        return ("redirect", 0, 0, redirect)

    elif method == "sign_document":
        if formid == 0:
            raise utils.ASMError(
                "method sign_document requires a valid formid")
        if post["sig"] == "":
            return set_cached_response(cache_key, "text/html", 2, 2,
                                       sign_document_page(dbo, formid))
        else:
            media.sign_document(dbo, "service", formid, post["sig"],
                                post["signdate"])
            media.create_log(dbo, "service", formid, "ES02",
                             _("Document signed", l))
            return ("text/plain", 0, 0, "OK")

    else:
        al.error("invalid method '%s'" % method, "service.handler", dbo)
        raise utils.ASMError("Invalid method '%s'" % method)
Exemple #41
0
def handler(post, remoteip, referer):
    """
    Handles the various service method types.
    data: The GET/POST parameters 
    return value is a tuple containing MIME type, max-age, content
    """
    # Database info
    dbo = db.DatabaseInfo()

    # Get service parameters
    account = post["account"]
    username = post["username"]
    password = post["password"]
    method = post["method"]
    animalid = post.integer("animalid")
    formid = post.integer("formid")
    seq = post.integer("seq")
    title = post["title"]
    cache_key = "a" + account + "u" + username + "p" + password + "m" + method + \
        "i" + str(animalid) + "s" + str(seq) + "f" + str(formid) + "t" + title
    
    # cache keys aren't allowed spaces
    cache_key = cache_key.replace(" ", "")

    # Do we have a cached response for these parameters?
    cached_response = get_cached_response(cache_key)
    if cached_response is not None:
        al.debug("cache hit for %s/%s/%s/%s" % (account, method, animalid, title), "service.handler")
        return cached_response

    # Are we dealing with multiple databases, but no account was specified?
    if account == "" and MULTIPLE_DATABASES:
        return ("text/plan", 0, "ERROR: No database/alias specified")

    # Are we dealing with multiple databases and an account was specified?
    if account != "":
        if MULTIPLE_DATABASES:
            if MULTIPLE_DATABASES_TYPE == "smcom":
                # Is this sheltermanager.com? If so, we need to get the 
                # database connection info (dbo) before we can login.
                dbo = smcom.get_database_info(account)
            else:
                # Look up the database info from our map
                dbo  = db.get_multiple_database_info(account)
            if dbo.database == "FAIL" or dbo.database == "DISABLED": 
                al.error("auth failed - invalid smaccount %s from %s" % (account, remoteip), "service.handler", dbo)
                return ("text/plain", 0, "ERROR: Invalid database")

    # If the database has disabled the service API, stop now
    if not configuration.service_enabled(dbo):
        al.error("Service API is disabled (%s)" % method, "service.handler", dbo)
        return ("text/plain", 0, "ERROR: Service API is disabled")

    # Do any database updates need doing in this db?
    if dbupdate.check_for_updates(dbo):
        dbupdate.perform_updates(dbo)

    # Does the method require us to authenticate? If so, do it.
    user = None
    securitymap = ""
    if method in AUTH_METHODS:
        # If the database has authenticated service methods disabled, stop now
        if not configuration.service_auth_enabled(dbo):
            al.error("Service API for auth methods is disabled (%s)" % method, "service.handler", dbo)
            return ("text/plain", 0, "ERROR: Service API for authenticated methods is disabled")
        user = users.authenticate(dbo, username, password)
        if user is None:
            al.error("auth failed - %s/%s is not a valid username/password from %s" % (username, password, remoteip), "service.handler", dbo)
            return ("text/plain", 0, "ERROR: Invalid username and password")
        securitymap = users.get_security_map(dbo, user["USERNAME"])

    # Get the preferred locale and timezone for the site
    l = configuration.locale(dbo)
    dbo.locale = l
    dbo.timezone = configuration.timezone(dbo)
    al.info("call %s->%s [%s %s]" % (username, method, str(animalid), title), "service.handler", dbo)

    if method =="animal_image":
        hotlink_protect("animal_image", referer)
        if animalid == "" or utils.cint(animalid) == 0:
            al.error("animal_image failed, %s is not an animalid" % str(animalid), "service.handler", dbo)
            return ("text/plain", 0, "ERROR: Invalid animalid")
        else:
            if seq == 0: seq = 1
            mm = media.get_media_by_seq(dbo, media.ANIMAL, utils.cint(animalid), seq)
            if len(mm) == 0:
                return set_cached_response(cache_key, "image/jpeg", 86400, 120, dbfs.get_string(dbo, "nopic.jpg", "/reports"))
            else:
                return set_cached_response(cache_key, "image/jpeg", 86400, 120, dbfs.get_string(dbo, mm[0]["MEDIANAME"]))

    elif method == "animal_view":
        if animalid == "" or utils.cint(animalid) == 0:
            al.error("animal_view failed, %s is not an animalid" % str(animalid), "service.handler", dbo)
            return ("text/plain", 0, "ERROR: Invalid animalid")
        else:
            return set_cached_response(cache_key, "text/html", 120, 120, publish.get_animal_view(dbo, int(animalid)))

    elif method =="dbfs_image":
        hotlink_protect("dbfs_image", referer)
        return set_cached_response(cache_key, "image/jpeg", 86400, 120, dbfs.get_string_filepath(dbo, title))

    elif method =="extra_image":
        hotlink_protect("extra_image", referer)
        return set_cached_response(cache_key, "image/jpeg", 86400, 120, dbfs.get_string(dbo, title, "/reports"))

    elif method == "json_adoptable_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap, users.VIEW_ANIMAL)
        pc = publish.PublishCriteria(configuration.publisher_presets(dbo))
        rs = publish.get_animal_data(dbo, pc, True)
        return set_cached_response(cache_key, "application/json", 3600, 3600, html.json(rs))

    elif method == "jsonp_adoptable_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap, users.VIEW_ANIMAL)
        pc = publish.PublishCriteria(configuration.publisher_presets(dbo))
        rs = publish.get_animal_data(dbo, pc, True)
        return ("application/javascript", 0, "%s(%s);" % (post["callback"], html.json(rs)))

    elif method == "xml_adoptable_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap, users.VIEW_ANIMAL)
        pc = publish.PublishCriteria(configuration.publisher_presets(dbo))
        rs = publish.get_animal_data(dbo, pc, True)
        return set_cached_response(cache_key, "application/xml", 3600, 3600, html.xml(rs))

    elif method == "json_recent_adoptions":
        users.check_permission_map(l, user["SUPERUSER"], securitymap, users.VIEW_ANIMAL)
        rs = movement.get_recent_adoptions(dbo)
        return set_cached_response(cache_key, "application/json", 3600, 3600, html.json(rs))

    elif method == "jsonp_recent_adoptions":
        users.check_permission_map(l, user["SUPERUSER"], securitymap, users.VIEW_ANIMAL)
        rs = movement.get_recent_adoptions(dbo)
        return ("application/javascript", 0, "%s(%s);" % (post["callback"], html.json(rs)))

    elif method == "xml_recent_adoptions":
        users.check_permission_map(l, user["SUPERUSER"], securitymap, users.VIEW_ANIMAL)
        rs = movement.get_recent_adoptions(dbo)
        return set_cached_response(cache_key, "application/xml", 3600, 3600, html.xml(rs))

    elif method == "html_report":
        users.check_permission_map(l, user["SUPERUSER"], securitymap, users.VIEW_REPORT)
        crid = reports.get_id(dbo, title)
        p = reports.get_criteria_params(dbo, crid, post)
        rhtml = reports.execute(dbo, crid, username, p)
        return set_cached_response(cache_key, "text/html", 3600, 3600, rhtml)

    elif method == "csv_mail" or method == "csv_report":
        users.check_permission_map(l, user["SUPERUSER"], securitymap, users.VIEW_REPORT)
        crid = reports.get_id(dbo, title)
        p = reports.get_criteria_params(dbo, crid, post)
        rows, cols = reports.execute_query(dbo, crid, username, p)
        mcsv = utils.csv(l, rows, cols, True)
        return set_cached_response(cache_key, "text/csv", 3600, 3600, mcsv)

    elif method == "jsonp_shelter_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap, users.VIEW_ANIMAL)
        sa = animal.get_animal_find_simple(dbo, "", "shelter")
        return ("application/javascript", 0, "%s(%s);" % (post["callback"], html.json(sa)))

    elif method == "json_shelter_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap, users.VIEW_ANIMAL)
        sa = animal.get_animal_find_simple(dbo, "", "shelter")
        return set_cached_response(cache_key, "application/json", 3600, 3600, html.json(sa))

    elif method == "xml_shelter_animals":
        users.check_permission_map(l, user["SUPERUSER"], securitymap, users.VIEW_ANIMAL)
        sa = animal.get_animal_find_simple(dbo, "", "shelter")
        return set_cached_response(cache_key, "application/xml", 3600, 3600, html.xml(sa))

    elif method == "rss_timeline":
        users.check_permission_map(l, user["SUPERUSER"], securitymap, users.VIEW_ANIMAL)
        return set_cached_response(cache_key, "application/rss+xml", 3600, 3600, html.timeline_rss(dbo))

    elif method == "upload_animal_image":
        users.check_permission_map(l, user["SUPERUSER"], securitymap, users.ADD_MEDIA)
        media.attach_file_from_form(dbo, username, media.ANIMAL, int(animalid), post)
        return ("text/plain", 0, "OK")

    elif method == "online_form_html":
        if formid == 0:
            raise utils.ASMError("method online_form_html requires a valid formid")
        return set_cached_response(cache_key, "text/html; charset=utf-8", 120, 120, onlineform.get_onlineform_html(dbo, formid))

    elif method == "online_form_json":
        if formid == 0:
            raise utils.ASMError("method online_form_json requires a valid formid")
        return set_cached_response(cache_key, "text/json; charset=utf-8", 30, 30, onlineform.get_onlineform_json(dbo, formid))

    elif method == "online_form_post":
        flood_protect("online_form_post", remoteip, 15)
        onlineform.insert_onlineformincoming_from_form(dbo, post, remoteip)
        redirect = post["redirect"]
        if redirect == "":
            redirect = BASE_URL + "/static/pages/form_submitted.html"
        return ("redirect", 0, redirect)

    elif method == "sign_document":
        if formid == 0:
            raise utils.ASMError("method sign_document requires a valid formid")
        if post["sig"] == "":
            return set_cached_response(cache_key, "text/html", 2, 2, sign_document_page(dbo, formid))
        else:
            media.sign_document(dbo, "service", formid, post["sig"], post["signdate"])
            return ("text/plain", 0, "OK")

    else:
        al.error("invalid method '%s'" % method, "service.handler", dbo)
        raise utils.ASMError("Invalid method '%s'" % method)
Exemple #42
0
    print "       maint_db_dump_dbfs - produce a dump of INSERT statements to recreate the dbfs"
    print "       maint_db_dump_animalcsv - produce a CSV of animal/adoption/owner data"
    print "       maint_db_dump_personcsv - produce a CSV of person data"
    print "       maint_db_dump_smcom - produce an SQL dump for import into sheltermanager.com"
    print "       maint_db_install - install structure/data into a new empty database"
    print "       maint_db_reinstall - wipe the db and reinstall default data"
    print "       maint_recode_all - regenerate all animal codes"
    print "       maint_recode_shelter - regenerate animals codes for all shelter animals"
    print "       maint_reinstall_default_media - re-adds default document/publishing templates"
    print "       maint_scale_animal_images - re-scales all the animal images in the database"
    print "       maint_variable_data - calculate variable data for the day"

if __name__ == "__main__": 
    if len(sys.argv) == 2 and not MULTIPLE_DATABASES:
        # mode argument given and we have a single database
        run_default_database(sys.argv[1])
    elif len(sys.argv) == 2 and MULTIPLE_DATABASES and MULTIPLE_DATABASES_TYPE == "map":
        # mode argument given and we have multiple map databases
        run_all_map_databases(sys.argv[1])
    elif len(sys.argv) == 3 and MULTIPLE_DATABASES:
        # mode and alias given
        run_alias(sys.argv[1], sys.argv[2])
    elif len(sys.argv) == 9:
        # mode and database information given
        run_override_database(sys.argv[1], sys.argv[2], sys.argv[3], utils.cint(sys.argv[4]), sys.argv[5], sys.argv[6], sys.argv[7], sys.argv[8])
    else:
        # We didn't get a valid combination of args
        print_usage()
        sys.exit(1)

Exemple #43
0
def get_animalcontrol_find_advanced(dbo, criteria, limit = 0):
    """
    Returns rows for advanced animal control searches.
    criteria: A dictionary of criteria
       number - string partial pattern
       callername - string partial pattern
       victimname - string partial pattern
       callerphone - string partial pattern
       incidenttype - -1 for all or ID
       dispatchedaco - string partial pattern
       completedtype - -1 for all or ID
       citationtype - -1 for all or ID
       address - string partial pattern
       city - string partial pattern
       postcode - string partial pattern
       pickuplocation - -1 for all or ID
       description - string partial pattern
       agegroup - agegroup text to match
       sex - -1 for all or ID
       species - -1 for all or ID
       filter - unpaid, incomplete, undispatched, requirefollowup
       incidentfrom - incident date from in current display locale format
       incidentto - incident date to in current display locale format
       dispatchfrom - dispatch date from in current display locale format
       dispatchto - dispatch date from in current display locale format
       respondedfrom - responded date from in current display locale format
       respondedto - responded date to in current display locale format
       followupfrom - follow up date from in current display locale format
       followupto - follow up date to in current display locale format
       completedfrom - completed date from in current display locale format
       completedto - completed date to in current display locale format

    """
    c = []
    l = dbo.locale
    post = utils.PostedData(criteria, l)

    def hk(cfield):
        return post[cfield] != ""

    def crit(cfield):
        return post[cfield]

    def addid(cfield, field): 
        if hk(cfield) and int(crit(cfield)) != -1: 
            c.append("%s = %s" % (field, crit(cfield)))

    def addstr(cfield, field): 
        if hk(cfield) and crit(cfield) != "": 
            c.append("LOWER(%s) LIKE '%%%s%%'" % ( field, crit(cfield).lower().replace("'", "`")))

    def adddate(cfieldfrom, cfieldto, field): 
        if hk(cfieldfrom) and hk(cfieldto): 
            post.data["dayend"] = "23:59:59"
            c.append("%s >= %s AND %s <= %s" % ( 
                field, post.db_date(cfieldfrom),
                field, post.db_datetime(cfieldto, "dayend")))

    def addcomp(cfield, value, condition):
        if hk(cfield) and crit(cfield) == value: 
            c.append(condition)

    c.append("ac.ID > 0")
    if crit("number") != "": c.append("ac.ID = " + str(utils.cint(crit("number"))))
    addstr("callername", "co.OwnerName")
    addstr("victimname", "vo.OwnerName")
    addstr("callerphone", "co.HomeTelephone")
    addid("incidenttype", "ac.IncidentTypeID")
    addid("pickuplocation", "ac.PickupLocationID")
    if (crit("dispatchedaco") != "-1"): addstr("dispatchedaco", "ac.DispatchedACO")
    adddate("incidentfrom", "incidentto", "ac.IncidentDateTime")
    adddate("dispatchfrom", "dispatchto", "ac.DispatchDateTime")
    adddate("respondedfrom", "respondedto", "ac.RespondedDateTime")
    adddate("followupfrom", "followupto", "ac.FollwupDateTime")
    adddate("completedfrom", "completedto", "ac.CompletedDate")
    addid("completedtype", "ac.IncidentCompletedID")
    addid("citationtype", "ac.CitationTypeID")
    addstr("address", "ac.DispatchAddress")
    addstr("city", "ac.DispatchTown")
    addstr("postcode", "ac.DispatchPostcode")
    addstr("callnotes", "ac.CallNotes")
    addstr("description", "ac.AnimalDescription")
    if (crit("agegroup") != "-1"): addstr("agegroup", "ac.AgeGroup")
    addid("sex", "ac.Sex")
    addid("species", "ac.SpeciesID")
    addcomp("filter", "incomplete", "ac.CompletedDate Is Null")
    addcomp("filter", "undispatched", "ac.CompletedDate Is Null AND ac.CallDateTime Is Not Null AND ac.DispatchDateTime Is Null")
    addcomp("filter", "requirefollowup", "(" \
        "(ac.FollowupDateTime Is Not Null AND ac.FollowupDateTime <= %(now)s AND NOT ac.FollowupComplete = 1) OR " \
        "(ac.FollowupDateTime2 Is Not Null AND ac.FollowupDateTime2 <= %(now)s AND NOT ac.FollowupComplete2 = 1) OR " \
        "(ac.FollowupDateTime3 Is Not Null AND ac.FollowupDateTime3 <= %(now)s AND NOT ac.FollowupComplete3 = 1) " \
        ")" % { "now": db.dd(now(dbo.timezone))} )
    where = ""
    if len(c) > 0:
        where = " WHERE " + " AND ".join(c)
    sql = get_animalcontrol_query(dbo) + where + " ORDER BY ac.ID"
    if limit > 0: sql += " LIMIT " + str(limit)
    return db.query(dbo, sql)
Exemple #44
0
    if page_name != "" and page_id == "":
        raise utils.ASMValidationError("Could not find page '%s' in Facebook user accounts list (%s)" % (page_name, accounts_list))

    # If we're posting as the page, we can only post to the page.
    # switch us to post using the page's access token
    if post_as == "page":
        post_to = page_id
        access_token = page_access_token

    # If we're posting as us, but to a page, post to the page
    # but stick with the user's access_token
    if page_name != "":
        post_to = page_id

    # Grab the animal details
    a = animal.get_animal(dbo, utils.cint(oauth_state[1:]))

    # Bail out if we have a problem
    if a is None: 
        raise utils.ASMValidationError("Facebook response did not contain a valid animal ID (got %s)" % oauth_state[1:])

    # Generate the body of the post from our facebook template
    tags = wordprocessor.animal_tags(dbo, a)
    template = configuration.facebook_template(dbo)
    posttext = wordprocessor.substitute_tags(template, tags, False, "$$", "$$")

    # Post on the wall
    try:

        l = dbo.locale
        fb_url = "https://graph.facebook.com/%s/photos?access_token=%s" % (post_to, access_token)
Exemple #45
0
def web_login(post, session, remoteip, path):
    """
    Performs a login and sets up the user's session.
    Returns the username on successful login, or:
        FAIL        - problem with user/pass/account/ip
        DISABLED    - The database is disabled
        WRONGSERVER - The database is not on this server
    """
    dbo = db.DatabaseInfo()
    database = post["database"]
    username = post["username"]
    password = post["password"]
    mobileapp = post["mobile"] == "true"
    nologconnection = post["nologconnection"]
    if len(username) > 100:
        username = username[0:100]
    # Do we have multiple databases?
    if MULTIPLE_DATABASES:
        if MULTIPLE_DATABASES_TYPE == "smcom":
            # Is this sheltermanager.com? If so, we need to get the 
            # database connection info (dbo) before we can login.
            # If a database hasn't been supplied, let's bail out now
            # since we can't do anything
            if str(database).strip() == "":
                return "FAIL"
            else:
                dbo = smcom.get_database_info(database)
                # Bail out if there was a problem with the database
                if dbo.database in ("FAIL", "DISABLED", "WRONGSERVER"):
                    return dbo.database
        else:
            # Look up the database info from our map
            dbo  = db.get_multiple_database_info(database)
            if dbo.database == "FAIL":
                return dbo.database
    # Connect to the database and authenticate the username and password
    user = authenticate(dbo, username, password)
    if user is not None and not authenticate_ip(user, remoteip):
        al.error("user %s with ip %s failed ip restriction check '%s'" % (username, remoteip, user["IPRESTRICTION"]), "users.web_login", dbo)
        return "FAIL"
    if user is not None:
        al.info("%s successfully authenticated from %s" % (username, remoteip), "users.web_login", dbo)
        try:
            dbo.locked = configuration.smdb_locked(dbo)
            dbo.timezone = configuration.timezone(dbo)
            dbo.installpath = path
            session.locale = configuration.locale(dbo)
            dbo.locale = session.locale
            session.dbo = dbo
            session.user = user["USERNAME"]
            session.superuser = user["SUPERUSER"]
            session.passchange = (password == "password")
            session.mobileapp = mobileapp
            update_session(session)
        except:
            al.error("failed setting up session: %s" % str(sys.exc_info()[0]), "users.web_login", dbo, sys.exc_info())
            return "FAIL"
        try:
            session.securitymap = get_security_map(dbo, user["USERNAME"])
        except:
            # This is a pre-3002 login where the securitymap is with 
            # the user (the error occurs because there's no role table)
            al.debug("role table does not exist, using securitymap from user", "users.web_login", dbo)
            session.securitymap = user["SECURITYMAP"]
        try:
            ur = get_users(dbo, user["USERNAME"])[0]
            session.roles = ur["ROLES"]
            session.roleids = ur["ROLEIDS"]
            session.siteid = utils.cint(user["SITEID"])
            session.locationfilter = utils.nulltostr(user["LOCATIONFILTER"])
        except:
            # Users coming from v2 won't have the
            # IPRestriction or EmailAddress fields necessary for get_users - we can't
            # help them right now so just give them an empty set of
            # roles and locationfilter until they login again after the db update
            session.roles = ""
            session.roleids = ""
            session.locationfilter = ""
            session.siteid = 0
        try:
            # If it's a sheltermanager.com database, try and update the
            # last time the user connected to today
            if smcom.active() and database != "" and nologconnection == "":
                smcom.set_last_connected(dbo)
        except:
            pass
        try:
            # Mark the user logged in
            audit.login(dbo, username)
            # Check to see if any updates need performing on this database
            if dbupdate.check_for_updates(dbo):
                dbupdate.perform_updates(dbo)
                # We did some updates, better reload just in case config/reports/etc changed
                update_session(session)
            # Check to see if our views and sequences are out of date and need reloading
            if dbupdate.check_for_view_seq_changes(dbo):
                dbupdate.install_db_views(dbo)
                dbupdate.install_db_sequences(dbo)
        except:
            al.error("failed updating database: %s" % str(sys.exc_info()[0]), "users.web_login", dbo, sys.exc_info())
        try:
            al.info("%s logged in" % user["USERNAME"], "users.login", dbo)
            update_user_activity(dbo, user["USERNAME"])
        except:
            al.error("failed updating user activity: %s" % str(sys.exc_info()[0]), "users.web_login", dbo, sys.exc_info())
            return "FAIL"
    else:
        al.error("database:%s username:%s password:%s failed authentication from %s" % (database, username, password, remoteip), "users.web_login", dbo)
        return "FAIL"

    return user["USERNAME"]
Exemple #46
0
    print "       maint_scale_animal_images - re-scales all the animal images in the database"
    print "       maint_variable_data - calculate variable data for the day"


if __name__ == "__main__":
    if len(sys.argv) == 2 and not MULTIPLE_DATABASES:
        # mode argument given and we have a single database
        run_default_database(sys.argv[1])
    elif len(sys.argv) == 2 and MULTIPLE_DATABASES and MULTIPLE_DATABASES_TYPE == "map":
        # mode argument given and we have multiple map databases
        run_all_map_databases(sys.argv[1])
    elif len(sys.argv) == 3 and MULTIPLE_DATABASES:
        # mode and alias given
        run_alias(sys.argv[1], sys.argv[2])
    elif len(sys.argv) == 9:
        # mode and database information given
        run_override_database(
            sys.argv[1],
            sys.argv[2],
            sys.argv[3],
            utils.cint(sys.argv[4]),
            sys.argv[5],
            sys.argv[6],
            sys.argv[7],
            sys.argv[8],
        )
    else:
        # We didn't get a valid combination of args
        print_usage()
        sys.exit(1)
Exemple #47
0
    print "       maint_db_dump_smcom - produce an SQL dump for import into sheltermanager.com"
    print "       maint_db_install - install structure/data into a new empty database"
    print "       maint_db_reinstall - wipe the db and reinstall default data"
    print "       maint_deduplicate_people - automatically merge duplicate people records"
    print "       maint_recode_all - regenerate all animal codes"
    print "       maint_recode_shelter - regenerate animals codes for all shelter animals"
    print "       maint_reinstall_default_media - re-adds default document/publishing templates"
    print "       maint_scale_animal_images - re-scales all the animal images in the database"
    print "       maint_scale_odts - re-scales all odt files attached to records (remove images)"
    print "       maint_scale_pdfs - re-scales all the PDFs in the database"
    print "       maint_variable_data - recalculate all variable data for all animals"

if __name__ == "__main__": 
    if len(sys.argv) == 2 and not MULTIPLE_DATABASES:
        # mode argument given and we have a single database
        run_default_database(sys.argv[1])
    elif len(sys.argv) == 2 and MULTIPLE_DATABASES and MULTIPLE_DATABASES_TYPE == "map":
        # mode argument given and we have multiple map databases
        run_all_map_databases(sys.argv[1])
    elif len(sys.argv) == 3 and MULTIPLE_DATABASES:
        # mode and alias given
        run_alias(sys.argv[1], sys.argv[2])
    elif len(sys.argv) == 9:
        # mode and database information given
        run_override_database(sys.argv[1], sys.argv[2], sys.argv[3], utils.cint(sys.argv[4]), sys.argv[5], sys.argv[6], sys.argv[7], sys.argv[8])
    else:
        # We didn't get a valid combination of args
        print_usage()
        sys.exit(1)

Exemple #48
0
    print "       maint_db_install - install structure/data into a new empty database"
    print "       maint_db_reinstall - wipe the db and reinstall default data"
    print "       maint_recode_all - regenerate all animal codes"
    print "       maint_recode_shelter - regenerate animals codes for all shelter animals"
    print "       maint_reinstall_default_media - re-adds default document/publishing templates"
    print "       maint_scale_animal_images - re-scales all the animal images in the database"
    print "       maint_variable_data - calculate variable data for the day"


if __name__ == "__main__":
    if len(sys.argv) == 2 and not MULTIPLE_DATABASES:
        # mode argument given and we have a single database
        run_default_database(sys.argv[1])
    elif len(
            sys.argv
    ) == 2 and MULTIPLE_DATABASES and MULTIPLE_DATABASES_TYPE == "map":
        # mode argument given and we have multiple map databases
        run_all_map_databases(sys.argv[1])
    elif len(sys.argv) == 3 and MULTIPLE_DATABASES:
        # mode and alias given
        run_alias(sys.argv[1], sys.argv[2])
    elif len(sys.argv) == 9:
        # mode and database information given
        run_override_database(sys.argv[1], sys.argv[2], sys.argv[3],
                              utils.cint(sys.argv[4]), sys.argv[5],
                              sys.argv[6], sys.argv[7], sys.argv[8])
    else:
        # We didn't get a valid combination of args
        print_usage()
        sys.exit(1)
Exemple #49
0
            "Could not find page '%s' in Facebook user accounts list (%s)" %
            (page_name, accounts_list))

    # If we're posting as the page, we can only post to the page.
    # switch us to post using the page's access token
    if post_as == "page":
        post_to = page_id
        access_token = page_access_token

    # If we're posting as us, but to a page, post to the page
    # but stick with the user's access_token
    if page_name != "":
        post_to = page_id

    # Grab the animal details
    a = animal.get_animal(dbo, utils.cint(oauth_state[1:]))

    # Bail out if we have a problem
    if a is None:
        raise utils.ASMValidationError(
            "Facebook response did not contain a valid animal ID (got %s)" %
            oauth_state[1:])

    # Generate the body of the post from our facebook template
    tags = wordprocessor.animal_tags(dbo, a)
    template = configuration.facebook_template(dbo)
    posttext = wordprocessor.substitute_tags(template, tags, False, "$$", "$$")

    # Post on the wall
    try:
Exemple #50
0
def handler(data, remoteip, referer):
    """
    Handles the various service method types.
    data: The GET/POST parameters 
    return value is a tuple containing MIME type, max-age, content
    """
    # Database info
    dbo = db.DatabaseInfo()

    # Get service parameters
    account = utils.df_ks(data, "account")
    username = utils.df_ks(data, "username")
    password = utils.df_ks(data, "password")
    method = utils.df_ks(data, "method")
    animalid = utils.df_ki(data, "animalid")
    formid = utils.df_ki(data, "formid")
    title = utils.df_ks(data, "title")
    cache_key = "a" + account + "u" + username + "p" + password + "m" + method + "a" + str(animalid) + "f" + str(formid) + "t" + title
    
    # cache keys aren't allowed spaces
    cache_key = cache_key.replace(" ", "")

    # Do we have a cached response for these parameters?
    cached_response = get_cached_response(cache_key)
    if cached_response is not None:
        al.debug("cache hit for %s/%s/%s/%s" % (account, method, animalid, title), "service.handler")
        return cached_response

    # Are we dealing with multiple databases, but no account was specified?
    if account == "" and MULTIPLE_DATABASES:
        return ("text/plan", 0, "ERROR: No database/alias specified")

    # Are we dealing with multiple databases and an account was specified?
    if account != "":
        if MULTIPLE_DATABASES:
            if MULTIPLE_DATABASES_TYPE == "smcom":
                # Is this sheltermanager.com? If so, we need to get the 
                # database connection info (dbo) before we can login.
                dbo = smcom.get_database_info(account)
            else:
                # Look up the database info from our map
                dbo  = db.get_multiple_database_info(account)
            if dbo.database == "FAIL" or dbo.database == "DISABLED": 
                al.error("auth failed - invalid smaccount %s from %s" % (account, remoteip), "service.handler", dbo)
                return ("text/plain", 0, "ERROR: Invalid database")

    # Does the method require us to authenticate? If so, do it.
    user = None
    if method in AUTH_METHODS:
        user = users.authenticate(dbo, username, password)
        if user is None:
            al.error("auth failed - %s/%s is not a valid username/password from %s" % (username, password, remoteip), "service.handler", dbo)
            return ("text/plain", 0, "ERROR: Invalid username and password")

    # Get the preferred locale for the site
    dbo.locale = configuration.locale(dbo)
    al.info("call %s->%s [%s %s]" % (username, method, str(animalid), title), "service.handler", dbo)

    if method =="animal_image":
        # If we have a hotlinking restriction, enforce it
        if referer != "" and IMAGE_HOTLINKING_ONLY_FROM_DOMAIN != "" and referer.find(IMAGE_HOTLINKING_ONLY_FROM_DOMAIN) == -1:
            raise utils.ASMPermissionError("Image hotlinking is forbidden.")
        if animalid == "" or utils.cint(animalid) == 0:
            al.error("animal_image failed, %s is not an animalid" % str(animalid), "service.handler", dbo)
            return ("text/plain", 0, "ERROR: Invalid animalid")
        # If the option is on, forbid hotlinking
        else:
            seq = utils.df_ki(data, "seq")
            if seq == 0: seq = 1
            mm = media.get_media_by_seq(dbo, media.ANIMAL, utils.cint(animalid), seq)
            if len(mm) == 0:
                return ("image/jpeg", 86400, dbfs.get_string(dbo, "nopic.jpg", "/reports"))
            else:
                return ("image/jpeg", 86400, dbfs.get_string(dbo, mm[0]["MEDIANAME"]))

    elif method =="extra_image":
        return ("image/jpeg", 86400, dbfs.get_string(dbo, title, "/reports"))

    elif method == "json_adoptable_animals":
        pc = publish.PublishCriteria(configuration.publisher_presets(dbo))
        rs = publish.get_animal_data(dbo, pc, True)
        return set_cached_response(cache_key, "application/json", 3600, html.json(rs))

    elif method == "xml_adoptable_animals":
        pc = publish.PublishCriteria(configuration.publisher_presets(dbo))
        rs = publish.get_animal_data(dbo, pc, True)
        return set_cached_response(cache_key, "application/xml", 3600, html.xml(rs))

    elif method == "json_recent_adoptions":
        rs = movement.get_recent_adoptions(dbo)
        return set_cached_response(cache_key, "application/json", 3600, html.json(rs))

    elif method == "xml_recent_adoptions":
        rs = movement.get_recent_adoptions(dbo)
        return set_cached_response(cache_key, "application/xml", 3600, html.xml(rs))

    elif method == "html_report":
        crid = reports.get_id(dbo, title)
        p = reports.get_criteria_params(dbo, crid, data)
        rhtml = reports.execute(dbo, crid, username, p)
        return set_cached_response(cache_key, "text/html", 3600, rhtml)

    elif method == "jsonp_shelter_animals":
        sa = animal.get_animal_find_simple(dbo, "", "shelter")
        return set_cached_response(cache_key, "application/javascript", 3600, str(utils.df_ks(data, "callback")) + "(" + html.json(sa) + ")")

    elif method == "json_shelter_animals":
        sa = animal.get_animal_find_simple(dbo, "", "shelter")
        return set_cached_response(cache_key, "application/json", 3600, html.json(sa))

    elif method == "xml_shelter_animals":
        sa = animal.get_animal_find_simple(dbo, "", "shelter")
        return set_cached_response(cache_key, "application/xml", 3600, html.json(sa))

    elif method == "upload_animal_image":
        media.attach_file_from_form(dbo, username, media.ANIMAL, int(animalid), data)
        return ("text/plain", 0, "OK")

    elif method == "online_form_html":
        if formid == 0:
            raise utils.ASMError("method online_form_html requires a valid formid")
        return set_cached_response(cache_key, "text/html", 120, onlineform.get_onlineform_html(dbo, formid))

    elif method == "online_form_post":
        onlineform.insert_onlineformincoming_from_form(dbo, data, remoteip)
        redirect = utils.df_ks(data, "redirect")
        if redirect == "":
            redirect = BASE_URL + "/static/pages/form_submitted.html"
        return ("redirect", 0, redirect)

    else:
        al.error("invalid method '%s'" % method, "service.handler", dbo)
        raise utils.ASMError("Invalid method '%s'" % method)
Exemple #51
0
def are_emails_muted():
    from utils import cint
    return flags.mute_emails or cint(conf.get("mute_emails") or 0) or False
Exemple #52
0
def web_login(post, session, remoteip, path):
    """
    Performs a login and sets up the user's session.
    Returns the username on successful login, or:
        FAIL        - problem with user/pass/account/ip
        DISABLED    - The database is disabled
        WRONGSERVER - The database is not on this server
    """
    database = post["database"]
    username = post["username"]
    password = post["password"]
    mobileapp = post["mobile"] == "true"
    nologconnection = post["nologconnection"] == "true"
    if len(username) > 100:
        username = username[0:100]

    dbo = db.get_database(database)

    if dbo.database in ("FAIL", "DISABLED", "WRONGSERVER"):
        return dbo.database

    # Connect to the database and authenticate the username and password
    user = authenticate(dbo, username, password)
    if user is not None and not authenticate_ip(user, remoteip):
        al.error(
            "user %s with ip %s failed ip restriction check '%s'" %
            (username, remoteip, user.IPRESTRICTION), "users.web_login", dbo)
        return "FAIL"

    if user is not None and "DISABLELOGIN" in user and user.DISABLELOGIN == 1:
        al.error(
            "user %s with ip %s failed as account has logins disabled" %
            (username, remoteip), "users.web_login", dbo)
        return "FAIL"

    if user is not None:
        al.info("%s successfully authenticated from %s" % (username, remoteip),
                "users.web_login", dbo)

        try:
            dbo.locked = configuration.smdb_locked(dbo)
            dbo.timezone = configuration.timezone(dbo)
            dbo.installpath = path
            session.locale = configuration.locale(dbo)
            dbo.locale = session.locale
            session.dbo = dbo
            session.user = user.USERNAME
            session.superuser = user.SUPERUSER
            session.mobileapp = mobileapp
            update_session(session)
        except:
            al.error("failed setting up session: %s" % str(sys.exc_info()[0]),
                     "users.web_login", dbo, sys.exc_info())
            return "FAIL"

        try:
            session.securitymap = get_security_map(dbo, user.USERNAME)
        except:
            # This is a pre-3002 login where the securitymap is with
            # the user (the error occurs because there's no role table)
            al.debug("role table does not exist, using securitymap from user",
                     "users.web_login", dbo)
            session.securitymap = user.SECURITYMAP

        try:
            ur = get_users(dbo, user.USERNAME)[0]
            session.roles = ur.ROLES
            session.roleids = ur.ROLEIDS
            session.siteid = utils.cint(user.SITEID)
            session.locationfilter = utils.nulltostr(user.LOCATIONFILTER)
        except:
            # Users coming from v2 won't have the
            # IPRestriction or EmailAddress fields necessary for get_users - we can't
            # help them right now so just give them an empty set of
            # roles and locationfilter until they login again after the db update
            session.roles = ""
            session.roleids = ""
            session.locationfilter = ""
            session.siteid = 0

        try:
            # Mark the user logged in
            if not nologconnection:
                audit.login(dbo, username, remoteip)

            # Check to see if any updates need performing on this database
            if dbupdate.check_for_updates(dbo):
                dbupdate.perform_updates(dbo)
                # We did some updates, better reload just in case config/reports/etc changed
                update_session(session)

            # Check to see if our views and sequences are out of date and need reloading
            if dbupdate.check_for_view_seq_changes(dbo):
                dbupdate.install_db_views(dbo)
                dbupdate.install_db_sequences(dbo)

        except:
            al.error("failed updating database: %s" % str(sys.exc_info()[0]),
                     "users.web_login", dbo, sys.exc_info())

        try:
            al.info("%s logged in" % user.USERNAME, "users.login", dbo)
            update_user_activity(dbo, user.USERNAME)
        except:
            al.error(
                "failed updating user activity: %s" % str(sys.exc_info()[0]),
                "users.web_login", dbo, sys.exc_info())
            return "FAIL"
    else:
        al.error(
            "database:%s username:%s password:%s failed authentication from %s"
            % (database, username, password, remoteip), "users.web_login", dbo)
        return "FAIL"

    return user.USERNAME