You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by rp...@apache.org on 2008/04/08 15:49:52 UTC
svn commit: r645923 - in /httpd/httpd/trunk/modules/session: Makefile.in
config.m4 mod_session.c mod_session.h mod_session_cookie.c
mod_session_crypto.c mod_session_dbd.c
Author: rpluem
Date: Tue Apr 8 06:49:49 2008
New Revision: 645923
URL: http://svn.apache.org/viewvc?rev=645923&view=rev
Log:
* Fix eol-style property.
Changes to mod_session.c only fix line endings again. No functional
changes.
Modified:
httpd/httpd/trunk/modules/session/Makefile.in (props changed)
httpd/httpd/trunk/modules/session/config.m4 (props changed)
httpd/httpd/trunk/modules/session/mod_session.c (contents, props changed)
httpd/httpd/trunk/modules/session/mod_session.h (props changed)
httpd/httpd/trunk/modules/session/mod_session_cookie.c (props changed)
httpd/httpd/trunk/modules/session/mod_session_crypto.c (props changed)
httpd/httpd/trunk/modules/session/mod_session_dbd.c (props changed)
Propchange: httpd/httpd/trunk/modules/session/Makefile.in
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpd/httpd/trunk/modules/session/config.m4
------------------------------------------------------------------------------
svn:eol-style = native
Modified: httpd/httpd/trunk/modules/session/mod_session.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/session/mod_session.c?rev=645923&r1=645922&r2=645923&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/session/mod_session.c (original)
+++ httpd/httpd/trunk/modules/session/mod_session.c Tue Apr 8 06:49:49 2008
@@ -1,620 +1,620 @@
-/* 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.
- */
-
-#include "mod_session.h"
-#include "apr_lib.h"
-#include "apr_strings.h"
-#include "util_filter.h"
-#include "http_log.h"
-#include "http_request.h"
-#include "http_protocol.h"
-
-#define SESSION_PREFIX "mod_session: "
-#define SESSION_EXPIRY "expiry"
-#define HTTP_SESSION "HTTP_SESSION"
-
-APR_HOOK_STRUCT(
- APR_HOOK_LINK(session_load)
- APR_HOOK_LINK(session_save)
- APR_HOOK_LINK(session_encode)
- APR_HOOK_LINK(session_decode)
-)
-AP_IMPLEMENT_HOOK_RUN_FIRST(int, session_load,
- (request_rec * r, session_rec ** z), (r, z), DECLINED)
-AP_IMPLEMENT_HOOK_RUN_FIRST(int, session_save,
- (request_rec * r, session_rec * z), (r, z), DECLINED)
-AP_IMPLEMENT_HOOK_RUN_ALL(int, session_encode,
- (request_rec * r, session_rec * z), (r, z), OK, DECLINED)
-AP_IMPLEMENT_HOOK_RUN_ALL(int, session_decode,
- (request_rec * r, session_rec * z), (r, z), OK, DECLINED)
-/**
- * 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.
- */
- static int session_included(request_rec * r, session_dir_conf * conf)
-{
-
- const char **includes = (const char **) conf->includes->elts;
- const char **excludes = (const char **) 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++) {
- const char *include = includes[i];
- if (strncmp(r->parsed_uri.path, include, strlen(include))) {
- included = 1;
- }
- }
- }
-
- if (conf->excludes->nelts) {
- for (i = 0; included && i < conf->includes->nelts; i++) {
- const char *exclude = excludes[i];
- if (strncmp(r->parsed_uri.path, exclude, strlen(exclude))) {
- included = 0;
- }
- }
- }
-
- return included;
-}
-
-/**
- * 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.
- */
-AP_DECLARE(void) ap_session_get(request_rec * r, session_rec * z, const char *key, const char **value)
-{
- if (!z) {
- ap_session_load(r, &z);
- }
- if (z) {
- *value = apr_table_get(z->entries, key);
- }
-}
-
-/**
- * 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.
- */
-AP_DECLARE(void) ap_session_set(request_rec * r, session_rec * z,
- const char *key, const char *value)
-{
- if (!z) {
- ap_session_load(r, &z);
- }
- if (z) {
- if (value) {
- apr_table_set(z->entries, key, value);
- }
- else {
- apr_table_unset(z->entries, key);
- }
- z->dirty = 1;
- }
-}
-
-/**
- * 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.
- */
-AP_DECLARE(int) ap_session_load(request_rec * r, session_rec ** z)
-{
-
- session_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
- &session_module);
- apr_time_t now;
- session_rec *zz = NULL;
- int rv = 0;
-
- /* is the session enabled? */
- if (!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, SESSION_PREFIX
- "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, SESSION_PREFIX
- "session is enabled but no session modules have been configured, "
- "session not loaded: %s", r->uri);
- return APR_EGENERAL;
- }
- else if (OK != rv) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, SESSION_PREFIX
- "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 || (zz->expiry && zz->expiry < now)) {
-
- /* no luck, create a blank session */
- zz = (session_rec *) apr_pcalloc(r->pool, sizeof(session_rec));
- zz->pool = r->pool;
- zz->entries = apr_table_make(zz->pool, 10);
- zz->uuid = (apr_uuid_t *) apr_pcalloc(zz->pool, sizeof(apr_uuid_t));
- apr_uuid_get(zz->uuid);
-
- }
- else {
- rv = ap_run_session_decode(r, zz);
- if (OK != rv) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, SESSION_PREFIX
- "error while decoding the session, "
- "session not loaded: %s", r->uri);
- return rv;
- }
- }
-
- /* make sure the expiry is set, if present */
- if (!zz->expiry && dconf->maxage) {
- 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.
- */
-AP_DECLARE(int) ap_session_save(request_rec * r, session_rec * z)
-{
- if (z) {
- apr_time_t now = apr_time_now();
- int rv = 0;
-
- /* sanity checks, should we try save at all? */
- if (z->written) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, SESSION_PREFIX
- "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, SESSION_PREFIX
- "attempt made to save a session when the session had already expired, "
- "session not saved: %s", r->uri);
- return APR_EGENERAL;
- }
-
- /* encode the session */
- rv = ap_run_session_encode(r, z);
- if (OK != rv) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, SESSION_PREFIX
- "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, SESSION_PREFIX
- "session is enabled but no session modules have been configured, "
- "session not saved: %s", r->uri);
- return APR_EGENERAL;
- }
- else if (OK != rv) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, SESSION_PREFIX
- "error while saving the session, "
- "session not saved: %s", r->uri);
- return rv;
- }
- else {
- z->written = 1;
- }
- }
-
- return APR_SUCCESS;
-
-}
-
-static int identity_count(int *count, const char *key, const char *val)
-{
- *count += strlen(key) * 3 + strlen(val) * 3 + 1;
- return 1;
-}
-
-static int identity_concat(char *buffer, const char *key, const char *val)
-{
- char *slider = buffer;
- int length = strlen(slider);
- slider += length;
- if (length) {
- *slider = '&';
- slider++;
- }
- ap_escape_path_segment_buffer(slider, key);
- slider += strlen(slider);
- *slider = '=';
- slider++;
- ap_escape_path_segment_buffer(slider, val);
- return 1;
-}
-
-/**
- * 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.
- */
-AP_DECLARE(int) ap_session_identity_encode(request_rec * r, session_rec * z)
-{
-
- char *buffer = NULL;
- int length = 0;
- if (z->expiry) {
- char *expiry = apr_psprintf(r->pool, "%" APR_INT64_T_FMT, z->expiry);
- apr_table_set(z->entries, SESSION_EXPIRY, expiry);
- }
- apr_table_do((int (*) (void *, const char *, const char *))
- identity_count, &length, z->entries, NULL);;
- buffer = apr_pcalloc(r->pool, length + 1);
- apr_table_do((int (*) (void *, const char *, const char *))
- identity_concat, buffer, z->entries, NULL);
- z->encoded = buffer;
- return OK;
-
-}
-
-/**
- * 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.
- */
-AP_DECLARE(int) ap_session_identity_decode(request_rec * r, session_rec * z)
-{
-
- char *last = NULL;
- char *encoded, *pair;
- const char *sep = "&";
-
- /* sanity check - anything to decode? */
- if (!z->encoded) {
- return OK;
- }
-
- /* decode what we have */
- encoded = apr_pstrcat(r->pool, z->encoded, NULL);
- pair = apr_strtok(encoded, sep, &last);
- while (pair && pair[0]) {
- char *plast = NULL;
- const char *psep = "=";
- char *key = apr_strtok(pair, psep, &plast);
- char *val = apr_strtok(NULL, psep, &plast);
- if (key && *key) {
- if (!val || !*val) {
- apr_table_unset(z->entries, key);
- }
- if (!ap_unescape_all(key) && !ap_unescape_all(val)) {
- if (!strcmp(SESSION_EXPIRY, key)) {
- z->expiry = (apr_time_t) apr_atoi64(val);
- }
- else {
- apr_table_set(z->entries, key, val);
- }
- }
- }
- pair = apr_strtok(NULL, sep, &last);
- }
- z->encoded = NULL;
- return OK;
-
-}
-
-/**
- * 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 ap_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 */
- 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) {
- const char *override = apr_table_get(r->err_headers_out, conf->header);
- if (!override) {
- override = apr_table_get(r->headers_out, conf->header);
- }
- if (override) {
- z->encoded = override;
- ap_session_identity_decode(r, z);
- }
- }
-
- /* save away the session, and we're done */
- 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);
-
-}
-
-/**
- * Insert the output filter.
- */
-static void ap_session_insert_output_filter(request_rec * r)
-{
- ap_add_output_filter("MOD_SESSION_OUT", NULL, r, r->connection);
-}
-
-/**
- * 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
- */
-AP_DECLARE(int) ap_session_fixups(request_rec * r)
-{
- session_dir_conf *conf = ap_get_module_config(r->per_dir_config,
- &session_module);
-
- session_rec *z = NULL;
- ap_session_load(r, &z);
-
- if (conf->env) {
- ap_session_identity_encode(r, z);
- if (z->encoded) {
- apr_table_set(r->subprocess_env, HTTP_SESSION, z->encoded);
- z->encoded = NULL;
- }
- }
-
- return OK;
-
-}
-
-
-static void *create_session_dir_config(apr_pool_t * p, char *dummy)
-{
- session_dir_conf *new =
- (session_dir_conf *) apr_pcalloc(p, sizeof(session_dir_conf));
-
- new->includes = apr_array_make(p, 10, sizeof(const char **));
- new->excludes = apr_array_make(p, 10, sizeof(const char **));
-
- return (void *) new;
-}
-
-static void *merge_session_dir_config(apr_pool_t * p, void *basev, void *addv)
-{
- session_dir_conf *new = (session_dir_conf *) apr_pcalloc(p, sizeof(session_dir_conf));
- session_dir_conf *add = (session_dir_conf *) addv;
- session_dir_conf *base = (session_dir_conf *) basev;
-
- new->enabled = (add->enabled_set == 0) ? base->enabled : add->enabled;
- new->enabled_set = add->enabled_set || base->enabled_set;
- new->maxage = (add->maxage_set == 0) ? base->maxage : add->maxage;
- new->maxage_set = add->maxage_set || base->maxage_set;
- new->header = (add->header_set == 0) ? base->header : add->header;
- new->header_set = add->header_set || base->header_set;
- new->env = (add->env_set == 0) ? base->env : add->env;
- new->env_set = add->env_set || base->env_set;
- new->includes = apr_array_append(p, base->includes, add->includes);
- new->excludes = apr_array_append(p, base->excludes, add->excludes);
-
- return new;
-}
-
-
-static const char *
- set_session_enable(cmd_parms * parms, void *dconf, int flag)
-{
- session_dir_conf *conf = dconf;
-
- conf->enabled = flag;
- conf->enabled_set = 1;
-
- return NULL;
-}
-
-static const char *
- set_session_maxage(cmd_parms * parms, void *dconf, const char *arg)
-{
- session_dir_conf *conf = dconf;
-
- conf->maxage = atol(arg);
- conf->maxage_set = 1;
-
- return NULL;
-}
-
-static const char *
- set_session_header(cmd_parms * parms, void *dconf, const char *arg)
-{
- session_dir_conf *conf = dconf;
-
- conf->header = arg;
- conf->header_set = 1;
-
- return NULL;
-}
-
-static const char *
- set_session_env(cmd_parms * parms, void *dconf, int flag)
-{
- session_dir_conf *conf = dconf;
-
- conf->env = flag;
- conf->env_set = 1;
-
- return NULL;
-}
-
-static const char *add_session_include(cmd_parms * cmd, void *dconf, const char *f)
-{
- session_dir_conf *conf = dconf;
-
- const char **new = apr_array_push(conf->includes);
- *new = f;
-
- return NULL;
-}
-
-static const char *add_session_exclude(cmd_parms * cmd, void *dconf, const char *f)
-{
- session_dir_conf *conf = dconf;
-
- const char **new = apr_array_push(conf->excludes);
- *new = f;
-
- return NULL;
-}
-
-
-static const command_rec session_cmds[] =
-{
- AP_INIT_FLAG("Session", set_session_enable, NULL, OR_AUTHCFG,
- "on if a session should be maintained for these URLs"),
- AP_INIT_TAKE1("SessionMaxAge", set_session_maxage, NULL, OR_AUTHCFG,
- "length of time for which a session should be valid. Zero to disable"),
- AP_INIT_TAKE1("SessionHeader", set_session_header, NULL, OR_AUTHCFG,
- "output header, if present, whose contents will be injected into the session."),
- AP_INIT_FLAG("SessionEnv", set_session_env, NULL, OR_AUTHCFG,
- "on if a session should be written to the CGI environment. Defaults to off"),
- AP_INIT_TAKE1("SessionInclude", add_session_include, NULL, OR_AUTHCFG,
- "URL prefixes to include in the session. Defaults to all URLs"),
- AP_INIT_TAKE1("SessionExclude", add_session_exclude, NULL, OR_AUTHCFG,
- "URL prefixes to exclude from the session. Defaults to no URLs"),
- {NULL}
-};
-
-static void register_hooks(apr_pool_t * p)
-{
- ap_register_output_filter("MOD_SESSION_OUT", ap_session_output_filter,
- NULL, AP_FTYPE_CONTENT_SET);
- ap_hook_insert_filter(ap_session_insert_output_filter, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_insert_error_filter(ap_session_insert_output_filter,
- NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_fixups(ap_session_fixups, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_session_encode(ap_session_identity_encode, NULL, NULL, APR_HOOK_REALLY_FIRST);
- ap_hook_session_decode(ap_session_identity_decode, NULL, NULL, APR_HOOK_REALLY_LAST);
- APR_REGISTER_OPTIONAL_FN(ap_session_get);
- APR_REGISTER_OPTIONAL_FN(ap_session_set);
- APR_REGISTER_OPTIONAL_FN(ap_session_load);
- APR_REGISTER_OPTIONAL_FN(ap_session_save);
-}
-
-module AP_MODULE_DECLARE_DATA session_module =
-{
- STANDARD20_MODULE_STUFF,
- create_session_dir_config, /* dir config creater */
- merge_session_dir_config, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server config */
- session_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
+/* 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.
+ */
+
+#include "mod_session.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "util_filter.h"
+#include "http_log.h"
+#include "http_request.h"
+#include "http_protocol.h"
+
+#define SESSION_PREFIX "mod_session: "
+#define SESSION_EXPIRY "expiry"
+#define HTTP_SESSION "HTTP_SESSION"
+
+APR_HOOK_STRUCT(
+ APR_HOOK_LINK(session_load)
+ APR_HOOK_LINK(session_save)
+ APR_HOOK_LINK(session_encode)
+ APR_HOOK_LINK(session_decode)
+)
+AP_IMPLEMENT_HOOK_RUN_FIRST(int, session_load,
+ (request_rec * r, session_rec ** z), (r, z), DECLINED)
+AP_IMPLEMENT_HOOK_RUN_FIRST(int, session_save,
+ (request_rec * r, session_rec * z), (r, z), DECLINED)
+AP_IMPLEMENT_HOOK_RUN_ALL(int, session_encode,
+ (request_rec * r, session_rec * z), (r, z), OK, DECLINED)
+AP_IMPLEMENT_HOOK_RUN_ALL(int, session_decode,
+ (request_rec * r, session_rec * z), (r, z), OK, DECLINED)
+/**
+ * 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.
+ */
+ static int session_included(request_rec * r, session_dir_conf * conf)
+{
+
+ const char **includes = (const char **) conf->includes->elts;
+ const char **excludes = (const char **) 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++) {
+ const char *include = includes[i];
+ if (strncmp(r->parsed_uri.path, include, strlen(include))) {
+ included = 1;
+ }
+ }
+ }
+
+ if (conf->excludes->nelts) {
+ for (i = 0; included && i < conf->includes->nelts; i++) {
+ const char *exclude = excludes[i];
+ if (strncmp(r->parsed_uri.path, exclude, strlen(exclude))) {
+ included = 0;
+ }
+ }
+ }
+
+ return included;
+}
+
+/**
+ * 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.
+ */
+AP_DECLARE(void) ap_session_get(request_rec * r, session_rec * z, const char *key, const char **value)
+{
+ if (!z) {
+ ap_session_load(r, &z);
+ }
+ if (z) {
+ *value = apr_table_get(z->entries, key);
+ }
+}
+
+/**
+ * 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.
+ */
+AP_DECLARE(void) ap_session_set(request_rec * r, session_rec * z,
+ const char *key, const char *value)
+{
+ if (!z) {
+ ap_session_load(r, &z);
+ }
+ if (z) {
+ if (value) {
+ apr_table_set(z->entries, key, value);
+ }
+ else {
+ apr_table_unset(z->entries, key);
+ }
+ z->dirty = 1;
+ }
+}
+
+/**
+ * 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.
+ */
+AP_DECLARE(int) ap_session_load(request_rec * r, session_rec ** z)
+{
+
+ session_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
+ &session_module);
+ apr_time_t now;
+ session_rec *zz = NULL;
+ int rv = 0;
+
+ /* is the session enabled? */
+ if (!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, SESSION_PREFIX
+ "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, SESSION_PREFIX
+ "session is enabled but no session modules have been configured, "
+ "session not loaded: %s", r->uri);
+ return APR_EGENERAL;
+ }
+ else if (OK != rv) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, SESSION_PREFIX
+ "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 || (zz->expiry && zz->expiry < now)) {
+
+ /* no luck, create a blank session */
+ zz = (session_rec *) apr_pcalloc(r->pool, sizeof(session_rec));
+ zz->pool = r->pool;
+ zz->entries = apr_table_make(zz->pool, 10);
+ zz->uuid = (apr_uuid_t *) apr_pcalloc(zz->pool, sizeof(apr_uuid_t));
+ apr_uuid_get(zz->uuid);
+
+ }
+ else {
+ rv = ap_run_session_decode(r, zz);
+ if (OK != rv) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, SESSION_PREFIX
+ "error while decoding the session, "
+ "session not loaded: %s", r->uri);
+ return rv;
+ }
+ }
+
+ /* make sure the expiry is set, if present */
+ if (!zz->expiry && dconf->maxage) {
+ 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.
+ */
+AP_DECLARE(int) ap_session_save(request_rec * r, session_rec * z)
+{
+ if (z) {
+ apr_time_t now = apr_time_now();
+ int rv = 0;
+
+ /* sanity checks, should we try save at all? */
+ if (z->written) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, SESSION_PREFIX
+ "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, SESSION_PREFIX
+ "attempt made to save a session when the session had already expired, "
+ "session not saved: %s", r->uri);
+ return APR_EGENERAL;
+ }
+
+ /* encode the session */
+ rv = ap_run_session_encode(r, z);
+ if (OK != rv) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, SESSION_PREFIX
+ "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, SESSION_PREFIX
+ "session is enabled but no session modules have been configured, "
+ "session not saved: %s", r->uri);
+ return APR_EGENERAL;
+ }
+ else if (OK != rv) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, SESSION_PREFIX
+ "error while saving the session, "
+ "session not saved: %s", r->uri);
+ return rv;
+ }
+ else {
+ z->written = 1;
+ }
+ }
+
+ return APR_SUCCESS;
+
+}
+
+static int identity_count(int *count, const char *key, const char *val)
+{
+ *count += strlen(key) * 3 + strlen(val) * 3 + 1;
+ return 1;
+}
+
+static int identity_concat(char *buffer, const char *key, const char *val)
+{
+ char *slider = buffer;
+ int length = strlen(slider);
+ slider += length;
+ if (length) {
+ *slider = '&';
+ slider++;
+ }
+ ap_escape_path_segment_buffer(slider, key);
+ slider += strlen(slider);
+ *slider = '=';
+ slider++;
+ ap_escape_path_segment_buffer(slider, val);
+ return 1;
+}
+
+/**
+ * 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.
+ */
+AP_DECLARE(int) ap_session_identity_encode(request_rec * r, session_rec * z)
+{
+
+ char *buffer = NULL;
+ int length = 0;
+ if (z->expiry) {
+ char *expiry = apr_psprintf(r->pool, "%" APR_INT64_T_FMT, z->expiry);
+ apr_table_set(z->entries, SESSION_EXPIRY, expiry);
+ }
+ apr_table_do((int (*) (void *, const char *, const char *))
+ identity_count, &length, z->entries, NULL);;
+ buffer = apr_pcalloc(r->pool, length + 1);
+ apr_table_do((int (*) (void *, const char *, const char *))
+ identity_concat, buffer, z->entries, NULL);
+ z->encoded = buffer;
+ return OK;
+
+}
+
+/**
+ * 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.
+ */
+AP_DECLARE(int) ap_session_identity_decode(request_rec * r, session_rec * z)
+{
+
+ char *last = NULL;
+ char *encoded, *pair;
+ const char *sep = "&";
+
+ /* sanity check - anything to decode? */
+ if (!z->encoded) {
+ return OK;
+ }
+
+ /* decode what we have */
+ encoded = apr_pstrcat(r->pool, z->encoded, NULL);
+ pair = apr_strtok(encoded, sep, &last);
+ while (pair && pair[0]) {
+ char *plast = NULL;
+ const char *psep = "=";
+ char *key = apr_strtok(pair, psep, &plast);
+ char *val = apr_strtok(NULL, psep, &plast);
+ if (key && *key) {
+ if (!val || !*val) {
+ apr_table_unset(z->entries, key);
+ }
+ if (!ap_unescape_all(key) && !ap_unescape_all(val)) {
+ if (!strcmp(SESSION_EXPIRY, key)) {
+ z->expiry = (apr_time_t) apr_atoi64(val);
+ }
+ else {
+ apr_table_set(z->entries, key, val);
+ }
+ }
+ }
+ pair = apr_strtok(NULL, sep, &last);
+ }
+ z->encoded = NULL;
+ return OK;
+
+}
+
+/**
+ * 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 ap_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 */
+ 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) {
+ const char *override = apr_table_get(r->err_headers_out, conf->header);
+ if (!override) {
+ override = apr_table_get(r->headers_out, conf->header);
+ }
+ if (override) {
+ z->encoded = override;
+ ap_session_identity_decode(r, z);
+ }
+ }
+
+ /* save away the session, and we're done */
+ 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);
+
+}
+
+/**
+ * Insert the output filter.
+ */
+static void ap_session_insert_output_filter(request_rec * r)
+{
+ ap_add_output_filter("MOD_SESSION_OUT", NULL, r, r->connection);
+}
+
+/**
+ * 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
+ */
+AP_DECLARE(int) ap_session_fixups(request_rec * r)
+{
+ session_dir_conf *conf = ap_get_module_config(r->per_dir_config,
+ &session_module);
+
+ session_rec *z = NULL;
+ ap_session_load(r, &z);
+
+ if (conf->env) {
+ ap_session_identity_encode(r, z);
+ if (z->encoded) {
+ apr_table_set(r->subprocess_env, HTTP_SESSION, z->encoded);
+ z->encoded = NULL;
+ }
+ }
+
+ return OK;
+
+}
+
+
+static void *create_session_dir_config(apr_pool_t * p, char *dummy)
+{
+ session_dir_conf *new =
+ (session_dir_conf *) apr_pcalloc(p, sizeof(session_dir_conf));
+
+ new->includes = apr_array_make(p, 10, sizeof(const char **));
+ new->excludes = apr_array_make(p, 10, sizeof(const char **));
+
+ return (void *) new;
+}
+
+static void *merge_session_dir_config(apr_pool_t * p, void *basev, void *addv)
+{
+ session_dir_conf *new = (session_dir_conf *) apr_pcalloc(p, sizeof(session_dir_conf));
+ session_dir_conf *add = (session_dir_conf *) addv;
+ session_dir_conf *base = (session_dir_conf *) basev;
+
+ new->enabled = (add->enabled_set == 0) ? base->enabled : add->enabled;
+ new->enabled_set = add->enabled_set || base->enabled_set;
+ new->maxage = (add->maxage_set == 0) ? base->maxage : add->maxage;
+ new->maxage_set = add->maxage_set || base->maxage_set;
+ new->header = (add->header_set == 0) ? base->header : add->header;
+ new->header_set = add->header_set || base->header_set;
+ new->env = (add->env_set == 0) ? base->env : add->env;
+ new->env_set = add->env_set || base->env_set;
+ new->includes = apr_array_append(p, base->includes, add->includes);
+ new->excludes = apr_array_append(p, base->excludes, add->excludes);
+
+ return new;
+}
+
+
+static const char *
+ set_session_enable(cmd_parms * parms, void *dconf, int flag)
+{
+ session_dir_conf *conf = dconf;
+
+ conf->enabled = flag;
+ conf->enabled_set = 1;
+
+ return NULL;
+}
+
+static const char *
+ set_session_maxage(cmd_parms * parms, void *dconf, const char *arg)
+{
+ session_dir_conf *conf = dconf;
+
+ conf->maxage = atol(arg);
+ conf->maxage_set = 1;
+
+ return NULL;
+}
+
+static const char *
+ set_session_header(cmd_parms * parms, void *dconf, const char *arg)
+{
+ session_dir_conf *conf = dconf;
+
+ conf->header = arg;
+ conf->header_set = 1;
+
+ return NULL;
+}
+
+static const char *
+ set_session_env(cmd_parms * parms, void *dconf, int flag)
+{
+ session_dir_conf *conf = dconf;
+
+ conf->env = flag;
+ conf->env_set = 1;
+
+ return NULL;
+}
+
+static const char *add_session_include(cmd_parms * cmd, void *dconf, const char *f)
+{
+ session_dir_conf *conf = dconf;
+
+ const char **new = apr_array_push(conf->includes);
+ *new = f;
+
+ return NULL;
+}
+
+static const char *add_session_exclude(cmd_parms * cmd, void *dconf, const char *f)
+{
+ session_dir_conf *conf = dconf;
+
+ const char **new = apr_array_push(conf->excludes);
+ *new = f;
+
+ return NULL;
+}
+
+
+static const command_rec session_cmds[] =
+{
+ AP_INIT_FLAG("Session", set_session_enable, NULL, OR_AUTHCFG,
+ "on if a session should be maintained for these URLs"),
+ AP_INIT_TAKE1("SessionMaxAge", set_session_maxage, NULL, OR_AUTHCFG,
+ "length of time for which a session should be valid. Zero to disable"),
+ AP_INIT_TAKE1("SessionHeader", set_session_header, NULL, OR_AUTHCFG,
+ "output header, if present, whose contents will be injected into the session."),
+ AP_INIT_FLAG("SessionEnv", set_session_env, NULL, OR_AUTHCFG,
+ "on if a session should be written to the CGI environment. Defaults to off"),
+ AP_INIT_TAKE1("SessionInclude", add_session_include, NULL, OR_AUTHCFG,
+ "URL prefixes to include in the session. Defaults to all URLs"),
+ AP_INIT_TAKE1("SessionExclude", add_session_exclude, NULL, OR_AUTHCFG,
+ "URL prefixes to exclude from the session. Defaults to no URLs"),
+ {NULL}
+};
+
+static void register_hooks(apr_pool_t * p)
+{
+ ap_register_output_filter("MOD_SESSION_OUT", ap_session_output_filter,
+ NULL, AP_FTYPE_CONTENT_SET);
+ ap_hook_insert_filter(ap_session_insert_output_filter, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_insert_error_filter(ap_session_insert_output_filter,
+ NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_fixups(ap_session_fixups, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_session_encode(ap_session_identity_encode, NULL, NULL, APR_HOOK_REALLY_FIRST);
+ ap_hook_session_decode(ap_session_identity_decode, NULL, NULL, APR_HOOK_REALLY_LAST);
+ APR_REGISTER_OPTIONAL_FN(ap_session_get);
+ APR_REGISTER_OPTIONAL_FN(ap_session_set);
+ APR_REGISTER_OPTIONAL_FN(ap_session_load);
+ APR_REGISTER_OPTIONAL_FN(ap_session_save);
+}
+
+module AP_MODULE_DECLARE_DATA session_module =
+{
+ STANDARD20_MODULE_STUFF,
+ create_session_dir_config, /* dir config creater */
+ merge_session_dir_config, /* dir merger --- default is to override */
+ NULL, /* server config */
+ NULL, /* merge server config */
+ session_cmds, /* command apr_table_t */
+ register_hooks /* register hooks */
+};
Propchange: httpd/httpd/trunk/modules/session/mod_session.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpd/httpd/trunk/modules/session/mod_session.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpd/httpd/trunk/modules/session/mod_session_cookie.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpd/httpd/trunk/modules/session/mod_session_crypto.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpd/httpd/trunk/modules/session/mod_session_dbd.c
------------------------------------------------------------------------------
svn:eol-style = native