httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From minf...@apache.org
Subject svn commit: r644746 - in /httpd/httpd/trunk: ./ docs/manual/mod/ include/ modules/session/ server/
Date Fri, 04 Apr 2008 15:58:18 GMT
Author: minfrin
Date: Fri Apr  4 08:58:15 2008
New Revision: 644746

URL: http://svn.apache.org/viewvc?rev=644746&view=rev
Log:
mod_session: Add a generic session interface to unify the different
attempts at saving persistent sessions across requests.

Added:
    httpd/httpd/trunk/docs/manual/mod/mod_session.xml
    httpd/httpd/trunk/modules/session/   (with props)
    httpd/httpd/trunk/modules/session/Makefile.in
    httpd/httpd/trunk/modules/session/config.m4
    httpd/httpd/trunk/modules/session/mod_session.c
    httpd/httpd/trunk/modules/session/mod_session.h
Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/configure.in
    httpd/httpd/trunk/include/httpd.h
    httpd/httpd/trunk/server/util.c

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=644746&r1=644745&r2=644746&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Fri Apr  4 08:58:15 2008
@@ -2,6 +2,10 @@
 Changes with Apache 2.3.0
 [ When backported to 2.2.x, remove entry from this file ]
 
+  *) mod_session: Add a generic session interface to unify the different
+     attempts at saving persistent sessions across requests.
+     [Graham Leggett]
+
   *) core, authn/z: Avoid calling access control hooks for internal requests
      with configurations which match those of initial request.  Revert to
      original behaviour (call access control hooks for internal requests

Modified: httpd/httpd/trunk/configure.in
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/configure.in?rev=644746&r1=644745&r2=644746&view=diff
==============================================================================
--- httpd/httpd/trunk/configure.in (original)
+++ httpd/httpd/trunk/configure.in Fri Apr  4 08:58:15 2008
@@ -204,7 +204,7 @@
   APR_ADDTO(INCLUDES, [-I\$(top_builddir)/include])
 fi
 
-APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/os/\$(OS_DIR) -I\$(top_srcdir)/server/mpm/\$(MPM_SUBDIR_NAME) -I\$(top_srcdir)/modules/http -I\$(top_srcdir)/modules/filters -I\$(top_srcdir)/modules/proxy -I\$(top_srcdir)/include -I\$(top_srcdir)/modules/generators -I\$(top_srcdir)/modules/mappers -I\$(top_srcdir)/modules/database])
+APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/os/\$(OS_DIR) -I\$(top_srcdir)/server/mpm/\$(MPM_SUBDIR_NAME) -I\$(top_srcdir)/modules/http -I\$(top_srcdir)/modules/filters -I\$(top_srcdir)/modules/proxy -I\$(top_srcdir)/modules/session -I\$(top_srcdir)/include -I\$(top_srcdir)/modules/generators -I\$(top_srcdir)/modules/mappers -I\$(top_srcdir)/modules/database])
 
 # apr/apr-util --includes may pick up system paths for dependent
 # libraries, so ensure these are later in INCLUDES than local source

Added: httpd/httpd/trunk/docs/manual/mod/mod_session.xml
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/mod/mod_session.xml?rev=644746&view=auto
==============================================================================
--- httpd/httpd/trunk/docs/manual/mod/mod_session.xml (added)
+++ httpd/httpd/trunk/docs/manual/mod/mod_session.xml Fri Apr  4 08:58:15 2008
@@ -0,0 +1,393 @@
+<?xml version="1.0"?>
+<!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd">
+<?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>
+<!-- $LastChangedRevision: 634760 $ -->
+
+<!--
+ 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.
+-->
+
+<modulesynopsis metafile="mod_session.xml.meta">
+
+<name>mod_session</name>
+<description>Session support</description>
+<status>Extension</status>
+<sourcefile>mod_session.c</sourcefile>
+<identifier>session_module</identifier>
+
+<summary>
+    <note type="warning"><title>Warning</title>
+      <p>The session modules make use of HTTP cookies, and as such can fall
+      victim to Cross Site Scripting attacks, or expose potentially private
+      information to clients. Please ensure that the relevant risks have
+      been taken into account before enabling the session functionality on
+      your server.</p>
+    </note>
+
+    <p>This module provides support for a server wide per user session
+    interface. Sessions can be used for keeping track of whether a user
+    has been logged in, or for other per user information that should
+    be kept available across requests.</p>
+    
+    <p>Sessions may be stored on the server, or may be stored on the
+    browser. Sessions may also be optionally encrypted for added security.
+    These features are divided into several modules in addition to
+    <module>mod_session</module>: <module>mod_session_crypto</module>,
+    <module>mod_session_cookie</module> and <module>mod_session_dbd</module>.
+    Depending on the server requirements, load the appropriate modules
+    into the server (either statically at compile time or dynamically
+    via the <directive module="mod_so">LoalModule</directive> directive).</p>
+
+    <p>Sessions may be manipulated from other modules that depend on the
+    session, or the session may be read from and written to using
+    environment variables and HTTP headers, as appropriate.</p>
+    
+</summary>
+<seealso><module>mod_session_cookie</module></seealso>
+<seealso><module>mod_session_crypto</module></seealso>
+<seealso><module>mod_session_dbd</module></seealso>
+
+    <section id="whatisasession"><title>What is a session?</title>
+      <p>At the core of the session interface is a table of key and value pairs
+      that are made accessible across browser requests.</p>
+      
+      <p>These pairs can be set any valid set of strings, as needed by the
+      application making use of the session.</p>
+      
+    </section>
+    <section id="whocanuseasession"><title>Who can use a session?</title>
+      <p>The session interface is primarily developed for the use by other
+      server modules, such as <module>mod_auth_form</module>, however CGI
+      based applications can optionally be granted access to the contents
+      of the session via the HTTP_SESSION environment variable. Sessions
+      have the option to be modified and/or updated by inserting an HTTP
+      response header containing the new session parameters.</p>
+
+    </section>
+    <section id="serversession"><title>Keeping sessions on the server</title>
+      <p>Apache can be configured to keep track of per user sessions stored
+      on a particular server or group of servers. This functionality is
+      similar to the sessions available in typical application servers.</p>
+      
+      <p>If configured, sessions are tracked through the use of a session ID that
+      is stored inside a cookie, or extracted from the parameters embedded
+      within the URL query string, as found in a typical GET request.</p>
+      
+      <p>As the contents of the session are stored exclusively on the server,
+      there is an expectation of privacy of the contents of the session. This
+      does have performance and resource implications should a large number
+      of sessions be present, or where a large number of webservers have to
+      share sessions with one another.</p>
+      
+      <p>The <module>mod_session_dbd</module> module allows the storage of user
+      sessions within a SQL database via <module>mod_dbd</module>.</p>
+
+    </section> <!-- /serversession -->
+    
+    <section id="browsersession"><title>Keeping sessions on the browser</title>
+      <p>Where keeping track of a session on a server is too resource
+      intensive or inconvenient, the option exists to store the contents
+      of the session within a cookie on the client browser instead.</p>
+      
+      <p>This has the advantage that minimal resources are required on the
+      server to keep track of sessions, and multiple servers within a server
+      farm have no need to share session information.</p>
+      
+      <p>The contents of the session however are exposed to the client, with a
+      corresponding risk of a loss of privacy. The
+      <module>mod_session_crypto</module> module can be configured to encrypt the
+      contents of the session before writing the session to the client.</p>
+
+      <p>The <module>mod_session_cookie</module> allows the storage of user
+      sessions on the browser within an HTTP cookie.</p>
+
+    </section> <!-- /browsersession -->
+
+    <section id="basicexamples"><title>Basic Examples</title>
+    
+      <p>Creating a session is as simple as turning the session on, and deciding
+      where the session will be stored. In this example, the session will be
+      stored on the browser, in a cookie called <code>session</code>.</p>
+      
+      <example><title>Browser based session</title>
+        Session On<br />
+        SessionCookieName session path=/<br />
+      </example>
+
+      <p>The session is not useful unless it can be written to or read from. The
+      following example shows how values can be injected into the session through
+      the use of a predetermined HTTP response header called
+      <code>X-Replace-Session</code>.</p>
+      
+      <example><title>Writing to a session</title>
+        Session On<br />
+        SessionCookieName session path=/<br />
+        SessionHeader X-Replace-Session<br />
+      </example>
+
+      <p>The header should contain name value pairs expressed in the same format
+      as a query string in a URL, as in the example below. Setting a key to the
+      empty string has the effect of removing that key from the session.</p>
+      
+      <example><title>CGI to write to a session</title>
+        #!/bin/bash<br />
+        echo "Content-Type: text/plain"<br />
+        echo "X-Replace-Session: key1=foo&amp;key2=&amp;key3=bar"<br />
+        echo<br />
+        env<br />
+      </example>
+
+      <p>If configured, the session can be read back from the HTTP_SESSION
+      environment variable. By default, the session is kept private, so this
+      has to be explicitly turned on with the
+      <directive module="mod_session">SessionEnv</directive> directive.</p>
+      
+      <example><title>Read from a session</title>
+        Session On<br />
+        SessionEnv On<br />
+        SessionCookieName session path=/<br />
+        SessionHeader X-Replace-Session<br />
+      </example>
+
+      <p>Once read, the CGI variable <code>HTTP_SESSION</code> should contain
+      the value <code>key1=foo&amp;key3=bar</code>.</p>
+
+    </section>
+    <section id="sessionprivacy"><title>Session Privacy</title>
+    
+      <p>Using the "show cookies" feature of your browser, you would have seen
+      a clear text representation of the session. This could potentially be a
+      problem should the end user need to be kept unaware of the contents of
+      the session, or where a third party could gain unauthorised access to the
+      data within the session.</p>
+      
+      <p>The contents of the session can be optionally encrypted before being
+      placed on the browser using the <module>mod_session_crypto</module>
+      module.</p>
+      
+      <example><title>Browser based encrypted session</title>
+        Session On<br />
+        SessionCryptoPassphrase secret<br />
+        SessionCookieName session path=/<br />
+      </example>
+      
+      <p>The session will be automatically decrypted on load, and encrypted on
+      save by Apache, the underlying application using the session need have
+      no knowledge that encryption is taking place.</p>
+      
+      <p>Sessions stored on the server rather than on the browser can also be
+      encrypted as needed, offering privacy where potentially sensitive
+      information is being shared between webservers in a server farm using
+      the <module>mod_session_dbd</module> module.</p>
+      
+    </section>
+    <section id="cookieprivacy"><title>Cookie Privacy</title>
+
+      <p>The HTTP cookie mechanism also offers privacy features, such as the
+      ability to restrict cookie transport to SSL protected pages only, or
+      to prevent browser based javascript from gaining access to the contents
+      of the cookie.</p>
+      
+      <note type="warning"><title>Warning</title>
+      <p>Some of the HTTP cookie privacy features are either non standard, or
+      are not implemented consistently across browsers. The session modules
+      allow you to set cookie parameters, but it makes no guarantee that privacy
+      will be respected by the browser. If security is a concern, use the
+      <module>mod_session_crypto</module> to encrypt the contents of the session,
+      or store the session on the server using the <module>mod_session_dbd</module>
+      module.</p>
+      </note>
+
+      <p>Standard cookie parameters can be specified after the name of the cookie,
+      as in the example below.</p>
+      
+      <example><title>Setting cookie parameters</title>
+        Session On<br />
+        SessionCryptoPassphrase secret<br />
+        SessionCookieName session path=/private;domain=example.com;httponly;secure;<br />
+      </example>
+      
+      <p>In cases where the Apache server forms the frontend for backend origin servers,
+      it is possible to have the session cookies removed from the incoming HTTP headers using
+      the <directive module="mod_session_cookie">SessionCookieRemove</directive> directive.
+      This keeps the contents of the session cookies from becoming accessible from the
+      backend server.
+      </p>
+
+    </section>
+    <section id="authentication"><title>Session Support for Authentication</title>
+
+      <p>As is possible within many application servers, authentication modules can use
+      a session for storing the username and password after login. The
+      <module>mod_auth_form</module> saves the user's login name and password within
+      the session.</p>
+
+      <example><title>Form based authentication</title>
+        Session On<br />
+        SessionCryptoPassphrase secret<br />
+        SessionCookieName session path=/<br />
+        AuthFormProvider file<br />
+        AuthUserFile conf/passwd<br />
+        AuthType form<br />
+        AuthName realm<br />
+        ...<br />
+      </example>
+      
+      <p>See the <module>mod_auth_form</module> module for documentation and complete
+      examples.</p>
+
+    </section>
+
+<directivesynopsis>
+<name>Session</name>
+<description>Enables a session for the current directory or location</description>
+<syntax>Session On|Off</syntax>
+<default>Session Off</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive>Session</directive> directive enables a session for the
+    directory or location container. Further directives control where the
+    session will be stored and how privacy is maintained.</p>
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>SessionMaxAge</name>
+<description>Define a maximum age in seconds for a session</description>
+<syntax>SessionMaxAge <var>maxage</var></syntax>
+<default>SessionMaxAge 0</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive>SessionMaxAge</directive> directive defines a time limit
+    for which a session will remain valid. When a session is saved, this time
+    limit is reset and an existing session can be continued. If a session
+    becomes older than this limit without a request to the server to refresh
+    the session, the session will time out and be removed. Where a session is
+    used to stored user login details, this has the effect of logging the user
+    out automatically after the given time.</p>
+    
+    <p>Setting the maxage to zero disables session expiry.</p>
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>SessionEnv</name>
+<description>Control whether the contents of the session are written to the
+<var>HTTP_SESSION</var> environment variable</description>
+<syntax>SessionEnv On|Off</syntax>
+<default>SessionEnv Off</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>If set to <var>On</var>, the <directive>SessionEnv</directive> directive
+    causes the contents of the session to be written to a CGI environment
+    variable called <var>HTTP_SESSION</var>.</p>
+    
+    <p>The string is written in the URL query format, for example:</p>
+
+    <example>
+      <code>key1=foo&amp;key3=bar</code>
+    </example>
+
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>SessionHeader</name>
+<description>Import session updates from a given HTTP response header</description>
+<syntax>SessionHeader <var>header</var></syntax>
+<default>none</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive>SessionHeader</directive> directive defines the name of an
+    HTTP response header which, if present, will be parsed and written to the
+    current session.</p>
+    
+    <p>The header value is expected to be in the URL query format, for example:</p>
+
+    <example>
+      <code>key1=foo&amp;key2=&amp;key3=bar</code>
+    </example>
+    
+    <p>Where a key is set to the empty string, that key will be removed from the
+    session.</p>
+
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>SessionInclude</name>
+<description>Define URL prefixes for which a session is valid</description>
+<syntax>SessionInclude <var>path</var></syntax>
+<default>all URLs</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive>SessionInclude</directive> directive allows sessions to
+    be made valid for specific URL prefixes only. This can be used to make a
+    website more efficient, by targeting a more precise URL space for which
+    a session should be maintained. By default, all URLs within the directory
+    or location are included in the session.</p>
+    
+    <note type="warning"><title>Warning</title>
+    <p>This directive has a similar purpose to the <var>path</var> attribute
+    in HTTP cookies, but should not be confused with this attribute. This
+    directive does not set the <var>path</var> attribute, which must be
+    configured separately.</p></note>
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>SessionExclude</name>
+<description>Define URL prefixes for which a session is ignored</description>
+<syntax>SessionExclude <var>path</var></syntax>
+<default>none</default>
+<contextlist><context>directory</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.0 and later</compatibility>
+
+<usage>
+    <p>The <directive>SessionExclude</directive> directive allows sessions to
+    be disabled specific URL prefixes only. This can be used to make a
+    website more efficient, by targeting a more precise URL space for which
+    a session should be maintained. By default, all URLs within the directory
+    or location are included in the session. The
+    <directive module="mod_session">SessionExclude</directive> directive takes
+    precedence over the
+    <directive module="mod_session">SessionInclude</directive> directive.</p>
+
+    <note type="warning"><title>Warning</title>
+    <p>This directive has a similar purpose to the <var>path</var> attribute
+    in HTTP cookies, but should not be confused with this attribute. This
+    directive does not set the <var>path</var> attribute, which must be
+    configured separately.</p></note>
+</usage>
+</directivesynopsis>
+
+</modulesynopsis>

Modified: httpd/httpd/trunk/include/httpd.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/httpd.h?rev=644746&r1=644745&r2=644746&view=diff
==============================================================================
--- httpd/httpd/trunk/include/httpd.h (original)
+++ httpd/httpd/trunk/include/httpd.h Fri Apr  4 08:58:15 2008
@@ -1435,6 +1435,13 @@
 AP_DECLARE(int) ap_is_url(const char *u);
 
 /**
+ * Unescape a string
+ * @param url The string to unescape
+ * @return 0 on success, non-zero otherwise
+ */
+AP_DECLARE(int) ap_unescape_all(char *url);
+
+/**
  * Unescape a URL
  * @param url The url to unescape
  * @return 0 on success, non-zero otherwise
@@ -1468,6 +1475,14 @@
  * @return The converted URL
  */
 AP_DECLARE(char *) ap_escape_path_segment(apr_pool_t *p, const char *s);
+
+/**
+ * Escape a path segment, as defined in RFC 1808, to a preallocated buffer.
+ * @param c The preallocated buffer to write to
+ * @param s The path to convert
+ * @return The converted URL (c)
+ */
+AP_DECLARE(char *) ap_escape_path_segment_b(char *c, const char *s);
 
 /**
  * convert an OS path to a URL in an OS dependant way.

Propchange: httpd/httpd/trunk/modules/session/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Apr  4 08:58:15 2008
@@ -0,0 +1,22 @@
+.deps
+.libs
+*.la
+modules.mk
+Makefile
+*.lo
+*.slo
+*.so
+Debug
+Release
+*.plg
+*.aps
+*.dep
+*.mak
+*.rc
+BuildLog.htm
+*.stc
+*.stt
+*.sto
+*.vcproj
+*.vcproj.*
+

Added: httpd/httpd/trunk/modules/session/Makefile.in
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/session/Makefile.in?rev=644746&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/session/Makefile.in (added)
+++ httpd/httpd/trunk/modules/session/Makefile.in Fri Apr  4 08:58:15 2008
@@ -0,0 +1,4 @@
+# a modules Makefile has no explicit targets -- they will be defined by
+# whatever modules are enabled. just grab special.mk to deal with this.
+include $(top_srcdir)/build/special.mk
+

Added: httpd/httpd/trunk/modules/session/config.m4
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/session/config.m4?rev=644746&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/session/config.m4 (added)
+++ httpd/httpd/trunk/modules/session/config.m4 Fri Apr  4 08:58:15 2008
@@ -0,0 +1,19 @@
+dnl modules enabled in this directory by default
+
+dnl Session
+
+dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]])
+
+APACHE_MODPATH_INIT(session)
+
+dnl Session modules; modules that are capable of storing key value pairs in
+dnl various places, such as databases, LDAP, or cookies.
+dnl
+APACHE_MODULE(session, session module, , , most)
+dnl APACHE_MODULE(session_cookie, session cookie module, , , most)
+dnl APACHE_MODULE(session_crypto, session crypto module, , , most)
+dnl APACHE_MODULE(session_dbd, session dbd module, , , most)
+dnl APACHE_MODULE(session_ldap, session ldap module, , , most)
+
+APACHE_MODPATH_FINISH
+

Added: httpd/httpd/trunk/modules/session/mod_session.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/session/mod_session.c?rev=644746&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/session/mod_session.c (added)
+++ httpd/httpd/trunk/modules/session/mod_session.c Fri Apr  4 08:58:15 2008
@@ -0,0 +1,617 @@
+/* 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.
+ */
+
+#define CORE_PRIVATE
+
+#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);
+    }
+    *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 (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;
+
+    /* 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 */
+    int 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_b(slider, key);
+    slider += strlen(slider);
+    *slider = '=';
+    slider++;
+    ap_escape_path_segment_b(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 */
+};

Added: httpd/httpd/trunk/modules/session/mod_session.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/session/mod_session.h?rev=644746&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/session/mod_session.h (added)
+++ httpd/httpd/trunk/modules/session/mod_session.h Fri Apr  4 08:58:15 2008
@@ -0,0 +1,206 @@
+/* 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.
+ */
+
+#ifndef MOD_SESSION_H
+#define MOD_SESSION_H
+
+/**
+ * @file  mod_session.h
+ * @brief Session Module for Apache
+ *
+ * @defgroup MOD_SESSION mod_session
+ * @ingroup  APACHE_MODS
+ * @{
+ */
+
+#define CORE_PRIVATE
+
+#include "apr_hooks.h"
+#include "apr_optional.h"
+#include "apr_tables.h"
+#include "apr_uuid.h"
+#include "apr_pools.h"
+#include "apr_time.h"
+
+#include "httpd.h"
+#include "http_config.h"
+#include "ap_config.h"
+
+#define MOD_SESSION_NOTES_KEY "mod_session_key"
+
+/**
+ * Define the name of a username stored in the session, so that modules interested
+ * in the username can find it in a standard place.
+ */
+#define MOD_SESSION_USER "user"
+
+/**
+ * Define the name of a password stored in the session, so that modules interested
+ * in the password can find it in a standard place.
+ */
+#define MOD_SESSION_PW "pw"
+
+/**
+ * A session structure.
+ *
+ * At the core of the session is a set of name value pairs making up the
+ * session.
+ *
+ * The session might be uniquely identified by an anonymous uuid, or
+ * a remote_user value, or both.
+ */
+typedef struct {
+    apr_pool_t *pool;             /* pool to be used for this session */
+    apr_uuid_t *uuid;             /* anonymous uuid of this particular session */
+    const char *remote_user;      /* user who owns this particular session */
+    apr_table_t *entries;         /* key value pairs */
+    const char *encoded;          /* the encoded version of the key value pairs */
+    apr_time_t expiry;            /* if > 0, the time of expiry of this session */
+    long maxage;                  /* if > 0, the maxage of the session, from
+                                   * which expiry is calculated */
+    int dirty;                    /* dirty flag */
+    int cached;                   /* true if this session was loaded from a
+                                   * cache of some kind */
+    int written;                  /* true if this session has already been
+                                   * written */
+} session_rec;
+
+/**
+ * Structure to carry the per-dir session config.
+ */
+typedef struct {
+    int enabled;                  /* whether the session has been enabled for
+                                   * this directory */
+    int enabled_set;
+    long maxage;                  /* seconds until session expiry */
+    int maxage_set;
+    const char *header;           /* header to inject session */
+    int header_set;
+    int env;                      /* whether the session has been enabled for
+                                   * this directory */
+    int env_set;
+    apr_array_header_t *includes; /* URL prefixes to be included. All
+                                   * URLs included if empty */
+    apr_array_header_t *excludes; /* URL prefixes to be excluded. No
+                                   * URLs excluded if empty */
+} session_dir_conf;
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * Hook to 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_HOOK(int, session_load, (request_rec * r, session_rec ** z))
+
+/**
+ * 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);
+
+/**
+ * Hook to 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_HOOK(int, session_save, (request_rec * r, session_rec * z))
+
+/**
+ * Hook to encode the session.
+ *
+ * In the default implementation, the key value pairs are encoded using
+ * key value pairs separated by equals, in turn separated by ampersand,
+ * like a web form.
+ *
+ * @param r The request
+ * @param z A pointer to where the session will be written.
+ */
+AP_DECLARE_HOOK(int, session_encode, (request_rec * r, session_rec * z))
+
+/**
+ * Hook to decode the session.
+ *
+ * In the default implementation, the key value pairs are encoded using
+ * key value pairs separated by equals, in turn separated by ampersand,
+ * like a web form.
+ *
+ * @param r The request
+ * @param z A pointer to where the session will be written.
+ */
+AP_DECLARE_HOOK(int, session_decode, (request_rec * r, session_rec * z))
+
+APR_DECLARE_OPTIONAL_FN(void, ap_session_get, (request_rec * r, session_rec * z,
+                                               const char *key, const char **value));
+APR_DECLARE_OPTIONAL_FN(void, ap_session_set, (request_rec * r, session_rec * z,
+                                               const char *key, const char *value));
+APR_DECLARE_OPTIONAL_FN(int, ap_session_load, (request_rec *, session_rec **));
+APR_DECLARE_OPTIONAL_FN(int, ap_session_save, (request_rec *, session_rec *));
+
+/**
+ * The name of the module.
+ */
+extern module AP_MODULE_DECLARE_DATA session_module;
+
+#endif /* MOD_SESSION_H */
+/** @} */

Modified: httpd/httpd/trunk/server/util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util.c?rev=644746&r1=644745&r2=644746&view=diff
==============================================================================
--- httpd/httpd/trunk/server/util.c (original)
+++ httpd/httpd/trunk/server/util.c Fri Apr  4 08:58:15 2008
@@ -1646,6 +1646,11 @@
     }
 }
 
+AP_DECLARE(int) ap_unescape_all(char *url)
+{
+    return unescape_url(url, NULL, NULL);
+}
+
 /* c2x takes an unsigned, and expects the caller has guaranteed that
  * 0 <= what < 256... which usually means that you have to cast to
  * unsigned char first, because (unsigned)(char)(x) first goes through
@@ -1685,9 +1690,8 @@
  * something with a '/' in it (and thus does not prefix "./").
  */
 
-AP_DECLARE(char *) ap_escape_path_segment(apr_pool_t *p, const char *segment)
+AP_DECLARE(char *) ap_escape_path_segment_b(char *copy, const char *segment)
 {
-    char *copy = apr_palloc(p, 3 * strlen(segment) + 1);
     const unsigned char *s = (const unsigned char *)segment;
     unsigned char *d = (unsigned char *)copy;
     unsigned c;
@@ -1703,6 +1707,11 @@
     }
     *d = '\0';
     return copy;
+}
+
+AP_DECLARE(char *) ap_escape_path_segment(apr_pool_t *p, const char *segment)
+{
+    return ap_escape_path_segment_b(apr_palloc(p, 3 * strlen(segment) + 1), segment);
 }
 
 AP_DECLARE(char *) ap_os_escape_path(apr_pool_t *p, const char *path, int partial)



Mime
View raw message