/* 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.
*/
/** * Should the session be included within this URL. * * This function tests whether a session is valid for this URL. It uses the * include and exclude arrays to determine whether they should be included.
*/ staticint session_included(request_rec * r, session_dir_conf * conf)
{
constchar **includes = (constchar **) conf->includes->elts; constchar **excludes = (constchar **) conf->excludes->elts; int included = 1; /* defaults to included */ int i;
if (conf->includes->nelts) {
included = 0; for (i = 0; !included && i < conf->includes->nelts; i++) { constchar *include = includes[i]; if (strncmp(r->uri, include, strlen(include)) == 0) {
included = 1;
}
}
}
if (conf->excludes->nelts) { for (i = 0; included && i < conf->excludes->nelts; i++) { constchar *exclude = excludes[i]; if (strncmp(r->uri, exclude, strlen(exclude)) == 0) {
included = 0;
}
}
}
return included;
}
/** * Load the session. * * If the session doesn't exist, a blank one will be created. * * @param r The request * @param z A pointer to where the session will be written.
*/ static apr_status_t ap_session_load(request_rec * r, session_rec ** z)
{
/* is the session enabled? */ if (!dconf || !dconf->enabled) { return APR_SUCCESS;
}
/* should the session be loaded at all? */ if (!session_included(r, dconf)) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01814) "excluded by configuration for: %s", r->uri); return APR_SUCCESS;
}
/* load the session from the session hook */
rv = ap_run_session_load(r, &zz); if (DECLINED == rv) {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01815) "session is enabled but no session modules have been configured, " "session not loaded: %s", r->uri); return APR_EGENERAL;
} elseif (OK != rv) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01816) "error while loading the session, " "session not loaded: %s", r->uri); return rv;
}
/* found a session that hasn't expired? */
now = apr_time_now();
if (zz) { /* load the session attributes */
rv = ap_run_session_decode(r, zz);
/* having a session we cannot decode is just as good as having
none at all */ if (OK != rv) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01817) "error while decoding the session, " "session not loaded: %s", r->uri);
zz = NULL;
}
/* invalidate session if session is expired */ if (zz && zz->expiry && zz->expiry < now) {
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "session is expired");
zz = NULL;
}
}
/* no luck, create a blank session */ if (!zz) {
zz = (session_rec *) apr_pcalloc(r->pool, sizeof(session_rec));
zz->pool = r->pool;
zz->entries = apr_table_make(zz->pool, 10);
}
/* make sure the expiry and maxage are set, if present */ if (dconf->maxage) { if (!zz->expiry) {
zz->expiry = now + dconf->maxage * APR_USEC_PER_SEC;
}
zz->maxage = dconf->maxage;
}
*z = zz;
return APR_SUCCESS;
}
/** * Save the session. * * In most implementations the session is only saved if the dirty flag is * true. This prevents the session being saved unnecessarily. * * @param r The request * @param z A pointer to where the session will be written.
*/ static apr_status_t ap_session_save(request_rec * r, session_rec * z)
{ if (z) {
apr_time_t now = apr_time_now();
apr_time_t initialExpiry = z->expiry; int rv = 0;
/* sanity checks, should we try save at all? */ if (z->written) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01818) "attempt made to save the session twice, " "session not saved: %s", r->uri); return APR_EGENERAL;
} if (z->expiry && z->expiry < now) {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01819) "attempt made to save a session when the session had already expired, " "session not saved: %s", r->uri); return APR_EGENERAL;
}
/* reset the expiry back to maxage, if the expiry is present */ if (dconf->maxage) {
z->expiry = now + dconf->maxage * APR_USEC_PER_SEC;
z->maxage = dconf->maxage;
}
/* reset the expiry before saving if present */ if (z->dirty && z->maxage) {
z->expiry = now + z->maxage * APR_USEC_PER_SEC;
}
/* don't save if the only change is the expiry by a small amount */ if (!z->dirty && dconf->expiry_update_time
&& (z->expiry - initialExpiry < dconf->expiry_update_time)) { return APR_SUCCESS;
}
/* also don't save sessions that didn't change at all */ if (!z->dirty && !z->maxage) { return APR_SUCCESS;
}
/* encode the session */
rv = ap_run_session_encode(r, z); if (OK != rv) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01820) "error while encoding the session, " "session not saved: %s", r->uri); return rv;
}
/* try the save */
rv = ap_run_session_save(r, z); if (DECLINED == rv) {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01821) "session is enabled but no session modules have been configured, " "session not saved: %s", r->uri); return APR_EGENERAL;
} elseif (OK != rv) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01822) "error while saving the session, " "session not saved: %s", r->uri); return rv;
} else {
z->written = 1;
}
}
return APR_SUCCESS;
}
/** * Get a particular value from the session. * @param r The current request. * @param z The current session. If this value is NULL, the session will be * looked up in the request, created if necessary, and saved to the request * notes. * @param key The key to get. * @param value The buffer to write the value to.
*/ static apr_status_t ap_session_get(request_rec * r, session_rec * z, constchar *key, constchar **value)
{ if (!z) {
apr_status_t rv;
rv = ap_session_load(r, &z); if (APR_SUCCESS != rv) { return rv;
}
} if (z && z->entries) {
*value = apr_table_get(z->entries, key);
}
return OK;
}
/** * Set a particular value to the session. * * Using this method ensures that the dirty flag is set correctly, so that * the session can be saved efficiently. * @param r The current request. * @param z The current session. If this value is NULL, the session will be * looked up in the request, created if necessary, and saved to the request * notes. * @param key The key to set. The existing key value will be replaced. * @param value The value to set.
*/ static apr_status_t ap_session_set(request_rec * r, session_rec * z, constchar *key, constchar *value)
{ if (!z) {
apr_status_t rv;
rv = ap_session_load(r, &z); if (APR_SUCCESS != rv) { return rv;
}
} if (z) { if (value) {
apr_table_set(z->entries, key, value);
} else {
apr_table_unset(z->entries, key);
}
z->dirty = 1;
} return APR_SUCCESS;
}
/** * Default identity encoding for the session. * * By default, the name value pairs in the session are URLEncoded, separated * by equals, and then in turn separated by ampersand, in the format of an * html form. * * This was chosen to make it easy for external code to unpack a session, * should there be a need to do so. * * @param r The request pointer. * @param z A pointer to where the session will be written.
*/ static apr_status_t session_identity_encode(request_rec * r, session_rec * z)
{ char *buffer = NULL;
apr_size_t length = 0;
/** * Default identity decoding for the session. * * By default, the name value pairs in the session are URLEncoded, separated * by equals, and then in turn separated by ampersand, in the format of an * html form. * * This was chosen to make it easy for external code to unpack a session, * should there be a need to do so. * * This function reverses that process, and populates the session table. * * Name / value pairs that are not encoded properly are ignored. * * @param r The request pointer. * @param z A pointer to where the session will be written.
*/ static apr_status_t session_identity_decode(request_rec * r, session_rec * z)
{
/** * Ensure any changes to the session are committed. * * This is done in an output filter so that our options for where to * store the session can include storing the session within a cookie: * As an HTTP header, the cookie must be set before the output is * written, but after the handler is run. * * NOTE: It is possible for internal redirects to cause more than one * request to be present, and each request might have a session * defined. We need to go through each session in turn, and save each * one. * * The same session might appear in more than one request. The first * attempt to save the session will be called
*/ static apr_status_t session_output_filter(ap_filter_t * f,
apr_bucket_brigade * in)
{
/* save all the sessions in all the requests */
request_rec *r = f->r->main; if (!r) {
r = f->r;
} while (r) {
session_rec *z = NULL;
session_dir_conf *conf = ap_get_module_config(r->per_dir_config,
&session_module);
/* load the session, or create one if necessary */ /* when unset or on error, z will be NULL */
ap_session_load(r, &z); if (!z || z->written) {
r = r->next; continue;
}
/* if a header was specified, insert the new values from the header */ if (conf->header_set) { constchar *override = apr_table_get(r->err_headers_out, conf->header); if (!override) {
override = apr_table_get(r->headers_out, conf->header);
} if (override) {
apr_table_unset(r->err_headers_out, conf->header);
apr_table_unset(r->headers_out, conf->header);
z->encoded = override;
z->dirty = 1;
session_identity_decode(r, z);
}
}
/* save away the session, and we're done */ /* when unset or on error, we've complained to the log */
ap_session_save(r, z);
r = r->next;
}
/* remove ourselves from the filter chain */
ap_remove_output_filter(f);
/* send the data up the stack */ return ap_pass_brigade(f->next, in);
/** * Fixups hook. * * Load the session within a fixup - this ensures that the session is * properly loaded prior to the handler being called. * * The fixup is also responsible for injecting the session into the CGI * environment, should the admin have configured it so. * * @param r The request
*/ staticint session_fixups(request_rec * r)
{
session_dir_conf *conf = ap_get_module_config(r->per_dir_config,
&session_module);
session_rec *z = NULL;
/* if an error occurs or no session has been configured, we ignore * the broken session and allow it to be recreated from scratch on save * if necessary.
*/
ap_session_load(r, &z);
if (conf->env) { if (z) {
session_identity_encode(r, z); if (z->encoded) {
apr_table_set(r->subprocess_env, HTTP_SESSION, z->encoded);
z->encoded = NULL;
}
}
apr_table_unset(r->headers_in, "Session");
}
conf->expiry_update_time = atoi(arg); if (conf->expiry_update_time < 0) { return"SessionExpiryUpdateInterval must be zero (disable) or a positive value";
}
conf->expiry_update_time = apr_time_from_sec(conf->expiry_update_time);
conf->expiry_update_set = 1;
return NULL;
}
staticconst command_rec session_cmds[] =
{
AP_INIT_FLAG("Session", set_session_enable, NULL, RSRC_CONF|OR_AUTHCFG, "on if a session should be maintained for these URLs"),
AP_INIT_TAKE1("SessionMaxAge", set_session_maxage, NULL, RSRC_CONF|OR_AUTHCFG, "length of time for which a session should be valid. Zero to disable"),
AP_INIT_TAKE1("SessionHeader", set_session_header, NULL, RSRC_CONF|OR_AUTHCFG, "output header, if present, whose contents will be injected into the session."),
AP_INIT_FLAG("SessionEnv", set_session_env, NULL, RSRC_CONF|OR_AUTHCFG, "on if a session should be written to the CGI environment. Defaults to off"),
AP_INIT_TAKE1("SessionInclude", add_session_include, NULL, RSRC_CONF|OR_AUTHCFG, "URL prefixes to include in the session. Defaults to all URLs"),
AP_INIT_TAKE1("SessionExclude", add_session_exclude, NULL, RSRC_CONF|OR_AUTHCFG, "URL prefixes to exclude from the session. Defaults to no URLs"),
AP_INIT_TAKE1("SessionExpiryUpdateInterval", set_session_expiry_update, NULL, RSRC_CONF|OR_AUTHCFG, "time interval for which a session's expiry time may change " "without having to be rewritten. Zero to disable"),
{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.