/* Calculate the cookie parameters.
 *
 * Parameters:
 *  request_rec *r       The request we should set the cookie in.
 *
 * Returns:
 *  The cookie parameters as a string.
 */
static const char *am_cookie_params(request_rec *r)
{
    int secure_cookie;
    int http_only_cookie;
    const char *cookie_domain = ap_get_server_name(r);
    const char *cookie_path = "/";
    am_dir_cfg_rec *cfg = am_get_dir_cfg(r);

    if (cfg->cookie_domain) {
        cookie_domain = cfg->cookie_domain;
    }

    if (cfg->cookie_path) {
        cookie_path = cfg->cookie_path;
    }

    secure_cookie = cfg->secure;
    http_only_cookie = cfg->http_only;

    return apr_psprintf(r->pool,
                        "Version=1; Path=%s; Domain=%s%s%s;",
                        cookie_path, cookie_domain,
                        http_only_cookie ? "; HttpOnly" : "",
                        secure_cookie ? "; secure" : "");
}
/* This function retrieves the name of our cookie.
 *
 * Parameters:
 *  request_rec *r       The current request. Used to find the identifier of
 *                       the cookie. We also allocate memory from r->pool.
 *
 * Returns:
 *  The name of the cookie.
 */
static const char *am_cookie_name(request_rec *r)
{
    am_dir_cfg_rec *dir_cfg;

    dir_cfg = am_get_dir_cfg(r);

    return apr_pstrcat(r->pool, "mellon-", dir_cfg->varname, NULL);
}
/* This function populates the subprocess environment with data received
 * from the IdP.
 *
 * Parameters:
 *  request_rec *r       The request we should add the data to.
 *  am_cache_entry_t *t  The session data.
 *
 * Returns:
 *  Nothing.
 */
void am_cache_env_populate(request_rec *r, am_cache_entry_t *t)
{
    am_dir_cfg_rec *d;
    int i;
    apr_hash_t *counters;
    am_envattr_conf_t *env_varname_conf;
    const char *varname;
    const char *varname_prefix;
    const char *value;
    int *count;
    int status;

    d = am_get_dir_cfg(r);

    /* Check if the user attribute has been set, and set it if it
     * hasn't been set. */
    if (am_cache_entry_slot_is_empty(&t->user)) {
        for(i = 0; i < t->size; ++i) {
            varname = am_cache_entry_get_string(t, &t->env[i].varname);
            if (strcmp(varname, d->userattr) == 0) {
                value = am_cache_entry_get_string(t, &t->env[i].value);
                status = am_cache_entry_store_string(t, &t->user, value);
                if (status != 0) {
                    ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r,
                                  "Unable to store the user name because there"
                                  " is no more space in the session. "
                                  "Username = \"%s\".", value);
                }
            }
        }
    }

    /* Allocate a set of counters for duplicate variables in the list. */
    counters = apr_hash_make(r->pool);

    /* Populate the subprocess environment with the attributes we
     * received from the IdP.
     */
    for(i = 0; i < t->size; ++i) {
        varname = am_cache_entry_get_string(t, &t->env[i].varname);
        varname_prefix = "MELLON_";

        /* Check if we should map this name into another name. */
        env_varname_conf = (am_envattr_conf_t *)apr_hash_get(
            d->envattr, varname, APR_HASH_KEY_STRING);

        if(env_varname_conf != NULL) {
            varname = env_varname_conf->name;
            if (!env_varname_conf->prefixed) {
              varname_prefix = "";
            }
        }

        value = am_cache_entry_get_string(t, &t->env[i].value);

        /*  
         * If we find a variable remapping to MellonUser, use it.
         */
        if (am_cache_entry_slot_is_empty(&t->user) &&
            (strcmp(varname, d->userattr) == 0)) {
            status = am_cache_entry_store_string(t, &t->user, value);
            if (status != 0) {
                ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r,
                              "Unable to store the user name because there"
                              " is no more space in the session. "
                              "Username = \"%s\".", value);
            }
        }

        /* Find the number of times this variable has been set. */
        count = apr_hash_get(counters, varname, APR_HASH_KEY_STRING);
        if(count == NULL) {

            /* This is the first time. Create a counter for this variable. */
            count = apr_palloc(r->pool, sizeof(int));
            *count = 0;
            apr_hash_set(counters, varname, APR_HASH_KEY_STRING, count);

            /* Add the variable without a suffix. */
            apr_table_set(r->subprocess_env,
                          apr_pstrcat(r->pool, varname_prefix, varname, NULL),
                          value);
        }

        /* Add the variable with a suffix indicating how many times it has
         * been added before.
         */
        apr_table_set(r->subprocess_env,
                      apr_psprintf(r->pool, "%s%s_%d", varname_prefix, varname, *count),
                      value);

        /* Increase the count. */
        ++(*count);
    }

    if (!am_cache_entry_slot_is_empty(&t->user)) {
        /* We have a user-"name". Set r->user and r->ap_auth_type. */
        r->user = apr_pstrdup(r->pool, am_cache_entry_get_string(t, &t->user));
        r->ap_auth_type = apr_pstrdup(r->pool, "Mellon");
    } else {
        /* We don't have a user-"name". Log error. */
        ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r,
                      "Didn't find the attribute \"%s\" in the attributes"
                      " which were received from the IdP. Cannot set a user"
                      " for this request without a valid user attribute.",
                      d->userattr);
    }


    /* Populate with the session? */
    if (d->dump_session) {
        char *session;
        const char *srcstr;
        int srclen, dstlen;

        srcstr = am_cache_entry_get_string(t, &t->lasso_session);
        srclen = strlen(srcstr);
        dstlen = apr_base64_encode_len(srclen);

        session = apr_palloc(r->pool, dstlen);
        (void)apr_base64_encode(session, srcstr, srclen);
        apr_table_set(r->subprocess_env, "MELLON_SESSION", session);
    }

    if (d->dump_saml_response) {
        const char *sr = am_cache_entry_get_string(t, &t->lasso_saml_response);
        if (sr) {
            apr_table_set(r->subprocess_env, "MELLON_SAML_RESPONSE", sr);
        }
    }
}