aboutsummaryrefslogtreecommitdiffstats
path: root/package/uhttpd/src/uhttpd-utils.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jow@openwrt.org>2010-04-15 19:46:35 +0000
committerJo-Philipp Wich <jow@openwrt.org>2010-04-15 19:46:35 +0000
commit20ef055c2f698618142a280d5cbc010acacfd651 (patch)
tree3df03f974bf03b35e3f32dbbfed7385272c2d975 /package/uhttpd/src/uhttpd-utils.c
parenta8e20318c5fdb6809892e31cd658d2eda4a9ee2d (diff)
downloadupstream-20ef055c2f698618142a280d5cbc010acacfd651.tar.gz
upstream-20ef055c2f698618142a280d5cbc010acacfd651.tar.bz2
upstream-20ef055c2f698618142a280d5cbc010acacfd651.zip
uhttpd: - make network timeout configurable, increase default to 30 seconds (#7067) - follow symlinks in docroot and add option to disable that - fix mimetype detection for files with combined extensions (.tar.gz, ...)
SVN-Revision: 20883
Diffstat (limited to 'package/uhttpd/src/uhttpd-utils.c')
-rw-r--r--package/uhttpd/src/uhttpd-utils.c82
1 files changed, 78 insertions, 4 deletions
diff --git a/package/uhttpd/src/uhttpd-utils.c b/package/uhttpd/src/uhttpd-utils.c
index 55b2c410e3..e65f2136d6 100644
--- a/package/uhttpd/src/uhttpd-utils.c
+++ b/package/uhttpd/src/uhttpd-utils.c
@@ -116,8 +116,8 @@ int uh_tcp_send(struct client *cl, const char *buf, int len)
FD_ZERO(&writer);
FD_SET(cl->socket, &writer);
- timeout.tv_sec = 0;
- timeout.tv_usec = 500000;
+ timeout.tv_sec = cl->server->conf->network_timeout;
+ timeout.tv_usec = 0;
if( select(cl->socket + 1, NULL, &writer, NULL, &timeout) > 0 )
{
@@ -376,6 +376,78 @@ int uh_b64decode(char *buf, int blen, const unsigned char *src, int slen)
return len;
}
+static char * canonpath(const char *path, char *path_resolved)
+{
+ char path_copy[PATH_MAX];
+ char *path_cpy = path_copy;
+ char *path_res = path_resolved;
+
+ struct stat s;
+
+
+ /* relative -> absolute */
+ if( *path != '/' )
+ {
+ getcwd(path_copy, PATH_MAX);
+ strncat(path_copy, "/", PATH_MAX - strlen(path_copy));
+ strncat(path_copy, path, PATH_MAX - strlen(path_copy));
+ }
+ else
+ {
+ strncpy(path_copy, path, PATH_MAX);
+ }
+
+ /* normalize */
+ while( (*path_cpy != '\0') && (path_cpy < (path_copy + PATH_MAX - 2)) )
+ {
+ if( *path_cpy == '/' )
+ {
+ /* skip repeating / */
+ if( path_cpy[1] == '/' )
+ {
+ path_cpy++;
+ continue;
+ }
+
+ /* /./ or /../ */
+ else if( path_cpy[1] == '.' )
+ {
+ /* skip /./ */
+ if( (path_cpy[2] == '/') || (path_cpy[2] == '\0') )
+ {
+ path_cpy += 2;
+ continue;
+ }
+
+ /* collapse /x/../ */
+ else if( path_cpy[2] == '.' )
+ {
+ while( (path_res > path_resolved) && (*--path_res != '/') )
+ ;
+
+ path_cpy += 3;
+ continue;
+ }
+ }
+ }
+
+ *path_res++ = *path_cpy++;
+ }
+
+ /* remove trailing slash if not root / */
+ if( (path_res > (path_resolved+1)) && (path_res[-1] == '/') )
+ path_res--;
+ else if( path_res == path_resolved )
+ *path_res++ = '/';
+
+ *path_res = '\0';
+
+ /* test access */
+ if( !stat(path_resolved, &s) && (s.st_mode & S_IROTH) )
+ return path_resolved;
+
+ return NULL;
+}
struct path_info * uh_path_lookup(struct client *cl, const char *url)
{
@@ -387,6 +459,7 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url)
char *docroot = cl->server->conf->docroot;
char *pathptr = NULL;
+ int no_sym = cl->server->conf->no_symlinks;
int i = 0;
struct stat s;
@@ -432,8 +505,9 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url)
memset(path_info, 0, sizeof(path_info));
memcpy(path_info, buffer, min(i + 1, sizeof(path_info) - 1));
- if( realpath(path_info, path_phys) )
- {
+ if( no_sym ? realpath(path_info, path_phys)
+ : canonpath(path_info, path_phys)
+ ) {
memset(path_info, 0, sizeof(path_info));
memcpy(path_info, &buffer[i],
min(strlen(buffer) - i, sizeof(path_info) - 1));