|  | @@ -2350,7 +2350,8 @@ static pid_t spawn_process(struct mg_connection *conn, const char *prog,
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      if ((pid = fork()) == -1) {
 |  |      if ((pid = fork()) == -1) {
 | 
											
												
													
														|  |          /* Parent */
 |  |          /* Parent */
 | 
											
												
													
														|  | -        send_http_error(conn, 500, NULL, "fork(): %s", strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | 
 |  | +        send_http_error(conn, 500, NULL,
 | 
											
												
													
														|  | 
 |  | +            "Error: Creating CGI process\nfork(): %s", strerror(ERRNO));
 | 
											
												
													
														|  |      } else if (pid == 0) {
 |  |      } else if (pid == 0) {
 | 
											
												
													
														|  |          /* Child */
 |  |          /* Child */
 | 
											
												
													
														|  |          if (chdir(dir) != 0) {
 |  |          if (chdir(dir) != 0) {
 | 
											
										
											
												
													
														|  | @@ -3933,8 +3934,9 @@ static void handle_directory_request(struct mg_connection *conn,
 | 
											
												
													
														|  |      time_t curtime = time(NULL);
 |  |      time_t curtime = time(NULL);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      if (!scan_directory(conn, dir, &data, dir_scan_callback)) {
 |  |      if (!scan_directory(conn, dir, &data, dir_scan_callback)) {
 | 
											
												
													
														|  | -        send_http_error(conn, 500, "Cannot open directory",
 |  | 
 | 
											
												
													
														|  | -                        "Error: opendir(%s): %s", dir, strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | 
 |  | +        send_http_error(conn, 500, NULL,
 | 
											
												
													
														|  | 
 |  | +            "Error: Cannot open directory\nopendir(%s): %s",
 | 
											
												
													
														|  | 
 |  | +            dir, strerror(ERRNO));
 | 
											
												
													
														|  |          return;
 |  |          return;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -4080,7 +4082,8 @@ static void handle_static_file_request(struct mg_connection *conn, const char *p
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      if (!mg_fopen(conn, path, "rb", filep)) {
 |  |      if (!mg_fopen(conn, path, "rb", filep)) {
 | 
											
												
													
														|  |          send_http_error(conn, 500, NULL,
 |  |          send_http_error(conn, 500, NULL,
 | 
											
												
													
														|  | -                        "fopen(%s): %s", path, strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | 
 |  | +            "Error: Cannot open file\nfopen(%s): %s",
 | 
											
												
													
														|  | 
 |  | +            path, strerror(ERRNO));
 | 
											
												
													
														|  |          return;
 |  |          return;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -4094,7 +4097,8 @@ static void handle_static_file_request(struct mg_connection *conn, const char *p
 | 
											
												
													
														|  |          /* actually, range requests don't play well with a pre-gzipped
 |  |          /* actually, range requests don't play well with a pre-gzipped
 | 
											
												
													
														|  |             file (since the range is specified in the uncompressed space) */
 |  |             file (since the range is specified in the uncompressed space) */
 | 
											
												
													
														|  |          if (filep->gzipped) {
 |  |          if (filep->gzipped) {
 | 
											
												
													
														|  | -            send_http_error(conn, 501, NULL, "range requests in gzipped files are not supported");
 |  | 
 | 
											
												
													
														|  | 
 |  | +            send_http_error(conn, 501, NULL, "%s",
 | 
											
												
													
														|  | 
 |  | +                "Error: Range requests in gzipped files are not supported");
 | 
											
												
													
														|  |              mg_fclose(filep);
 |  |              mg_fclose(filep);
 | 
											
												
													
														|  |              return;
 |  |              return;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
										
											
												
													
														|  | @@ -4155,14 +4159,15 @@ void mg_send_file2(struct mg_connection *conn, const char *path, int timeout)
 | 
											
												
													
														|  |              if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")) {
 |  |              if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")) {
 | 
											
												
													
														|  |                  handle_directory_request(conn, path);
 |  |                  handle_directory_request(conn, path);
 | 
											
												
													
														|  |              } else {
 |  |              } else {
 | 
											
												
													
														|  | -                send_http_error(conn, 403, "Directory Listing Denied",
 |  | 
 | 
											
												
													
														|  | -                    "Directory listing denied");
 |  | 
 | 
											
												
													
														|  | 
 |  | +                send_http_error(conn, 403, NULL, "%s",
 | 
											
												
													
														|  | 
 |  | +                    "Error: Directory listing denied");
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |          } else {
 |  |          } else {
 | 
											
												
													
														|  |              handle_static_file_request(conn, path, &file);
 |  |              handle_static_file_request(conn, path, &file);
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      } else {
 |  |      } else {
 | 
											
												
													
														|  | -        send_http_error(conn, 404, NULL, "%s", "File not found");
 |  | 
 | 
											
												
													
														|  | 
 |  | +        send_http_error(conn, 404, NULL, "%s",
 | 
											
												
													
														|  | 
 |  | +            "Error: File not found");
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -4336,12 +4341,19 @@ static int forward_body_data(struct mg_connection *conn, FILE *fp,
 | 
											
												
													
														|  |      assert(fp != NULL);
 |  |      assert(fp != NULL);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      if (conn->content_len == -1) {
 |  |      if (conn->content_len == -1) {
 | 
											
												
													
														|  | -        send_http_error(conn, 411, NULL, "%s", "");
 |  | 
 | 
											
												
													
														|  | -    } else if (expect != NULL && mg_strcasecmp(expect, "100-continue")) {
 |  | 
 | 
											
												
													
														|  | -        send_http_error(conn, 417, NULL, "%s", "");
 |  | 
 | 
											
												
													
														|  | 
 |  | +        /* Content length is not specified by the client. */
 | 
											
												
													
														|  | 
 |  | +        send_http_error(conn, 411, NULL, "%s",
 | 
											
												
													
														|  | 
 |  | +            "Error: Client did not specify content length");
 | 
											
												
													
														|  | 
 |  | +    } else if ((expect != NULL) && (mg_strcasecmp(expect, "100-continue") != 0)) {
 | 
											
												
													
														|  | 
 |  | +        /* Client sent an "Expect: xyz" header and xyz is not 100-continue. */
 | 
											
												
													
														|  | 
 |  | +        send_http_error(conn, 417, NULL,
 | 
											
												
													
														|  | 
 |  | +            "Error: Can not fulfill expectation %s", expect);
 | 
											
												
													
														|  |      } else {
 |  |      } else {
 | 
											
												
													
														|  |          if (expect != NULL) {
 |  |          if (expect != NULL) {
 | 
											
												
													
														|  |              (void) mg_printf(conn, "%s", "HTTP/1.1 100 Continue\r\n\r\n");
 |  |              (void) mg_printf(conn, "%s", "HTTP/1.1 100 Continue\r\n\r\n");
 | 
											
												
													
														|  | 
 |  | +            conn->status_code = 100;
 | 
											
												
													
														|  | 
 |  | +        } else {
 | 
											
												
													
														|  | 
 |  | +            conn->status_code = 200;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |          buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len - conn->consumed_content;
 |  |          buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len - conn->consumed_content;
 | 
											
										
											
												
													
														|  | @@ -4376,6 +4388,7 @@ static int forward_body_data(struct mg_connection *conn, FILE *fp,
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |          /* Each error code path in this function must send an error */
 |  |          /* Each error code path in this function must send an error */
 | 
											
												
													
														|  |          if (!success) {
 |  |          if (!success) {
 | 
											
												
													
														|  | 
 |  | +            /* TODO: Maybe some data has already been sent. */
 | 
											
												
													
														|  |              send_http_error(conn, 500, NULL, "%s", "");
 |  |              send_http_error(conn, 500, NULL, "%s", "");
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
										
											
												
													
														|  | @@ -4589,14 +4602,14 @@ static void handle_cgi_request(struct mg_connection *conn, const char *prog)
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      if (pipe(fdin) != 0 || pipe(fdout) != 0) {
 |  |      if (pipe(fdin) != 0 || pipe(fdout) != 0) {
 | 
											
												
													
														|  |          send_http_error(conn, 500, NULL,
 |  |          send_http_error(conn, 500, NULL,
 | 
											
												
													
														|  | -                        "Cannot create CGI pipe: %s", strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | 
 |  | +            "Error: Cannot create CGI pipe: %s", strerror(ERRNO));
 | 
											
												
													
														|  |          goto done;
 |  |          goto done;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      pid = spawn_process(conn, p, blk.buf, blk.vars, fdin[0], fdout[1], dir);
 |  |      pid = spawn_process(conn, p, blk.buf, blk.vars, fdin[0], fdout[1], dir);
 | 
											
												
													
														|  |      if (pid == (pid_t) -1) {
 |  |      if (pid == (pid_t) -1) {
 | 
											
												
													
														|  |          send_http_error(conn, 500, NULL,
 |  |          send_http_error(conn, 500, NULL,
 | 
											
												
													
														|  | -                        "Cannot spawn CGI process [%s]: %s", prog, strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | 
 |  | +            "Error: Cannot spawn CGI process [%s]: %s", prog, strerror(ERRNO));
 | 
											
												
													
														|  |          goto done;
 |  |          goto done;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -4614,11 +4627,14 @@ static void handle_cgi_request(struct mg_connection *conn, const char *prog)
 | 
											
												
													
														|  |      (void) close(fdout[1]);
 |  |      (void) close(fdout[1]);
 | 
											
												
													
														|  |      fdin[0] = fdout[1] = -1;
 |  |      fdin[0] = fdout[1] = -1;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -    if ((in = fdopen(fdin[1], "wb")) == NULL ||
 |  | 
 | 
											
												
													
														|  | -        (out = fdopen(fdout[0], "rb")) == NULL) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    if ((in = fdopen(fdin[1], "wb")) == NULL) {
 | 
											
												
													
														|  | 
 |  | +        send_http_error(conn, 500, NULL,
 | 
											
												
													
														|  | 
 |  | +            "Error: CGI can not open fdin\nfopen: %s", strerror(ERRNO));
 | 
											
												
													
														|  | 
 |  | +        goto done;
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    if ((out = fdopen(fdout[0], "rb")) == NULL) {
 | 
											
												
													
														|  |          send_http_error(conn, 500, NULL,
 |  |          send_http_error(conn, 500, NULL,
 | 
											
												
													
														|  | -                        "fopen: %s", strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | 
 |  | +            "Error: CGI can not open fdout\nfopen: %s", strerror(ERRNO));
 | 
											
												
													
														|  |          goto done;
 |  |          goto done;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -4645,16 +4661,15 @@ static void handle_cgi_request(struct mg_connection *conn, const char *prog)
 | 
											
												
													
														|  |      buf = (char *)mg_malloc(buflen);
 |  |      buf = (char *)mg_malloc(buflen);
 | 
											
												
													
														|  |      if (buf == NULL) {
 |  |      if (buf == NULL) {
 | 
											
												
													
														|  |          send_http_error(conn, 500, NULL,
 |  |          send_http_error(conn, 500, NULL,
 | 
											
												
													
														|  | -                        "Not enough memory for buffer (%u bytes)",
 |  | 
 | 
											
												
													
														|  | -                        (unsigned int) buflen);
 |  | 
 | 
											
												
													
														|  | 
 |  | +            "Error: Not enough memory for CGI buffer (%u bytes)",
 | 
											
												
													
														|  | 
 |  | +            (unsigned int) buflen);
 | 
											
												
													
														|  |          goto done;
 |  |          goto done;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |      headers_len = read_request(out, conn, buf, (int) buflen, &data_len);
 |  |      headers_len = read_request(out, conn, buf, (int) buflen, &data_len);
 | 
											
												
													
														|  |      if (headers_len <= 0) {
 |  |      if (headers_len <= 0) {
 | 
											
												
													
														|  |          send_http_error(conn, 500, NULL,
 |  |          send_http_error(conn, 500, NULL,
 | 
											
												
													
														|  | -                        "CGI program sent malformed or too big (>%u bytes) "
 |  | 
 | 
											
												
													
														|  | -                        "HTTP headers: [%.*s]",
 |  | 
 | 
											
												
													
														|  | -                        (unsigned) buflen, data_len, buf);
 |  | 
 | 
											
												
													
														|  | 
 |  | +            "Error: CGI program sent malformed or too big (>%u bytes) HTTP headers: [%.*s]",
 | 
											
												
													
														|  | 
 |  | +            (unsigned) buflen, data_len, buf);
 | 
											
												
													
														|  |          goto done;
 |  |          goto done;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |      pbuf = buf;
 |  |      pbuf = buf;
 | 
											
										
											
												
													
														|  | @@ -4730,9 +4745,12 @@ done:
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  #endif /* !NO_CGI */
 |  |  #endif /* !NO_CGI */
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -/* For a given PUT path, create all intermediate subdirectories
 |  | 
 | 
											
												
													
														|  | -   for given path. Return 0 if the path itself is a directory,
 |  | 
 | 
											
												
													
														|  | -   or -1 on error, 1 if OK. */
 |  | 
 | 
											
												
													
														|  | 
 |  | +/* For a given PUT path, create all intermediate subdirectories.
 | 
											
												
													
														|  | 
 |  | +   Return  0  if the path itself is a directory.
 | 
											
												
													
														|  | 
 |  | +   Return  1  if the path leads to a file.
 | 
											
												
													
														|  | 
 |  | +   Return -1  for if the path is too long.
 | 
											
												
													
														|  | 
 |  | +   Return -2  if path can not be created.
 | 
											
												
													
														|  | 
 |  | +*/
 | 
											
												
													
														|  |  static int put_dir(struct mg_connection *conn, const char *path)
 |  |  static int put_dir(struct mg_connection *conn, const char *path)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |      char buf[PATH_MAX];
 |  |      char buf[PATH_MAX];
 | 
											
										
											
												
													
														|  | @@ -4743,6 +4761,7 @@ static int put_dir(struct mg_connection *conn, const char *path)
 | 
											
												
													
														|  |      for (s = p = path + 2; (p = strchr(s, '/')) != NULL; s = ++p) {
 |  |      for (s = p = path + 2; (p = strchr(s, '/')) != NULL; s = ++p) {
 | 
											
												
													
														|  |          len = (int)(p - path);
 |  |          len = (int)(p - path);
 | 
											
												
													
														|  |          if (len >= (int) sizeof(buf)) {
 |  |          if (len >= (int) sizeof(buf)) {
 | 
											
												
													
														|  | 
 |  | +            /* path too long */
 | 
											
												
													
														|  |              res = -1;
 |  |              res = -1;
 | 
											
												
													
														|  |              break;
 |  |              break;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
										
											
												
													
														|  | @@ -4752,7 +4771,8 @@ static int put_dir(struct mg_connection *conn, const char *path)
 | 
											
												
													
														|  |          /* Try to create intermediate directory */
 |  |          /* Try to create intermediate directory */
 | 
											
												
													
														|  |          DEBUG_TRACE("mkdir(%s)", buf);
 |  |          DEBUG_TRACE("mkdir(%s)", buf);
 | 
											
												
													
														|  |          if (!mg_stat(conn, buf, &file) && mg_mkdir(buf, 0755) != 0) {
 |  |          if (!mg_stat(conn, buf, &file) && mg_mkdir(buf, 0755) != 0) {
 | 
											
												
													
														|  | -            res = -1;
 |  | 
 | 
											
												
													
														|  | 
 |  | +            /* path does not exixt and can not be created */
 | 
											
												
													
														|  | 
 |  | +            res = -2;
 | 
											
												
													
														|  |              break;
 |  |              break;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -4772,6 +4792,8 @@ static void mkcol(struct mg_connection *conn, const char *path)
 | 
											
												
													
														|  |      char date[64];
 |  |      char date[64];
 | 
											
												
													
														|  |      time_t curtime = time(NULL);
 |  |      time_t curtime = time(NULL);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    /* TODO: Check the send_http_error situations in this function */
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |      memset(&de.file, 0, sizeof(de.file));
 |  |      memset(&de.file, 0, sizeof(de.file));
 | 
											
												
													
														|  |      if (!mg_stat(conn, path, &de.file)) {
 |  |      if (!mg_stat(conn, path, &de.file)) {
 | 
											
												
													
														|  |          mg_cry(conn, "%s: mg_stat(%s) failed: %s",
 |  |          mg_cry(conn, "%s: mg_stat(%s) failed: %s",
 | 
											
										
											
												
													
														|  | @@ -4780,14 +4802,14 @@ static void mkcol(struct mg_connection *conn, const char *path)
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      if (de.file.modification_time) {
 |  |      if (de.file.modification_time) {
 | 
											
												
													
														|  |          send_http_error(conn, 405, NULL,
 |  |          send_http_error(conn, 405, NULL,
 | 
											
												
													
														|  | -                        "mkcol(%s): %s", path, strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | 
 |  | +                        "Error: mkcol(%s): %s", path, strerror(ERRNO));
 | 
											
												
													
														|  |          return;
 |  |          return;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      body_len = conn->data_len - conn->request_len;
 |  |      body_len = conn->data_len - conn->request_len;
 | 
											
												
													
														|  |      if (body_len > 0) {
 |  |      if (body_len > 0) {
 | 
											
												
													
														|  |          send_http_error(conn, 415, NULL,
 |  |          send_http_error(conn, 415, NULL,
 | 
											
												
													
														|  | -                        "mkcol(%s): %s", path, strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | 
 |  | +                        "Error: mkcol(%s): %s", path, strerror(ERRNO));
 | 
											
												
													
														|  |          return;
 |  |          return;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -4801,13 +4823,13 @@ static void mkcol(struct mg_connection *conn, const char *path)
 | 
											
												
													
														|  |      } else if (rc == -1) {
 |  |      } else if (rc == -1) {
 | 
											
												
													
														|  |          if (errno == EEXIST)
 |  |          if (errno == EEXIST)
 | 
											
												
													
														|  |              send_http_error(conn, 405, NULL,
 |  |              send_http_error(conn, 405, NULL,
 | 
											
												
													
														|  | -                            "mkcol(%s): %s", path, strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | 
 |  | +                            "Error:mkcol(%s): %s", path, strerror(ERRNO));
 | 
											
												
													
														|  |          else if (errno == EACCES)
 |  |          else if (errno == EACCES)
 | 
											
												
													
														|  |              send_http_error(conn, 403, NULL,
 |  |              send_http_error(conn, 403, NULL,
 | 
											
												
													
														|  | -                            "mkcol(%s): %s", path, strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | 
 |  | +                            "Error: mkcol(%s): %s", path, strerror(ERRNO));
 | 
											
												
													
														|  |          else if(errno == ENOENT)
 |  |          else if(errno == ENOENT)
 | 
											
												
													
														|  |              send_http_error(conn, 409, NULL,
 |  |              send_http_error(conn, 409, NULL,
 | 
											
												
													
														|  | -                            "mkcol(%s): %s", path, strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | 
 |  | +                            "Error: mkcol(%s): %s", path, strerror(ERRNO));
 | 
											
												
													
														|  |          else
 |  |          else
 | 
											
												
													
														|  |              send_http_error(conn, 500, NULL,
 |  |              send_http_error(conn, 500, NULL,
 | 
											
												
													
														|  |                              "fopen(%s): %s", path, strerror(ERRNO));
 |  |                              "fopen(%s): %s", path, strerror(ERRNO));
 | 
											
										
											
												
													
														|  | @@ -4824,58 +4846,101 @@ static void put_file(struct mg_connection *conn, const char *path)
 | 
											
												
													
														|  |      time_t curtime = time(NULL);
 |  |      time_t curtime = time(NULL);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      conn->status_code = mg_stat(conn, path, &file) ? 200 : 201;
 |  |      conn->status_code = mg_stat(conn, path, &file) ? 200 : 201;
 | 
											
												
													
														|  | 
 |  | +    rc = put_dir(conn, path);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    if ((rc = put_dir(conn, path)) == 0) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    if (rc == 0) {
 | 
											
												
													
														|  | 
 |  | +        /* put_dir returns 0 if path is a directory */
 | 
											
												
													
														|  |          gmt_time_string(date, sizeof(date), &curtime);
 |  |          gmt_time_string(date, sizeof(date), &curtime);
 | 
											
												
													
														|  |          mg_printf(conn, "HTTP/1.1 %d OK\r\nDate: %s\r\nContent-Length: 0\r\nConnection: %s\r\n\r\n",
 |  |          mg_printf(conn, "HTTP/1.1 %d OK\r\nDate: %s\r\nContent-Length: 0\r\nConnection: %s\r\n\r\n",
 | 
											
												
													
														|  |                    conn->status_code, date, suggest_connection_header(conn));
 |  |                    conn->status_code, date, suggest_connection_header(conn));
 | 
											
												
													
														|  | -    } else if (rc == -1) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        /* Request to create a directory has been fulfilled successfully.
 | 
											
												
													
														|  | 
 |  | +           No need to put a file. */
 | 
											
												
													
														|  | 
 |  | +        return;
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    if (rc == -1) {
 | 
											
												
													
														|  | 
 |  | +        /* put_dir returns -1 if the path is too long */
 | 
											
												
													
														|  | 
 |  | +        send_http_error(conn, 414, NULL,
 | 
											
												
													
														|  | 
 |  | +            "Error: Path too long\nput_dir(%s): %s", path, strerror(ERRNO));
 | 
											
												
													
														|  | 
 |  | +        return;
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    if (rc == -2) {
 | 
											
												
													
														|  | 
 |  | +        /* put_dir returns -2 if the directory can not be created */
 | 
											
												
													
														|  |          send_http_error(conn, 500, NULL,
 |  |          send_http_error(conn, 500, NULL,
 | 
											
												
													
														|  | -                        "put_dir(%s): %s", path, strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | -    } else if (!mg_fopen(conn, path, "wb+", &file) || file.fp == NULL) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +            "Error: Can not create directory\nput_dir(%s): %s", path, strerror(ERRNO));
 | 
											
												
													
														|  | 
 |  | +        return;
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    /* TODO: If the file exists and is read only, return 403 or 405 */
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    /* A file should be created or overwritten. */
 | 
											
												
													
														|  | 
 |  | +    if (!mg_fopen(conn, path, "wb+", &file) || file.fp == NULL) {
 | 
											
												
													
														|  |          mg_fclose(&file);
 |  |          mg_fclose(&file);
 | 
											
												
													
														|  |          send_http_error(conn, 500, NULL,
 |  |          send_http_error(conn, 500, NULL,
 | 
											
												
													
														|  | -                        "fopen(%s): %s", path, strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | -    } else {
 |  | 
 | 
											
												
													
														|  | -        fclose_on_exec(&file, conn);
 |  | 
 | 
											
												
													
														|  | -        range = mg_get_header(conn, "Content-Range");
 |  | 
 | 
											
												
													
														|  | -        r1 = r2 = 0;
 |  | 
 | 
											
												
													
														|  | -        if (range != NULL && parse_range_header(range, &r1, &r2) > 0) {
 |  | 
 | 
											
												
													
														|  | -            conn->status_code = 206;
 |  | 
 | 
											
												
													
														|  | -            fseeko(file.fp, r1, SEEK_SET);
 |  | 
 | 
											
												
													
														|  | -        }
 |  | 
 | 
											
												
													
														|  | -        if (!forward_body_data(conn, file.fp, INVALID_SOCKET, NULL)) {
 |  | 
 | 
											
												
													
														|  | -            conn->status_code = 500;
 |  | 
 | 
											
												
													
														|  | -        }
 |  | 
 | 
											
												
													
														|  | -        gmt_time_string(date, sizeof(date), &curtime);
 |  | 
 | 
											
												
													
														|  | -        mg_printf(conn, "HTTP/1.1 %d OK\r\nDate: %s\r\nContent-Length: 0\r\nConnection: %s\r\n\r\n",
 |  | 
 | 
											
												
													
														|  | -                  conn->status_code, date, suggest_connection_header(conn));
 |  | 
 | 
											
												
													
														|  | -        mg_fclose(&file);
 |  | 
 | 
											
												
													
														|  | 
 |  | +            "Error: Can not create file\nfopen(%s): %s", path, strerror(ERRNO));
 | 
											
												
													
														|  | 
 |  | +        return;
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    fclose_on_exec(&file, conn);
 | 
											
												
													
														|  | 
 |  | +    range = mg_get_header(conn, "Content-Range");
 | 
											
												
													
														|  | 
 |  | +    r1 = r2 = 0;
 | 
											
												
													
														|  | 
 |  | +    if (range != NULL && parse_range_header(range, &r1, &r2) > 0) {
 | 
											
												
													
														|  | 
 |  | +        conn->status_code = 206; /* Partial content */
 | 
											
												
													
														|  | 
 |  | +        fseeko(file.fp, r1, SEEK_SET);
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    if (!forward_body_data(conn, file.fp, INVALID_SOCKET, NULL)) {
 | 
											
												
													
														|  | 
 |  | +        /* forward_body_data failed.
 | 
											
												
													
														|  | 
 |  | +           The error code has already been sent to the client,
 | 
											
												
													
														|  | 
 |  | +           and conn->status_code is already set. */
 | 
											
												
													
														|  | 
 |  | +        return;
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    gmt_time_string(date, sizeof(date), &curtime);
 | 
											
												
													
														|  | 
 |  | +    mg_printf(conn, "HTTP/1.1 %d %s\r\n"
 | 
											
												
													
														|  | 
 |  | +                    "Date: %s\r\n"
 | 
											
												
													
														|  | 
 |  | +                    "Content-Length: 0\r\n"
 | 
											
												
													
														|  | 
 |  | +                    "Connection: %s\r\n\r\n",
 | 
											
												
													
														|  | 
 |  | +              conn->status_code, mg_get_response_code_text(conn->status_code, NULL),
 | 
											
												
													
														|  | 
 |  | +              date,
 | 
											
												
													
														|  | 
 |  | +              suggest_connection_header(conn)
 | 
											
												
													
														|  | 
 |  | +              );
 | 
											
												
													
														|  | 
 |  | +    mg_fclose(&file);
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  static void delete_file(struct mg_connection *conn, const char *path)
 |  |  static void delete_file(struct mg_connection *conn, const char *path)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |      struct de de;
 |  |      struct de de;
 | 
											
												
													
														|  |      memset(&de.file, 0, sizeof(de.file));
 |  |      memset(&de.file, 0, sizeof(de.file));
 | 
											
												
													
														|  | -    if(!mg_stat(conn, path, &de.file)) {
 |  | 
 | 
											
												
													
														|  | -        send_http_error(conn, 404, NULL, "%s", "File not found");
 |  | 
 | 
											
												
													
														|  | 
 |  | +    if (!mg_stat(conn, path, &de.file)) {
 | 
											
												
													
														|  | 
 |  | +        /* mg_stat returns 0 if the file does not exist */
 | 
											
												
													
														|  | 
 |  | +        send_http_error(conn, 404, NULL,
 | 
											
												
													
														|  | 
 |  | +            "Error: Cannot delete file\nFile %s not found", path);
 | 
											
												
													
														|  |      } else {
 |  |      } else {
 | 
											
												
													
														|  | -        if(de.file.modification_time) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +        if (de.file.modification_time) {
 | 
											
												
													
														|  |              if(de.file.is_directory) {
 |  |              if(de.file.is_directory) {
 | 
											
												
													
														|  |                  remove_directory(conn, path);
 |  |                  remove_directory(conn, path);
 | 
											
												
													
														|  | 
 |  | +                /* Delete successful. (Do not send content for 204) */
 | 
											
												
													
														|  |                  send_http_error(conn, 204, NULL, "%s", "");
 |  |                  send_http_error(conn, 204, NULL, "%s", "");
 | 
											
												
													
														|  |              } else if (mg_remove(path) == 0) {
 |  |              } else if (mg_remove(path) == 0) {
 | 
											
												
													
														|  | 
 |  | +                /* Delete successful. (Do not send content for 204) */
 | 
											
												
													
														|  |                  send_http_error(conn, 204, NULL, "%s", "");
 |  |                  send_http_error(conn, 204, NULL, "%s", "");
 | 
											
												
													
														|  |              } else {
 |  |              } else {
 | 
											
												
													
														|  | -                send_http_error(conn, 423, NULL, "remove(%s): %s", path,
 |  | 
 | 
											
												
													
														|  | -                    strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | 
 |  | +                /* Delete not successful (file locked). */
 | 
											
												
													
														|  | 
 |  | +                send_http_error(conn, 423, NULL,
 | 
											
												
													
														|  | 
 |  | +                    "Error: Cannot delete file\nremove(%s): %s", path, strerror(ERRNO));
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |          } else {
 |  |          } else {
 | 
											
												
													
														|  | -            send_http_error(conn, 500, NULL, "remove(%s): %s", path,
 |  | 
 | 
											
												
													
														|  | -                strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | 
 |  | +            /* mg_stat returns != 0 and modification_time == 0
 | 
											
												
													
														|  | 
 |  | +               if the file is in memory */
 | 
											
												
													
														|  | 
 |  | +            send_http_error(conn, 405, NULL,
 | 
											
												
													
														|  | 
 |  | +                "Error: Delete not possible\nDeleting %s is not supported", path);
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    /* TODO: put and delete should value the read only flag of files and return 403 */
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  static void send_ssi_file(struct mg_connection *, const char *,
 |  |  static void send_ssi_file(struct mg_connection *, const char *,
 | 
											
										
											
												
													
														|  | @@ -5027,9 +5092,8 @@ static void send_ssi_file(struct mg_connection *conn, const char *path,
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  static void handle_ssi_file_request(struct mg_connection *conn,
 |  |  static void handle_ssi_file_request(struct mg_connection *conn,
 | 
											
												
													
														|  | -                                    const char *path)
 |  | 
 | 
											
												
													
														|  | 
 |  | +                                    const char *path, struct file *filep)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  | -    struct file file = STRUCT_FILE_INITIALIZER;
 |  | 
 | 
											
												
													
														|  |      char date[64];
 |  |      char date[64];
 | 
											
												
													
														|  |      time_t curtime = time(NULL);
 |  |      time_t curtime = time(NULL);
 | 
											
												
													
														|  |      const char *cors1, *cors2, *cors3;
 |  |      const char *cors1, *cors2, *cors3;
 | 
											
										
											
												
													
														|  | @@ -5043,13 +5107,15 @@ static void handle_ssi_file_request(struct mg_connection *conn,
 | 
											
												
													
														|  |          cors1 = cors2 = cors3 = "";
 |  |          cors1 = cors2 = cors3 = "";
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    if (!mg_fopen(conn, path, "rb", &file)) {
 |  | 
 | 
											
												
													
														|  | -        send_http_error(conn, 500, NULL, "fopen(%s): %s", path,
 |  | 
 | 
											
												
													
														|  | -                        strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | 
 |  | +    if (!mg_fopen(conn, path, "rb", filep)) {
 | 
											
												
													
														|  | 
 |  | +        /* File exists (precondition for calling this function),
 | 
											
												
													
														|  | 
 |  | +           but can not be opened by the server. */
 | 
											
												
													
														|  | 
 |  | +        send_http_error(conn, 500, NULL,
 | 
											
												
													
														|  | 
 |  | +            "Error: Cannot read file\nfopen(%s): %s", path, strerror(ERRNO));
 | 
											
												
													
														|  |      } else {
 |  |      } else {
 | 
											
												
													
														|  |          conn->must_close = 1;
 |  |          conn->must_close = 1;
 | 
											
												
													
														|  |          gmt_time_string(date, sizeof(date), &curtime);
 |  |          gmt_time_string(date, sizeof(date), &curtime);
 | 
											
												
													
														|  | -        fclose_on_exec(&file, conn);
 |  | 
 | 
											
												
													
														|  | 
 |  | +        fclose_on_exec(filep, conn);
 | 
											
												
													
														|  |          mg_printf(conn, "HTTP/1.1 200 OK\r\n"
 |  |          mg_printf(conn, "HTTP/1.1 200 OK\r\n"
 | 
											
												
													
														|  |                          "%s%s%s"
 |  |                          "%s%s%s"
 | 
											
												
													
														|  |                          "Date: %s\r\n"
 |  |                          "Date: %s\r\n"
 | 
											
										
											
												
													
														|  | @@ -5057,8 +5123,8 @@ static void handle_ssi_file_request(struct mg_connection *conn,
 | 
											
												
													
														|  |                          "Connection: %s\r\n\r\n",
 |  |                          "Connection: %s\r\n\r\n",
 | 
											
												
													
														|  |                          cors1, cors2, cors3,
 |  |                          cors1, cors2, cors3,
 | 
											
												
													
														|  |                          date, suggest_connection_header(conn));
 |  |                          date, suggest_connection_header(conn));
 | 
											
												
													
														|  | -        send_ssi_file(conn, path, &file, 0);
 |  | 
 | 
											
												
													
														|  | -        mg_fclose(&file);
 |  | 
 | 
											
												
													
														|  | 
 |  | +        send_ssi_file(conn, path, filep, 0);
 | 
											
												
													
														|  | 
 |  | +        mg_fclose(filep);
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -5596,7 +5662,7 @@ static void handle_websocket_request(struct mg_connection *conn, const char *pat
 | 
											
												
													
														|  |  #endif
 |  |  #endif
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      if (version == NULL || strcmp(version, "13") != 0) {
 |  |      if (version == NULL || strcmp(version, "13") != 0) {
 | 
											
												
													
														|  | -        send_http_error(conn, 426, "Upgrade Required", "%s", "Upgrade Required");
 |  | 
 | 
											
												
													
														|  | 
 |  | +        send_http_error(conn, 426, NULL, "%s", "Protocol upgrade required");
 | 
											
												
													
														|  |      } else if (conn->ctx->callbacks.websocket_connect != NULL &&
 |  |      } else if (conn->ctx->callbacks.websocket_connect != NULL &&
 | 
											
												
													
														|  |                 conn->ctx->callbacks.websocket_connect(conn) != 0) {
 |  |                 conn->ctx->callbacks.websocket_connect(conn) != 0) {
 | 
											
												
													
														|  |          /* C callback has returned non-zero, do not proceed with handshake. */
 |  |          /* C callback has returned non-zero, do not proceed with handshake. */
 | 
											
										
											
												
													
														|  | @@ -6036,7 +6102,10 @@ static void handle_request(struct mg_connection *conn)
 | 
											
												
													
														|  |          if (ssl_index >= 0) {
 |  |          if (ssl_index >= 0) {
 | 
											
												
													
														|  |              redirect_to_https_port(conn, ssl_index);
 |  |              redirect_to_https_port(conn, ssl_index);
 | 
											
												
													
														|  |          } else {
 |  |          } else {
 | 
											
												
													
														|  | -            send_http_error(conn, 500, NULL, "%s", "SSL forward not configured properly");
 |  | 
 | 
											
												
													
														|  | 
 |  | +            /* A http to https forward port has been specified,
 | 
											
												
													
														|  | 
 |  | +               but no https port to forward to. */
 | 
											
												
													
														|  | 
 |  | +            send_http_error(conn, 503, NULL, "%s",
 | 
											
												
													
														|  | 
 |  | +                "Error: SSL forward not configured properly");
 | 
											
												
													
														|  |              mg_cry(conn, "Can not redirect to SSL, no SSL port available");
 |  |              mg_cry(conn, "Can not redirect to SSL, no SSL port available");
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |          return;
 |  |          return;
 | 
											
										
											
												
													
														|  | @@ -6081,8 +6150,10 @@ static void handle_request(struct mg_connection *conn)
 | 
											
												
													
														|  |  #else
 |  |  #else
 | 
											
												
													
														|  |          if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
 |  |          if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
 | 
											
												
													
														|  |  #endif
 |  |  #endif
 | 
											
												
													
														|  | -            /* no real files -> no PUT/DELETE */
 |  | 
 | 
											
												
													
														|  | -            send_http_error(conn, 405, NULL, "%s", "Method Not Allowed");
 |  | 
 | 
											
												
													
														|  | 
 |  | +            /* This server does not have any real files, thus the
 | 
											
												
													
														|  | 
 |  | +               PUT/DELETE methods are not valid. */
 | 
											
												
													
														|  | 
 |  | +            send_http_error(conn, 405, NULL,
 | 
											
												
													
														|  | 
 |  | +                "%s method not allowed", conn->request_info.request_method);
 | 
											
												
													
														|  |              return;
 |  |              return;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -6121,13 +6192,13 @@ static void handle_request(struct mg_connection *conn)
 | 
											
												
													
														|  |  #if defined(NO_FILES)
 |  |  #if defined(NO_FILES)
 | 
											
												
													
														|  |      /* 9a. In case the server uses only callbacks, this uri is unknown.
 |  |      /* 9a. In case the server uses only callbacks, this uri is unknown.
 | 
											
												
													
														|  |         Then, all request handling ends here. */
 |  |         Then, all request handling ends here. */
 | 
											
												
													
														|  | -    send_http_error(conn, 404, NULL, "Not Found");
 |  | 
 | 
											
												
													
														|  | 
 |  | +    send_http_error(conn, 404, NULL, "%s", "Not Found");
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  #else
 |  |  #else
 | 
											
												
													
														|  |      /* 9b. This request is either for a static file or resource handled
 |  |      /* 9b. This request is either for a static file or resource handled
 | 
											
												
													
														|  |         by a script file. Thus, a DOCUMENT_ROOT must exist. */
 |  |         by a script file. Thus, a DOCUMENT_ROOT must exist. */
 | 
											
												
													
														|  |      if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
 |  |      if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
 | 
											
												
													
														|  | -        send_http_error(conn, 404, NULL, "Not Found");
 |  | 
 | 
											
												
													
														|  | 
 |  | +        send_http_error(conn, 404, NULL, "%s", "Not Found");
 | 
											
												
													
														|  |          return;
 |  |          return;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -6155,14 +6226,15 @@ static void handle_request(struct mg_connection *conn)
 | 
											
												
													
														|  |              return;
 |  |              return;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |          /* 11.4. should never reach this point */
 |  |          /* 11.4. should never reach this point */
 | 
											
												
													
														|  | -        send_http_error(conn, 405, NULL, "%s", "Method Not Allowed");
 |  | 
 | 
											
												
													
														|  | 
 |  | +        send_http_error(conn, 405, NULL,
 | 
											
												
													
														|  | 
 |  | +            "%s method not allowed", conn->request_info.request_method);
 | 
											
												
													
														|  |          return;
 |  |          return;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      /* 11. File does not exist, or it was configured that it should be hidden */
 |  |      /* 11. File does not exist, or it was configured that it should be hidden */
 | 
											
												
													
														|  |      if (((file.membuf == NULL) && (file.modification_time == (time_t) 0)) ||
 |  |      if (((file.membuf == NULL) && (file.modification_time == (time_t) 0)) ||
 | 
											
												
													
														|  |          (must_hide_file(conn, path))) {
 |  |          (must_hide_file(conn, path))) {
 | 
											
												
													
														|  | -        send_http_error(conn, 404, NULL, "%s", "File not found");
 |  | 
 | 
											
												
													
														|  | 
 |  | +        send_http_error(conn, 404, NULL, "%s", "Not found");
 | 
											
												
													
														|  |          return;
 |  |          return;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -6195,7 +6267,8 @@ static void handle_request(struct mg_connection *conn)
 | 
											
												
													
														|  |      /* 13.3. everything but GET and HEAD (e.g. POST) */
 |  |      /* 13.3. everything but GET and HEAD (e.g. POST) */
 | 
											
												
													
														|  |      if (!strcmp(ri->request_method, "GET") &&
 |  |      if (!strcmp(ri->request_method, "GET") &&
 | 
											
												
													
														|  |          !strcmp(ri->request_method, "HEAD")) {
 |  |          !strcmp(ri->request_method, "HEAD")) {
 | 
											
												
													
														|  | -        send_http_error(conn, 405, NULL, "%s", "Method Not Allowed");
 |  | 
 | 
											
												
													
														|  | 
 |  | +        send_http_error(conn, 405, NULL,
 | 
											
												
													
														|  | 
 |  | +            "%s method not allowed", conn->request_info.request_method);
 | 
											
												
													
														|  |          return;
 |  |          return;
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -6210,8 +6283,8 @@ static void handle_request(struct mg_connection *conn)
 | 
											
												
													
														|  |              if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")) {
 |  |              if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")) {
 | 
											
												
													
														|  |                  handle_directory_request(conn, path);
 |  |                  handle_directory_request(conn, path);
 | 
											
												
													
														|  |              } else {
 |  |              } else {
 | 
											
												
													
														|  | -                send_http_error(conn, 403, "Directory Listing Denied",
 |  | 
 | 
											
												
													
														|  | -                                "%s", "Directory listing denied");
 |  | 
 | 
											
												
													
														|  | 
 |  | +                send_http_error(conn, 403, NULL, "%s",
 | 
											
												
													
														|  | 
 |  | +                    "Error: Directory listing denied");
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |              return;
 |  |              return;
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
										
											
												
													
														|  | @@ -6252,8 +6325,9 @@ static void handle_file_based_request(struct mg_connection *conn, const char *pa
 | 
											
												
													
														|  |      } else if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
 |  |      } else if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
 | 
											
												
													
														|  |                              (int)strlen(conn->ctx->config[SSI_EXTENSIONS]),
 |  |                              (int)strlen(conn->ctx->config[SSI_EXTENSIONS]),
 | 
											
												
													
														|  |                              path) > 0) {
 |  |                              path) > 0) {
 | 
											
												
													
														|  | -        handle_ssi_file_request(conn, path);
 |  | 
 | 
											
												
													
														|  | 
 |  | +        handle_ssi_file_request(conn, path, file);
 | 
											
												
													
														|  |      } else if ((!conn->in_error_handler) && is_not_modified(conn, file)) {
 |  |      } else if ((!conn->in_error_handler) && is_not_modified(conn, file)) {
 | 
											
												
													
														|  | 
 |  | +        /* Send 304 "Not Modified" - this must not send any body data */
 | 
											
												
													
														|  |          send_http_error(conn, 304, NULL, "%s", "");
 |  |          send_http_error(conn, 304, NULL, "%s", "");
 | 
											
												
													
														|  |      } else {
 |  |      } else {
 | 
											
												
													
														|  |          handle_static_file_request(conn, path, file);
 |  |          handle_static_file_request(conn, path, file);
 | 
											
										
											
												
													
														|  | @@ -7085,7 +7159,10 @@ static void process_new_connection(struct mg_connection *conn)
 | 
											
												
													
														|  |      conn->data_len = 0;
 |  |      conn->data_len = 0;
 | 
											
												
													
														|  |      do {
 |  |      do {
 | 
											
												
													
														|  |          if (!getreq(conn, ebuf, sizeof(ebuf), TIMEOUT_INFINITE)) {
 |  |          if (!getreq(conn, ebuf, sizeof(ebuf), TIMEOUT_INFINITE)) {
 | 
											
												
													
														|  | -            send_http_error(conn, 500, NULL, "%s", ebuf);
 |  | 
 | 
											
												
													
														|  | 
 |  | +            /* The request sent by the client could not be understood by the server,
 | 
											
												
													
														|  | 
 |  | +               or it was incomplete or a timeout. Send an error message and close
 | 
											
												
													
														|  | 
 |  | +               the connection. */
 | 
											
												
													
														|  | 
 |  | +            send_http_error(conn, 400, NULL, "%s", ebuf);
 | 
											
												
													
														|  |              conn->must_close = 1;
 |  |              conn->must_close = 1;
 | 
											
												
													
														|  |          } else if (!is_valid_uri(conn->request_info.uri)) {
 |  |          } else if (!is_valid_uri(conn->request_info.uri)) {
 | 
											
												
													
														|  |              snprintf(ebuf, sizeof(ebuf), "Invalid URI: [%s]", ri->uri);
 |  |              snprintf(ebuf, sizeof(ebuf), "Invalid URI: [%s]", ri->uri);
 |