uhttpd: everybody loves licences, add one
[project/luci.git] / contrib / package / uhttpd / src / uhttpd-utils.c
index 89ee46f..c3ff35f 100644 (file)
@@ -1,3 +1,21 @@
+/*
+ * uhttpd - Tiny non-forking httpd - Utility functions
+ *
+ *   Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
+ *
+ *  Licensed 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 "uhttpd.h"
 #include "uhttpd-utils.h"
 
@@ -344,9 +362,7 @@ struct uh_path_info * uh_path_lookup(struct client *cl, const char *url)
        char *docroot = cl->server->conf->docroot;
        char *pathptr = NULL;
 
-       int skip = 0;
-       int plen = 0;
-
+       int i = 0;
        struct stat s;
 
 
@@ -355,129 +371,101 @@ struct uh_path_info * uh_path_lookup(struct client *cl, const char *url)
        memset(buffer, 0, sizeof(buffer));
        memset(&p, 0, sizeof(p));
 
-       /* first separate query string from url */
+       /* copy docroot */
+       memcpy(buffer, docroot, sizeof(buffer));
+
+       /* separate query string from url */
        if( (pathptr = strchr(url, '?')) != NULL )
        {
                p.query = pathptr[1] ? pathptr + 1 : NULL;
 
                /* urldecode component w/o query */
                if( pathptr > url )
-                       plen = uh_urldecode(
-                               buffer, sizeof(buffer), url,
-                               (int)(pathptr - url) - 1
+                       uh_urldecode(
+                               &buffer[strlen(docroot)],
+                               sizeof(buffer) - strlen(docroot) - 1,
+                               url, (int)(pathptr - url) - 1
                        );
-               else
-                       plen = 0;
        }
 
        /* no query string, decode all of url */
        else
        {
-               plen = uh_urldecode(
-                       buffer, sizeof(buffer), url, strlen(url)
+               uh_urldecode(
+                       &buffer[strlen(docroot)],
+                       sizeof(buffer) - strlen(docroot) - 1,
+                       url, strlen(url)
                );
        }
 
-       /* copy docroot */
-       memcpy(path_phys, docroot, sizeof(path_phys));
-
-       /* append normalized path, leave two bytes free
-        * for trailing slash and terminating zero byte */
-       plen = strlen(docroot) + uh_path_normalize(
-               &path_phys[strlen(docroot)],
-               sizeof(path_phys) - strlen(docroot) - 2,
-               buffer, plen
-       );
-
-       /* copy result to info buffer */
-       memcpy(path_info, path_phys, sizeof(path_info));
-
-       /* find path */
-       while( 1 )
+       /* create canon path */
+       for( i = strlen(buffer); i >= 0; i-- )
        {
-               /* test current path */
-               if( !stat(path_phys, &p.stat) )
+               if( (buffer[i] == 0) || (buffer[i] == '/') )
                {
-                       /* is a regular file */
-                       if( p.stat.st_mode & S_IFREG )
-                       {
-                               p.root = docroot;
-                               p.phys = path_phys;
-                               p.name = &path_phys[strlen(docroot)-1];
-
-                               /* find workdir */
-                               if( (pathptr = strrchr(path_phys, '/')) != NULL )
-                               {
-                                       path_info[(int)(pathptr - path_phys) + 1] = 0;
-                                       p.wdir = path_info;
-                               }
-                               else
-                               {
-                                       p.wdir = docroot;
-                               }
+                       memset(path_info, 0, sizeof(path_info));
+                       memcpy(path_info, buffer, min(i + 1, sizeof(path_info) - 1));
 
-                               /* find path info */
-                               if( path_info[strlen(path_phys)] != 0 )
-                               {
-                                       p.info = &path_info[strlen(path_phys)];
-                               }
+                       if( realpath(path_info, path_phys) )
+                       {
+                               memset(path_info, 0, sizeof(path_info));
+                               memcpy(path_info, &buffer[i],
+                                       min(strlen(buffer) - i, sizeof(path_info) - 1));
 
                                break;
                        }
+               }
+       }
 
-                       /* is a directory */
-                       else if( (p.stat.st_mode & S_IFDIR) && (skip < 1) )
-                       {
-                               /* ensure trailing slash */
-                               if( path_phys[plen-1] != '/' )
-                                       path_phys[plen] = '/';
-
-                               /* try to locate index file */
-                               memset(buffer, 0, sizeof(buffer));
-                               memcpy(buffer, path_phys, sizeof(buffer));
-                               pathptr = &buffer[strlen(buffer)];
+       /* check whether found path is within docroot */
+       if( strncmp(path_phys, docroot, strlen(docroot)) ||
+           ((path_phys[strlen(docroot)] != 0) &&
+                (path_phys[strlen(docroot)] != '/'))
+       ) {
+               return NULL;
+       }
 
-                               for( skip = 0; skip < array_size(uh_index_files); skip++ )
-                               {
-                                       strncat(buffer, uh_index_files[skip], sizeof(buffer));
-
-                                       if( !stat(buffer, &s) && (s.st_mode & S_IFREG) )
-                                       {
-                                               memset(path_info, 0, sizeof(path_info));
-                                               memcpy(path_info, path_phys, strlen(path_phys));
-                                               memcpy(path_phys, buffer, sizeof(path_phys));
-                                               memcpy(&p.stat, &s, sizeof(p.stat));
-                                               p.wdir = path_info;
-                                               break;
-                                       }
-
-                                       *pathptr = 0;
-                               }
+       /* test current path */
+       if( ! stat(path_phys, &p.stat) )
+       {
+               /* is a regular file */
+               if( p.stat.st_mode & S_IFREG )
+               {
+                       p.root = docroot;
+                       p.phys = path_phys;
+                       p.name = &path_phys[strlen(docroot)];
+                       p.info = path_info[0] ? path_info : NULL;
+               }
 
-                               p.root = docroot;
-                               p.phys = path_phys;
-                               p.name = &path_phys[strlen(docroot)-1];
+               /* is a directory */
+               else if( (p.stat.st_mode & S_IFDIR) && !strlen(path_info) )
+               {
+                       /* ensure trailing slash */
+                       if( path_phys[strlen(path_phys)-1] != '/' )
+                               path_phys[strlen(path_phys)] = '/';
 
-                               break;
-                       }
+                       /* try to locate index file */
+                       memset(buffer, 0, sizeof(buffer));
+                       memcpy(buffer, path_phys, sizeof(buffer));
+                       pathptr = &buffer[strlen(buffer)];
 
-                       /* not found */
-                       else if( skip )
+                       for( i = 0; i < array_size(uh_index_files); i++ )
                        {
-                               break;
-                       }
-               }
+                               strncat(buffer, uh_index_files[i], sizeof(buffer));
 
-               else if( (strlen(path_phys) > strlen(docroot)) &&
-                        ((pathptr = strrchr(path_phys, '/')) != NULL)
-               ) {
-                       *pathptr = 0;
-                       skip = 1;
-               }
+                               if( !stat(buffer, &s) && (s.st_mode & S_IFREG) )
+                               {
+                                       memcpy(path_phys, buffer, sizeof(path_phys));
+                                       memcpy(&p.stat, &s, sizeof(p.stat));
+                                       break;
+                               }
 
-               else
-               {
-                       break;
+                               *pathptr = 0;
+                       }
+
+                       p.root = docroot;
+                       p.phys = path_phys;
+                       p.name = &path_phys[strlen(docroot)];
                }
        }