/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/
/** * Structure to carry the per-dir session config.
*/ typedefstruct { constchar *name; int name_set; constchar *name_attrs; constchar *name2; int name2_set; constchar *name2_attrs; int peruser; int peruser_set; int remove; int remove_set; constchar *selectlabel; constchar *insertlabel; constchar *updatelabel; constchar *deletelabel;
} session_dbd_dir_conf;
/* optional function - look it up once in post_config */ static ap_dbd_t *(*session_dbd_acquire_fn) (request_rec *) = NULL; staticvoid (*session_dbd_prepare_fn) (server_rec *, constchar *, constchar *) = NULL;
/** * Initialise the database. * * If the mod_dbd module is missing, this method will return APR_EGENERAL.
*/ static apr_status_t dbd_init(request_rec *r, constchar *query, ap_dbd_t **dbdp,
apr_dbd_prepared_t **statementp)
{
ap_dbd_t *dbd;
apr_dbd_prepared_t *statement;
if (!session_dbd_prepare_fn || !session_dbd_acquire_fn) {
session_dbd_prepare_fn = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_prepare);
session_dbd_acquire_fn = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_acquire); if (!session_dbd_prepare_fn || !session_dbd_acquire_fn) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01850) "You must load mod_dbd to enable AuthDBD functions"); return APR_EGENERAL;
}
}
dbd = session_dbd_acquire_fn(r); if (!dbd) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01851) "failed to acquire database connection"); return APR_EGENERAL;
}
statement = apr_hash_get(dbd->prepared, query, APR_HASH_KEY_STRING); if (!statement) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01852) "failed to find the prepared statement called '%s'", query); return APR_EGENERAL;
}
*dbdp = dbd;
*statementp = statement;
return APR_SUCCESS;
}
/** * Load the session by the key specified. * * The session value is allocated using the passed apr_pool_t.
*/ static apr_status_t dbd_load(apr_pool_t *p, request_rec * r, constchar *key, constchar **val)
{
if (conf->selectlabel == NULL) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01853) "no SessionDBDselectlabel has been specified"); return APR_EGENERAL;
}
rv = dbd_init(r, conf->selectlabel, &dbd, &statement); if (rv) { return rv;
}
rv = apr_dbd_pvbselect(dbd->driver, r->pool, dbd->handle, &res, statement,
0, key, &expiry, NULL); if (rv) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01854) "query execution error saving session '%s' " "in database using query '%s': %s", key, conf->selectlabel,
apr_dbd_error(dbd->driver, dbd->handle, rv)); return APR_EGENERAL;
} for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1);
rv != -1;
rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) { if (rv != 0) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01855) "error retrieving results while saving '%s' " "in database using query '%s': %s", key, conf->selectlabel,
apr_dbd_error(dbd->driver, dbd->handle, rv)); return APR_EGENERAL;
} if (*val == NULL) {
*val = apr_pstrdup(p, apr_dbd_get_entry(dbd->driver, row, 0));
} /* we can't break out here or row won't get cleaned up */
}
return APR_SUCCESS;
}
/** * Load the session by firing off a dbd query. * * If the session is anonymous, the session key will be extracted from * the cookie specified. Failing that, the session key will be extracted * from the GET parameters. * * If the session is keyed by the username, the session will be extracted * by that. * * If no session is found, an empty session will be created. * * On success, this returns OK.
*/ static apr_status_t session_dbd_load(request_rec * r, session_rec ** z)
{
if (conf->updatelabel == NULL) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01856) "no SessionDBDupdatelabel has been specified"); return APR_EGENERAL;
}
/* * if some rows were updated it means a session existed and was updated, * so we are done.
*/ if (rows != 0) { return APR_SUCCESS;
}
}
if (conf->insertlabel == NULL) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01858) "no SessionDBDinsertlabel has been specified"); return APR_EGENERAL;
}
/* * if some rows were inserted it means a session was inserted, so we are * done.
*/ if (rows != 0) { return APR_SUCCESS;
}
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01860) "the session insert query did not cause any rows to be added " "to the database for session '%s', session not inserted", newkey);
return APR_EGENERAL;
}
/** * Remove the session by the key specified.
*/ static apr_status_t dbd_remove(request_rec * r, constchar *key)
{
apr_status_t rv;
ap_dbd_t *dbd;
apr_dbd_prepared_t *statement; int rows = 0;
if (conf->deletelabel == NULL) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01862) "no SessionDBDdeletelabel has been specified"); return APR_EGENERAL;
}
rv = dbd_init(r, conf->deletelabel, &dbd, &statement); if (rv != APR_SUCCESS) { /* No need to do additional error logging here, it has already
been done in dbd_init if needed */ return rv;
}
/** * Clean out expired sessions. * * TODO: We need to figure out a way to clean out expired sessions from the database. * The monitor hook doesn't help us that much, as we have no handle into the * server, and so we need to come up with a way to do this safely.
*/ static apr_status_t dbd_clean(apr_pool_t *p, server_rec *s)
{
return APR_ENOTIMPL;
}
/** * Save the session by firing off a dbd query. * * If the session is anonymous, save the session and write a cookie * containing the uuid. * * If the session is keyed to the username, save the session using * the username as a key. * * On success, this method will return APR_SUCCESS. * * @param r The request pointer. * @param z A pointer to where the session will be written.
*/ static apr_status_t session_dbd_save(request_rec * r, session_rec * z)
{
apr_status_t ret = APR_SUCCESS;
session_dbd_dir_conf *conf = ap_get_module_config(r->per_dir_config,
&session_dbd_module);
/* support anonymous sessions */ if (conf->name_set || conf->name2_set) { char *oldkey = NULL, *newkey = NULL;
/* if the session is new or changed, make a new session ID */ if (z->uuid) {
oldkey = apr_pcalloc(r->pool, APR_UUID_FORMATTED_LENGTH + 1);
apr_uuid_format(oldkey, z->uuid);
} if (z->dirty || !oldkey) {
z->uuid = apr_pcalloc(z->pool, sizeof(apr_uuid_t));
apr_uuid_get(z->uuid);
newkey = apr_pcalloc(r->pool, APR_UUID_FORMATTED_LENGTH + 1);
apr_uuid_format(newkey, z->uuid);
} else {
newkey = oldkey;
}
/* save the session with the uuid as key */ if (z->encoded && z->encoded[0]) {
ret = dbd_save(r, oldkey, newkey, z->encoded, z->expiry);
} else {
ret = dbd_remove(r, oldkey);
} if (ret != APR_SUCCESS) { return ret;
}
/* don't cache pages with a session */
apr_table_addn(r->headers_out, "Cache-Control", "no-cache, private");
if (r->user) {
ret = dbd_save(r, r->user, r->user, z->encoded, z->expiry); if (ret != APR_SUCCESS) { return ret;
} return OK;
} else {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01865) "peruser sessions can only be saved if a user is logged in, " "session not saved: %s", r->uri);
}
}
return DECLINED;
}
/** * This function performs housekeeping on the database, deleting expired * sessions.
*/ staticint session_dbd_monitor(apr_pool_t *p, server_rec *s)
{ /* TODO handle housekeeping */
dbd_clean(p, s); return OK;
}
/** * Sanity check a given string that it exists, is not empty, * and does not contain special characters.
*/ staticconstchar *check_string(cmd_parms * cmd, constchar *string)
{ if (APR_SUCCESS != ap_cookie_check_string(string)) { return apr_pstrcat(cmd->pool, cmd->directive->directive, " cannot contain '=', ';' or '&'.",
NULL);
} return NULL;
}
staticconst command_rec session_dbd_cmds[] =
{
AP_INIT_TAKE1("SessionDBDSelectLabel", ap_set_string_slot,
(void *) APR_OFFSETOF(session_dbd_dir_conf, selectlabel), RSRC_CONF|OR_AUTHCFG, "Query label used to select a new session"),
AP_INIT_TAKE1("SessionDBDInsertLabel", ap_set_string_slot,
(void *) APR_OFFSETOF(session_dbd_dir_conf, insertlabel), RSRC_CONF|OR_AUTHCFG, "Query label used to insert a new session"),
AP_INIT_TAKE1("SessionDBDUpdateLabel", ap_set_string_slot,
(void *) APR_OFFSETOF(session_dbd_dir_conf, updatelabel), RSRC_CONF|OR_AUTHCFG, "Query label used to update an existing session"),
AP_INIT_TAKE1("SessionDBDDeleteLabel", ap_set_string_slot,
(void *) APR_OFFSETOF(session_dbd_dir_conf, deletelabel), RSRC_CONF|OR_AUTHCFG, "Query label used to delete an existing session"),
AP_INIT_FLAG("SessionDBDPerUser", set_dbd_peruser, NULL, RSRC_CONF|OR_AUTHCFG, "Save the session per user"),
AP_INIT_FLAG("SessionDBDCookieRemove", set_dbd_cookie_remove, NULL, RSRC_CONF|OR_AUTHCFG, "Remove the session cookie after session load. On by default."),
AP_INIT_RAW_ARGS("SessionDBDCookieName", set_cookie_name, NULL, RSRC_CONF|OR_AUTHCFG, "The name of the RFC2109 cookie carrying the session key"),
AP_INIT_RAW_ARGS("SessionDBDCookieName2", set_cookie_name2, NULL, RSRC_CONF|OR_AUTHCFG, "The name of the RFC2965 cookie carrying the session key"),
{NULL}
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.