httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From n.@apache.org
Subject cvs commit: httpd-2.0/modules/mappers mod_rewrite.c mod_rewrite.h
Date Mon, 19 May 2003 02:25:19 GMT
nd          2003/05/18 19:25:19

  Modified:    .        Tag: APACHE_2_0_BRANCH CHANGES STATUS
               modules/mappers Tag: APACHE_2_0_BRANCH mod_rewrite.c
                        mod_rewrite.h
  Log:
  Fix mod_rewrite's abs_URI handling.
  - uris were partially not correctly escaped (in particular:
    ldap, news, mailto)
  - not all uri schemes contain an authority component (//)
  - add nntp:// scheme
  - don't add a query string (and drop r->args) if it's not
    http or mailto scheme
  - be more efficient (think so)
  
  Reviewed by: Justin Erenkrantz, Brian Pane
  
  Revision  Changes    Path
  No                   revision
  
  
  No                   revision
  
  
  1.988.2.104 +4 -0      httpd-2.0/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/CHANGES,v
  retrieving revision 1.988.2.103
  retrieving revision 1.988.2.104
  diff -u -r1.988.2.103 -r1.988.2.104
  --- CHANGES	18 May 2003 18:56:15 -0000	1.988.2.103
  +++ CHANGES	19 May 2003 02:25:18 -0000	1.988.2.104
  @@ -1,5 +1,9 @@
   Changes with Apache 2.0.46
   
  +  *) Fix mod_rewrite's handling of absolute URIs. The escaping routines
  +     now work scheme dependent and the query string will only be
  +     appended if supported by the particular scheme.  [André Malo]
  +
     *) Make mod_expires' ExpiresByType work properly, including for
        dynamically-generated documents.  [Ken Coar]
   
  
  
  
  1.751.2.299 +1 -5      httpd-2.0/STATUS
  
  Index: STATUS
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/STATUS,v
  retrieving revision 1.751.2.298
  retrieving revision 1.751.2.299
  diff -u -r1.751.2.298 -r1.751.2.299
  --- STATUS	19 May 2003 01:39:15 -0000	1.751.2.298
  +++ STATUS	19 May 2003 02:25:18 -0000	1.751.2.299
  @@ -134,10 +134,6 @@
         [ This one is under review.  Don't merge.  ]
         +1:
   
  -    * Fix mod_rewrite's handling of absolute URIs. (2.0 + 1.3)
  -      modules/mappers/mod_rewrite.c: r1.146
  -      +1: nd, jerenkrantz, brianp
  -
       * mod_negotiation: parse quality values independent from
         the current locale and level values as integers. PR 17564.
         (essentially: get a rid of atof()) (2.0 + 1.3)
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.135.2.12 +172 -81   httpd-2.0/modules/mappers/mod_rewrite.c
  
  Index: mod_rewrite.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/mappers/mod_rewrite.c,v
  retrieving revision 1.135.2.11
  retrieving revision 1.135.2.12
  diff -u -r1.135.2.11 -r1.135.2.12
  --- mod_rewrite.c	13 May 2003 22:49:39 -0000	1.135.2.11
  +++ mod_rewrite.c	19 May 2003 02:25:19 -0000	1.135.2.12
  @@ -1103,7 +1103,6 @@
       const char *thisurl;
       char buf[512];
       char docroot[512];
  -    char *cp, *cp2;
       const char *ccp;
       unsigned int port;
       int rulestatus;
  @@ -1190,6 +1189,7 @@
        */
       rulestatus = apply_rewrite_list(r, conf->rewriterules, NULL);
       if (rulestatus) {
  +        unsigned skip;
   
           if (strlen(r->filename) > 6 &&
               strncmp(r->filename, "proxy:", 6) == 0) {
  @@ -1227,40 +1227,21 @@
                          r->filename);
               return OK;
           }
  -        else if (is_absolute_uri(r->filename)) {
  +        else if ((skip = is_absolute_uri(r->filename)) > 0) {
               /* it was finally rewritten to a remote URL */
   
  -            /* skip 'scheme:' */
  -            for (cp = r->filename; *cp != ':' && *cp != '\0'; cp++)
  -                ;
  -            /* skip '://' */
  -            cp += 3;
  -            /* skip host part */
  -            for ( ; *cp != '/' && *cp != '\0'; cp++)
  -                ;
  -            if (*cp != '\0') {
  -                if (rulestatus != ACTION_NOESCAPE) {
  -                    rewritelog(r, 1, "escaping %s for redirect", r->filename);
  -                    cp2 = ap_escape_uri(r->pool, cp);
  -                }
  -                else {
  -                    cp2 = apr_pstrdup(r->pool, cp);
  -                }
  -                *cp = '\0';
  -                r->filename = apr_pstrcat(r->pool, r->filename, cp2, NULL);
  +            if (rulestatus != ACTION_NOESCAPE) {
  +                rewritelog(r, 1, "escaping %s for redirect", r->filename);
  +                r->filename = escape_absolute_uri(r->pool, r->filename, skip);
               }
   
               /* append the QUERY_STRING part */
  -            if (r->args != NULL) {
  -                char *args;
  -                if (rulestatus == ACTION_NOESCAPE) {
  -                    args = r->args;
  -                }
  -                else {
  -                    args = ap_escape_uri(r->pool, r->args);
  -                }
  +            if (r->args) {
                   r->filename = apr_pstrcat(r->pool, r->filename, "?",
  -                                          args, NULL);
  +                                          (rulestatus == ACTION_NOESCAPE)
  +                                            ? r->args
  +                                            : ap_escape_uri(r->pool, r->args),
  +                                          NULL);
               }
   
               /* determine HTTP redirect response code */
  @@ -1472,6 +1453,7 @@
        */
       rulestatus = apply_rewrite_list(r, dconf->rewriterules, dconf->directory);
       if (rulestatus) {
  +        unsigned skip;
   
           if (strlen(r->filename) > 6 &&
               strncmp(r->filename, "proxy:", 6) == 0) {
  @@ -1495,7 +1477,7 @@
                          "%s [OK]", dconf->directory, r->filename);
               return OK;
           }
  -        else if (is_absolute_uri(r->filename)) {
  +        else if ((skip = is_absolute_uri(r->filename)) > 0) {
               /* it was finally rewritten to a remote URL */
   
               /* because we are in a per-dir context
  @@ -1503,11 +1485,9 @@
                * if there is a base-URL available
                */
               if (dconf->baseurl != NULL) {
  -                /* skip 'scheme:' */
  -                for (cp = r->filename; *cp != ':' && *cp != '\0'; cp++)
  -                    ;
  -                /* skip '://' */
  -                cp += 3;
  +                /* skip 'scheme://' */
  +                cp = r->filename + skip;
  +
                   if ((cp = ap_strchr(cp, '/')) != NULL && *(++cp)) {
                       rewritelog(r, 2,
                                  "[per-dir %s] trying to replace "
  @@ -1550,39 +1530,19 @@
               }
   
               /* now prepare the redirect... */
  -
  -            /* skip 'scheme:' */
  -            for (cp = r->filename; *cp != ':' && *cp != '\0'; cp++)
  -                ;
  -            /* skip '://' */
  -            cp += 3;
  -            /* skip host part */
  -            for ( ; *cp != '/' && *cp != '\0'; cp++)
  -                ;
  -            if (*cp != '\0') {
  -                if (rulestatus != ACTION_NOESCAPE) {
  -                    rewritelog(r, 1, "[per-dir %s] escaping %s for redirect",
  -                               dconf->directory, r->filename);
  -                    cp2 = ap_escape_uri(r->pool, cp);
  -                }
  -                else {
  -                    cp2 = apr_pstrdup(r->pool, cp);
  -                }
  -                *cp = '\0';
  -                r->filename = apr_pstrcat(r->pool, r->filename, cp2, NULL);
  +            if (rulestatus != ACTION_NOESCAPE) {
  +                rewritelog(r, 1, "[per-dir %s] escaping %s for redirect",
  +                           dconf->directory, r->filename);
  +                r->filename = escape_absolute_uri(r->pool, r->filename, skip);
               }
   
               /* append the QUERY_STRING part */
  -            if (r->args != NULL) {
  -                char *args;
  -                if (rulestatus == ACTION_NOESCAPE) {
  -                    args = r->args;
  -                }
  -                else {
  -                    args = ap_escape_uri(r->pool, r->args);
  -                }
  +            if (r->args) {
                   r->filename = apr_pstrcat(r->pool, r->filename, "?",
  -                                          args, NULL);
  +                                          (rulestatus == ACTION_NOESCAPE)
  +                                            ? r->args
  +                                            : ap_escape_uri(r->pool, r->args),
  +                                          NULL);
               }
   
               /* determine HTTP redirect response code */
  @@ -2624,6 +2584,16 @@
       char *q;
       char *olduri;
   
  +    /* don't touch, unless it's an http or mailto URL.
  +     * See RFC 1738 and RFC 2368.
  +     */
  +    if (   is_absolute_uri(r->filename)
  +        && strncasecmp(r->filename, "http", 4)
  +        && strncasecmp(r->filename, "mailto", 6)) {
  +        r->args = NULL; /* forget the query that's still flying around */
  +        return;
  +    }
  +
       q = strchr(r->filename, '?');
       if (q != NULL) {
           olduri = apr_pstrdup(r->pool, r->filename);
  @@ -2647,6 +2617,7 @@
                          r->filename, r->args);
           }
       }
  +
       return;
   }
   
  @@ -2772,27 +2743,147 @@
   }
   
   
  -/*
  -**
  -**  return non-zero if the URI is absolute (includes a scheme etc.)
  -**
  -*/
  +/* return number of chars of the scheme (incl. '://')
  + * if the URI is absolute (includes a scheme etc.)
  + * otherwise 0.
  + *
  + * NOTE: If you add new schemes here, please have a
  + *       look at escape_absolute_uri and splitout_queryargs.
  + *       Not every scheme takes query strings and some schemes
  + *       may be handled in a special way.
  + *
  + * XXX: we should consider a scheme registry, perhaps with
  + *      appropriate escape callbacks to allow other modules
  + *      to extend mod_rewrite at runtime.
  + */
  +static unsigned is_absolute_uri(char *uri)
  +{
  +    /* fast exit */
  +    if (*uri == '/' || strlen(uri) <= 5) {
  +        return 0;
  +    }
  +
  +    switch (*uri++) {
  +    case 'f':
  +    case 'F':
  +        if (!strncasecmp(uri, "tp://", 5)) {        /* ftp://    */
  +            return 6;
  +        }
  +        break;
   
  -static int is_absolute_uri(char *uri)
  +    case 'g':
  +    case 'G':
  +        if (!strncasecmp(uri, "opher://", 8)) {     /* gopher:// */
  +            return 9;
  +        }
  +        break;
  +
  +    case 'h':
  +    case 'H':
  +        if (!strncasecmp(uri, "ttp://", 6)) {       /* http://   */
  +            return 7;
  +        }
  +        else if (!strncasecmp(uri, "ttps://", 7)) { /* https://  */
  +            return 8;
  +        }
  +        break;
  +
  +    case 'l':
  +    case 'L':
  +        if (!strncasecmp(uri, "dap://", 6)) {       /* ldap://   */
  +            return 7;
  +        }
  +        break;
  +
  +    case 'm':
  +    case 'M':
  +        if (!strncasecmp(uri, "ailto:", 6)) {       /* mailto:   */
  +            return 7;
  +        }
  +        break;
  +
  +    case 'n':
  +    case 'N':
  +        if (!strncasecmp(uri, "ews:", 4)) {         /* news:     */
  +            return 5;
  +        }
  +        else if (!strncasecmp(uri, "ntp://", 6)) {  /* nntp://   */
  +            return 7;
  +        }
  +        break;
  +    }
  +
  +    return 0;
  +}
  +
  +
  +/* escape absolute uri, which may or may not be path oriented.
  + * So let's handle them differently.
  + */
  +static char *escape_absolute_uri(apr_pool_t *p, char *uri, unsigned scheme)
   {
  -    int i = strlen(uri);
  -    if (   (i > 7 && strncasecmp(uri, "http://",   7) == 0)
  -        || (i > 8 && strncasecmp(uri, "https://",  8) == 0)
  -        || (i > 9 && strncasecmp(uri, "gopher://", 9) == 0)
  -        || (i > 6 && strncasecmp(uri, "ftp://",    6) == 0)
  -        || (i > 5 && strncasecmp(uri, "ldap:",     5) == 0)
  -        || (i > 5 && strncasecmp(uri, "news:",     5) == 0)
  -        || (i > 7 && strncasecmp(uri, "mailto:",   7) == 0) ) {
  -        return 1;
  +    char *cp;
  +
  +    /* be safe.
  +     * NULL should indicate elsewhere, that something's wrong
  +     */
  +    if (!scheme || strlen(uri) < scheme) {
  +        return NULL;
       }
  -    else {
  -        return 0;
  +
  +    cp = uri + scheme;
  +
  +    /* scheme with authority part? */
  +    if (cp[-1] == '/') {
  +        /* skip host part */
  +        while (*cp && *cp != '/') {
  +            ++cp;
  +        }
  +
  +        /* nothing after the hostpart. ready! */
  +        if (!*cp || !*++cp) {
  +            return apr_pstrdup(p, uri);
  +        }
  +
  +        /* remember the hostname stuff */
  +        scheme = cp - uri;
  +
  +        /* special thing for ldap.
  +         * The parts are separated by question marks. From RFC 2255:
  +         *     ldapurl = scheme "://" [hostport] ["/"
  +         *               [dn ["?" [attributes] ["?" [scope]
  +         *               ["?" [filter] ["?" extensions]]]]]]
  +         */
  +        if (!strncasecmp(uri, "ldap", 4)) {
  +            char *token[5];
  +            int c = 0;
  +
  +            token[0] = cp = apr_pstrdup(p, cp);
  +            while (*cp && c < 5) {
  +                if (*cp == '?') {
  +                    token[++c] = cp + 1;
  +                    *cp = '\0';
  +                }
  +                ++cp;
  +            }
  +
  +            return apr_pstrcat(p, apr_pstrndup(p, uri, scheme),
  +                                          ap_escape_uri(p, token[0]),
  +                               (c >= 1) ? "?" : NULL,
  +                               (c >= 1) ? ap_escape_uri(p, token[1]) : NULL,
  +                               (c >= 2) ? "?" : NULL,
  +                               (c >= 2) ? ap_escape_uri(p, token[2]) : NULL,
  +                               (c >= 3) ? "?" : NULL,
  +                               (c >= 3) ? ap_escape_uri(p, token[3]) : NULL,
  +                               (c >= 4) ? "?" : NULL,
  +                               (c >= 4) ? ap_escape_uri(p, token[4]) : NULL,
  +                               NULL);
  +        }
       }
  +
  +    /* Nothing special here. Apply normal escaping. */
  +    return apr_pstrcat(p, apr_pstrndup(p, uri, scheme),
  +                       ap_escape_uri(p, cp), NULL);
   }
   
   
  
  
  
  1.39.2.4  +2 -1      httpd-2.0/modules/mappers/mod_rewrite.h
  
  Index: mod_rewrite.h
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/mappers/mod_rewrite.h,v
  retrieving revision 1.39.2.3
  retrieving revision 1.39.2.4
  diff -u -r1.39.2.3 -r1.39.2.4
  --- mod_rewrite.h	27 Mar 2003 22:40:55 -0000	1.39.2.3
  +++ mod_rewrite.h	19 May 2003 02:25:19 -0000	1.39.2.4
  @@ -413,7 +413,8 @@
   static void  splitout_queryargs(request_rec *r, int qsappend);
   static void  fully_qualify_uri(request_rec *r);
   static void  reduce_uri(request_rec *r);
  -static int   is_absolute_uri(char *uri);
  +static unsigned is_absolute_uri(char *uri);
  +static char *escape_absolute_uri(apr_pool_t *p, char *uri, unsigned scheme);
   static char *expand_tildepaths(request_rec *r, char *uri);
   
       /* rewrite map support functions */
  
  
  

Mime
View raw message