[package] uhttpd: allow lowercase http header fields (#8513)
[openwrt.git] / package / uhttpd / src / uhttpd-utils.c
index e68926e..c7bc867 100644 (file)
@@ -112,6 +112,7 @@ int select_intr(int n, fd_set *r, fd_set *w, fd_set *e, struct timeval *t)
        /* unblock SIGCHLD */
        sigemptyset(&ssn);
        sigaddset(&ssn, SIGCHLD);
+       sigaddset(&ssn, SIGPIPE);
        sigprocmask(SIG_UNBLOCK, &ssn, &sso);
 
        rv = select(n, r, w, e, t);
@@ -193,8 +194,6 @@ int uh_tcp_recv(struct client *cl, char *buf, int len)
        return sz;
 }
 
-#define ensure(x) \
-       do { if( x < 0 ) return -1; } while(0)
 
 int uh_http_sendhf(struct client *cl, int code, const char *summary, const char *fmt, ...)
 {
@@ -211,14 +210,14 @@ int uh_http_sendhf(struct client *cl, int code, const char *summary, const char
                        code, summary
        );
 
-       ensure(uh_tcp_send(cl, buffer, len));
+       ensure_ret(uh_tcp_send(cl, buffer, len));
 
        va_start(ap, fmt);
        len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
        va_end(ap);
 
-       ensure(uh_http_sendc(cl, buffer, len));
-       ensure(uh_http_sendc(cl, NULL, 0));
+       ensure_ret(uh_http_sendc(cl, buffer, len));
+       ensure_ret(uh_http_sendc(cl, NULL, 0));
 
        return 0;
 }
@@ -235,13 +234,13 @@ int uh_http_sendc(struct client *cl, const char *data, int len)
        if( len > 0 )
        {
                clen = snprintf(chunk, sizeof(chunk), "%X\r\n", len);
-               ensure(uh_tcp_send(cl, chunk, clen));
-               ensure(uh_tcp_send(cl, data, len));
-               ensure(uh_tcp_send(cl, "\r\n", 2));
+               ensure_ret(uh_tcp_send(cl, chunk, clen));
+               ensure_ret(uh_tcp_send(cl, data, len));
+               ensure_ret(uh_tcp_send(cl, "\r\n", 2));
        }
        else
        {
-               ensure(uh_tcp_send(cl, "0\r\n\r\n", 5));
+               ensure_ret(uh_tcp_send(cl, "0\r\n\r\n", 5));
        }
 
        return 0;
@@ -259,9 +258,9 @@ int uh_http_sendf(
        va_end(ap);
 
        if( (req != NULL) && (req->version > 1.0) )
-               ensure(uh_http_sendc(cl, buffer, len));
+               ensure_ret(uh_http_sendc(cl, buffer, len));
        else if( len > 0 )
-               ensure(uh_tcp_send(cl, buffer, len));
+               ensure_ret(uh_tcp_send(cl, buffer, len));
 
        return 0;
 }
@@ -273,9 +272,9 @@ int uh_http_send(
                len = strlen(buf);
 
        if( (req != NULL) && (req->version > 1.0) )
-               ensure(uh_http_sendc(cl, buf, len));
+               ensure_ret(uh_http_sendc(cl, buf, len));
        else if( len > 0 )
-               ensure(uh_tcp_send(cl, buf, len));
+               ensure_ret(uh_tcp_send(cl, buf, len));
 
        return 0;
 }
@@ -475,6 +474,7 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url)
        char *docroot = cl->server->conf->docroot;
        char *pathptr = NULL;
 
+       int slash = 0;
        int no_sym = cl->server->conf->no_symlinks;
        int i = 0;
        struct stat s;
@@ -517,7 +517,7 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url)
        }
 
        /* create canon path */
-       for( i = strlen(buffer); i >= 0; i-- )
+       for( i = strlen(buffer), slash = (buffer[max(0, i-1)] == '/'); i >= 0; i-- )
        {
                if( (buffer[i] == 0) || (buffer[i] == '/') )
                {
@@ -568,7 +568,23 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url)
                        memcpy(buffer, path_phys, sizeof(buffer));
                        pathptr = &buffer[strlen(buffer)];
 
-                       if( cl->server->conf->index_file )
+                       /* if requested url resolves to a directory and a trailing slash
+                          is missing in the request url, redirect the client to the same
+                          url with trailing slash appended */
+                       if( !slash )
+                       {
+                               uh_http_sendf(cl, NULL,
+                                       "HTTP/1.1 302 Found\r\n"
+                                       "Location: %s%s%s\r\n"
+                                       "Connection: close\r\n\r\n",
+                                               &path_phys[strlen(docroot)],
+                                               p.query ? "?" : "",
+                                               p.query ? p.query : ""
+                               );
+
+                               p.redirected = 1;
+                       }
+                       else if( cl->server->conf->index_file )
                        {
                                strncat(buffer, cl->server->conf->index_file, sizeof(buffer));
 
@@ -611,7 +627,10 @@ struct auth_realm * uh_auth_add(char *path, char *user, char *pass)
 {
        struct auth_realm *new = NULL;
        struct passwd *pwd;
+
+#ifdef HAVE_SHADOW
        struct spwd *spwd;
+#endif
 
        if((new = (struct auth_realm *)malloc(sizeof(struct auth_realm))) != NULL)
        {
@@ -626,6 +645,7 @@ struct auth_realm * uh_auth_add(char *path, char *user, char *pass)
                /* given password refers to a passwd entry */
                if( (strlen(pass) > 3) && !strncmp(pass, "$p$", 3) )
                {
+#ifdef HAVE_SHADOW
                        /* try to resolve shadow entry */
                        if( ((spwd = getspnam(&pass[3])) != NULL) && spwd->sp_pwdp )
                        {
@@ -633,13 +653,16 @@ struct auth_realm * uh_auth_add(char *path, char *user, char *pass)
                                        min(strlen(spwd->sp_pwdp), sizeof(new->pass) - 1));
                        }
 
+                       else
+#endif
+
                        /* try to resolve passwd entry */
-                       else if( ((pwd = getpwnam(&pass[3])) != NULL) && pwd->pw_passwd &&
+                       if( ((pwd = getpwnam(&pass[3])) != NULL) && pwd->pw_passwd &&
                                (pwd->pw_passwd[0] != '!') && (pwd->pw_passwd[0] != 0)
                        ) {
                                memcpy(new->pass, pwd->pw_passwd,
                                        min(strlen(pwd->pw_passwd), sizeof(new->pass) - 1));
-                       }                       
+                       }
                }
 
                /* ordinary pwd */
@@ -729,8 +752,6 @@ int uh_auth_check(
                                        req->realm = realm;
                                        break;
                                }
-
-                               realm = NULL;
                        }
 
                        /* found a realm matching the username */
This page took 0.031673 seconds and 4 git commands to generate.