When displaying sizes as a floating-point number (e.g. "123.4 Mb"),
[sgt/agedu] / httpd.c
diff --git a/httpd.c b/httpd.c
index 7c3f0f8..aa40084 100644 (file)
--- a/httpd.c
+++ b/httpd.c
@@ -90,7 +90,7 @@ char *got_data(struct connctx *ctx, char *data, int length,
               const struct html_config *cfg)
 {
     char *line, *p, *q, *r, *z1, *z2, c1, c2;
-    int auth_provided = 0, auth_correct = 0;
+    int auth_correct = 0;
     unsigned long index;
     char *document, *ret;
 
@@ -235,7 +235,6 @@ char *got_data(struct connctx *ctx, char *data, int length,
                    p = q;
            }
            if (p < q) {
-               auth_provided = 1;
                while (p < q && isspace((unsigned char)*p))
                    p++;
                r = p;
@@ -262,23 +261,29 @@ char *got_data(struct connctx *ctx, char *data, int length,
        if (!magic_access && !auth_correct) {
            if (auth_string) {
                ret = http_error("401", "Unauthorized",
-                                "WWW-Authenticate: Basic realm=\""PNAME"\"\r",
+                                "WWW-Authenticate: Basic realm=\""PNAME"\"\r\n",
                                 "\nYou must authenticate to view these pages.");
            } else {
                ret = http_error("403", "Forbidden", NULL,
                                 "This is a restricted-access set of pages.");
            }
        } else {
+           char *q;
            p = ctx->url;
            p += strspn(p, "/?");
-           index = strtoul(p, NULL, 10);
-           document = html_query(ctx->t, index, cfg);
-           if (document) {
-               ret = http_success("text/html", 1, document);
-               sfree(document);
-           } else {
+           index = strtoul(p, &q, 10);
+           if (*q) {
                ret = http_error("404", "Not Found", NULL,
-                                "Pathname index out of range.");
+                                "This is not a valid pathname index.");
+           } else {
+               document = html_query(ctx->t, index, cfg, 1);
+               if (document) {
+                   ret = http_success("text/html", 1, document);
+                   sfree(document);
+               } else {
+                   ret = http_error("404", "Not Found", NULL,
+                                    "Pathname index out of range.");
+               }
            }
        }
        return ret;
@@ -362,9 +367,11 @@ int check_owning_uid(int fd, int flip)
        while (fgets(linebuf, sizeof(linebuf), fp)) {
            if (strlen(linebuf) >= 75 &&
                !strncmp(linebuf+6, matchbuf, strlen(matchbuf))) {
+               fclose(fp);
                return atoi(linebuf + 75);
            }
        }
+       fclose(fp);
     }
 
     return -1;
@@ -403,11 +410,9 @@ static void base64_encode_atom(unsigned char *data, int n, char *out)
 void run_httpd(const void *t, int authmask, const struct httpd_config *dcfg,
               const struct html_config *incfg)
 {
-    int fd;
+    int fd, ret;
     int authtype;
     char *authstring = NULL;
-    unsigned long ipaddr;
-    struct fd *f;
     struct sockaddr_in addr;
     socklen_t addrlen;
     struct html_config cfg = *incfg;
@@ -423,21 +428,40 @@ void run_httpd(const void *t, int authmask, const struct httpd_config *dcfg,
        fprintf(stderr, "socket(PF_INET): %s\n", strerror(errno));
        exit(1);
     }
+    memset(&addr, 0, sizeof(addr));
     addr.sin_family = AF_INET;
     if (!dcfg->address) {
+#ifdef RANDOM_LOCALHOST
+       unsigned long ipaddr;
        srand(0L);
        ipaddr = 0x7f000000;
        ipaddr += (1 + rand() % 255) << 16;
        ipaddr += (1 + rand() % 255) << 8;
        ipaddr += (1 + rand() % 255);
        addr.sin_addr.s_addr = htonl(ipaddr);
+#else
+       addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+#endif
        addr.sin_port = htons(0);
     } else {
        addr.sin_addr.s_addr = inet_addr(dcfg->address);
-       addr.sin_port = dcfg->port ? htons(dcfg->port) : 80;
+       addr.sin_port = dcfg->port ? htons(dcfg->port) : 0;
     }
     addrlen = sizeof(addr);
-    if (bind(fd, (struct sockaddr *)&addr, addrlen) < 0) {
+    ret = bind(fd, (const struct sockaddr *)&addr, addrlen);
+#ifdef RANDOM_LOCALHOST
+    if (ret < 0 && errno == EADDRNOTAVAIL && !dcfg->address) {
+       /*
+        * Some systems don't like us binding to random weird
+        * localhost-space addresses. Try again with the official
+        * INADDR_LOOPBACK.
+        */
+       addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+       addr.sin_port = htons(0);
+       ret = bind(fd, (const struct sockaddr *)&addr, addrlen);
+    }
+#endif
+    if (ret < 0) {
        fprintf(stderr, "bind: %s\n", strerror(errno));
        exit(1);
     }
@@ -537,19 +561,19 @@ void run_httpd(const void *t, int authmask, const struct httpd_config *dcfg,
        fprintf(stderr, PNAME ": authentication method not supported\n");
        exit(1);
     }
-    if (!dcfg->address) {
-       if (ntohs(addr.sin_port) == 80) {
-           printf("URL: http://%s/\n", inet_ntoa(addr.sin_addr));
-       } else {
-           printf("URL: http://%s:%d/\n",
-                  inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
-       }
+    if (ntohs(addr.sin_addr.s_addr) == INADDR_ANY) {
+       printf("Server port: %d\n", ntohs(addr.sin_port));
+    } else if (ntohs(addr.sin_port) == 80) {
+       printf("URL: http://%s/\n", inet_ntoa(addr.sin_addr));
+    } else {
+       printf("URL: http://%s:%d/\n",
+              inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
     }
 
     /*
      * Now construct an fd structure to hold it.
      */
-    f = new_fdstruct(fd, FD_LISTENER);
+    new_fdstruct(fd, FD_LISTENER);
 
     /*
      * Read from standard input, and treat EOF as a notification
@@ -589,6 +613,8 @@ void run_httpd(const void *t, int authmask, const struct httpd_config *dcfg,
 
            switch (fds[i].type) {
              case FD_CLIENT:
+               FD_SET_MAX(fds[i].fd, &rfds, maxfd);
+               break;
              case FD_LISTENER:
                FD_SET_MAX(fds[i].fd, &rfds, maxfd);
                break;