Example #1
0
def cache_extra_strings():
    """
    Caches strings from the all the extra XML string files.
    The extra string files look like this:
        <?xml version="1.0" encoding="UTF-8"?>
        <resources>
            <task name="TASK_1">
                <string name="NAME_1">VALUE</string>
                <string name="NAME_2">VALUE WITH\nNEWLINE</string>
                <!-- ... -->
            </task>
            <!-- ... -->
        </resources>
    """
    if cc_pls.pls.extraStringDicts is not None:
        return
    if cc_pls.pls.EXTRA_STRING_FILES is None:
        raise AssertionError(
            "pls.EXTRA_STRING_FILES is None -- likely use of "
            "XSTRING/WXSTRING in classmethod, before initialization via "
            "the WSGI application entry point")
    cc_pls.pls.extraStringDicts = {}
    for filename in cc_pls.pls.EXTRA_STRING_FILES:
        logger.debug("Loading XML file: " + filename)
        parser = ElementTree.XMLParser(encoding="UTF-8")
        tree = ElementTree.parse(filename, parser=parser)
        root = tree.getroot()
        for taskroot in root.findall("./task[@name]"):
            taskname = taskroot.attrib.get("name")
            if taskname not in cc_pls.pls.extraStringDicts:
                cc_pls.pls.extraStringDicts[taskname] = {}
            for e in taskroot.findall("./string[@name]"):
                stringname = e.attrib.get("name")
                value = e.text
                cc_pls.pls.extraStringDicts[taskname][stringname] = value
Example #2
0
def cache_strings():
    """
    Caches strings from the main XML string file.
    The string file looks like this:
        <?xml version="1.0" encoding="UTF-8"?>
        <resources>
            <string name="NAME">VALUE</string>
            <!-- ... -->
        </resources>
    """
    if cc_pls.pls.stringDict is not None:
        return
    if cc_pls.pls.CAMCOPS_STRINGS_FILE_ABSOLUTE is None:
        raise AssertionError(
            "pls.CAMCOPS_STRINGS_FILE_ABSOLUTE is None -- likely use of "
            "LSTRING/WSTRING in classmethod, before initialization via "
            "the WSGI application entry point")
    logger.debug("Loading XML file: " +
                 cc_pls.pls.CAMCOPS_STRINGS_FILE_ABSOLUTE)
    parser = ElementTree.XMLParser(encoding="UTF-8")
    tree = ElementTree.parse(cc_pls.pls.CAMCOPS_STRINGS_FILE_ABSOLUTE,
                             parser=parser)
    cc_pls.pls.stringDict = {}
    # find all children of the root with tag "string" and attribute "name"
    for e in tree.findall("./string[@name]"):
        cc_pls.pls.stringDict[e.attrib.get("name")] = e.text
Example #3
0
def get_current_blob_by_client_info(device, clientpk, era):
    """Returns the current Blob object, or None."""
    serverpk = cc_db.get_current_server_pk_by_client_info(
        Blob.TABLENAME, device, clientpk, era)
    if serverpk is None:
        logger.debug("FAILED TO FIND BLOB: " + str(clientpk))
        return None
    return Blob(serverpk)
Example #4
0
def send_analytics_if_necessary():
    """Send analytics to the CamCOPS base server, if required.

    If analytics reporting is enabled, and analytics have not been sent
    recently, collate and send them to the CamCOPS base server in Cambridge,
    UK.
    """
    if not pls.SEND_ANALYTICS:
        # User has disabled analytics reporting.
        return
    lastSentVar = cc_storedvar.ServerStoredVar("lastAnalyticsSentAt", "text",
                                               None)
    lastSentVal = lastSentVar.getValue()
    if lastSentVal:
        elapsed = pls.NOW_UTC_WITH_TZ - cc_dt.get_datetime_from_string(
            lastSentVal)
        if elapsed < ANALYTICS_PERIOD:
            # We sent analytics recently.
            return

    # Compile analytics
    now_as_utc_iso_string = cc_dt.format_datetime(pls.NOW_UTC_WITH_TZ,
                                                  DATEFORMAT.ISO8601)
    (table_names, record_counts) = get_all_tables_with_record_counts()

    # This is what's sent:
    d = {
        "source": "server",
        "now": now_as_utc_iso_string,
        "camcops_version": str(cc_version.CAMCOPS_SERVER_VERSION),
        "server": pls.SERVER_NAME,
        "table_names": ",".join(table_names),
        "record_counts": ",".join([str(x) for x in record_counts]),
    }
    # The HTTP_HOST variable might provide some extra information, but is
    # per-request rather than per-server, making analytics involving it that
    # bit more intrusive for little extra benefit, so let's not send it.
    # See http://stackoverflow.com/questions/2297403 for details.

    # Send it.
    encoded_dict = urllib.urlencode(d)
    request = urllib2.Request(ANALYTICS_URL, encoded_dict)
    try:
        urllib2.urlopen(request, timeout=ANALYTICS_TIMEOUT_MS)
        # connection = urllib2.urlopen(request, timeout=ANALYTICS_TIMEOUT_MS)
        # response = connection.read()  # we don't care
    except (urllib2.URLError, urllib2.HTTPError):
        # something broke; try again next time
        logger.info("Failed to send analytics to {}".format(ANALYTICS_URL))
        return

    # Store current time as last-sent time
    logger.debug("Analytics sent.")
    lastSentVar.setValue(now_as_utc_iso_string)
Example #5
0
def get_contemporaneous_blob_by_client_info(device, clientpk, era,
                                            referrer_added_utc,
                                            referrer_removed_utc):
    """Returns a contemporaneous Blob object, or None.

    Use particularly to look up BLOBs matching old task records.
    """
    serverpk = cc_db.get_contemporaneous_server_pk_by_client_info(
        Blob.TABLENAME, device, clientpk, era,
        referrer_added_utc, referrer_removed_utc)
    if serverpk is None:
        logger.debug("FAILED TO FIND BLOB: " + str(clientpk))
        return None
    return Blob(serverpk)
Example #6
0
def establish_session(env):
    """Look up details from the HTTP environment. Load existing session or
    create a new one. Session is then stored in pls.session (pls being
    process-local storage)."""
    ip_address = env["REMOTE_ADDR"]
    try:
        cookie = Cookie.SimpleCookie(env["HTTP_COOKIE"])
        session_id = cookie["session_id"].value
        session_token = cookie["session_token"].value
        #logger.debug("Found cookie token: ID {}, token {}".format(
        #    session_id, session_token))
    except (Cookie.CookieError, KeyError):
        logger.debug("No cookie yet. Creating new one.")
        session_id = None
        session_token = None
    pls.session = Session(session_id, session_token, ip_address)
Example #7
0
def clear_dummy_login_failures_if_necessary():
    """Clear dummy login failures if we haven't done so for a while.

    Not too often! See CLEAR_DUMMY_LOGIN_FREQUENCY_DAYS.
    """
    lastClearedVar = cc_storedvar.ServerStoredVar(
        "lastDummyLoginFailureClearanceAt", "text", None)
    lastClearedVal = lastClearedVar.getValue()
    if lastClearedVal:
        elapsed = pls.NOW_UTC_WITH_TZ - cc_dt.get_datetime_from_string(
            lastClearedVal)
        if elapsed < CLEAR_DUMMY_LOGIN_PERIOD:
            # We cleared it recently.
            return

    clear_login_failures_for_nonexistent_users()
    logger.debug("Dummy login failures cleared.")
    now_as_utc_iso_string = cc_dt.format_datetime(pls.NOW_UTC_WITH_TZ,
                                                  DATEFORMAT.ISO8601)
    lastClearedVar.setValue(now_as_utc_iso_string)
Example #8
0
def establish_session_for_tablet(session_id, session_token, ip_address,
                                 username, password):
    """As for establish_session, but without using HTTP cookies.
    Resulting session is stored in pls.session."""
    if not session_id or not session_token:
        logger.debug("No session yet for tablet. Creating new one.")
        session_id = None
        session_token = None
    pls.session = Session(session_id, session_token, ip_address)
    # Creates a new session if necessary
    if pls.session.userobject and pls.session.user != username:
        # We found a session, and it's associated with a user, but with
        # the wrong user. This is unlikely to happen!
        # Wipe the old one:
        pls.session.logout()
        # Create a fresh session.
        pls.session = Session(None, None, ip_address)
    if not pls.session.userobject and username:
        userobject = cc_user.get_user(username, password)  # checks password
        if userobject is not None and (userobject.may_upload
                                       or userobject.may_use_webstorage):
            # Successful login.
            pls.session.login(userobject)