guohui лет назад: 2
Родитель
Сommit
c9ddbe5905
4 измененных файлов с 124 добавлено и 17 удалено
  1. 104 0
      pro/mongoose/mongoose.c
  2. 3 0
      pro/mongoose/mongoose.h
  3. 16 16
      pro/src/appweb_handle.c
  4. 1 1
      pro/src/sys.c

+ 104 - 0
pro/mongoose/mongoose.c

@@ -2892,6 +2892,110 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
   }
 }
 
+
+static char *get_fname(const char *path)
+{
+    char *p=strrchr(path, '/');
+    if(p) {
+        return p+1;
+    }
+    return (char*)path;
+}
+void mg_http_serve_file2(struct mg_connection *c, struct mg_http_message *hm,
+                        const char *path,
+                        const struct mg_http_serve_opts *opts) {
+  char etag[64], tmp[MG_PATH_MAX];
+  struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
+  struct mg_fd *fd = NULL;
+  size_t size = 0;
+  time_t mtime = 0;
+  struct mg_str *inm = NULL;
+  struct mg_str mime = guess_content_type(mg_str(path), opts->mime_types);
+  bool gzip = false;
+
+  if (path != NULL) {
+    // If a browser sends us "Accept-Encoding: gzip", try to open .gz first
+    struct mg_str *ae = mg_http_get_header(hm, "Accept-Encoding");
+    if (ae != NULL) {
+      char *ae_ = mg_mprintf("%.*s", ae->len, ae->buf);
+      if (ae_ != NULL && strstr(ae_, "gzip") != NULL) {
+        mg_snprintf(tmp, sizeof(tmp), "%s.gz", path);
+        fd = mg_fs_open(fs, tmp, MG_FS_READ);
+        if (fd != NULL) gzip = true, path = tmp;
+      }
+      free(ae_);
+    }
+    // No luck opening .gz? Open what we've told to open
+    if (fd == NULL) fd = mg_fs_open(fs, path, MG_FS_READ);
+  }
+
+  // Failed to open, and page404 is configured? Open it, then
+  if (fd == NULL && opts->page404 != NULL) {
+    fd = mg_fs_open(fs, opts->page404, MG_FS_READ);
+    path = opts->page404;
+    mime = guess_content_type(mg_str(path), opts->mime_types);
+  }
+
+  if (fd == NULL || fs->st(path, &size, &mtime) == 0) {
+    mg_http_reply(c, 404, opts->extra_headers, "Not found\n");
+    mg_fs_close(fd);
+    // NOTE: mg_http_etag() call should go first!
+  } else if (mg_http_etag(etag, sizeof(etag), size, mtime) != NULL &&
+             (inm = mg_http_get_header(hm, "If-None-Match")) != NULL &&
+             mg_strcasecmp(*inm, mg_str(etag)) == 0) {
+    mg_fs_close(fd);
+    mg_http_reply(c, 304, opts->extra_headers, "");
+  } else {
+    int n, status = 200;
+    char range[100];
+    size_t r1 = 0, r2 = 0, cl = size;
+
+    // Handle Range header
+    struct mg_str *rh = mg_http_get_header(hm, "Range");
+    range[0] = '\0';
+    if (rh != NULL && (n = getrange(rh, &r1, &r2)) > 0) {
+      // If range is specified like "400-", set second limit to content len
+      if (n == 1) r2 = cl - 1;
+      if (r1 > r2 || r2 >= cl) {
+        status = 416;
+        cl = 0;
+        mg_snprintf(range, sizeof(range), "Content-Range: bytes */%lld\r\n",
+                    (int64_t) size);
+      } else {
+        status = 206;
+        cl = r2 - r1 + 1;
+        mg_snprintf(range, sizeof(range),
+                    "Content-Range: bytes %llu-%llu/%llu\r\n", (uint64_t) r1,
+                    (uint64_t) (r1 + cl - 1), (uint64_t) size);
+        fs->sk(fd->fd, r1);
+      }
+    }
+    mg_printf(c,
+              "HTTP/1.1 %d %s\r\n"
+              "Content-Type: %.*s\r\n"
+              "Content-Disposition: attachment;filename=%s\r\n"
+              "Etag: %s\r\n"
+              "Content-Length: %llu\r\n"
+              "%s%s%s\r\n",
+              status, mg_http_status_code_str(status), (int) mime.len, mime.buf,
+              get_fname(path),
+              etag, (uint64_t) cl, gzip ? "Content-Encoding: gzip\r\n" : "",
+              range, opts->extra_headers ? opts->extra_headers : "");
+    if (mg_strcasecmp(hm->method, mg_str("HEAD")) == 0) {
+      c->is_draining = 1;
+      c->is_resp = 0;
+      mg_fs_close(fd);
+    } else {
+      // Track to-be-sent content length at the end of c->data, aligned
+      size_t *clp = (size_t *) &c->data[(sizeof(c->data) - sizeof(size_t)) /
+                                        sizeof(size_t) * sizeof(size_t)];
+      c->pfn = static_cb;
+      c->pfn_data = fd;
+      *clp = cl;
+    }
+  }
+}
+
 struct printdirentrydata {
   struct mg_connection *c;
   struct mg_http_message *hm;

+ 3 - 0
pro/mongoose/mongoose.h

@@ -2123,6 +2123,9 @@ void mg_http_serve_dir(struct mg_connection *, struct mg_http_message *hm,
                        const struct mg_http_serve_opts *);
 void mg_http_serve_file(struct mg_connection *, struct mg_http_message *hm,
                         const char *path, const struct mg_http_serve_opts *);
+void mg_http_serve_file2(struct mg_connection *, struct mg_http_message *hm,
+                        const char *path, const struct mg_http_serve_opts *);
+
 void mg_http_reply(struct mg_connection *, int status_code, const char *headers,
                    const char *body_fmt, ...);
 int mg_http_reply2(struct mg_connection *c, int code, const char *headers,

+ 16 - 16
pro/src/appweb_handle.c

@@ -119,13 +119,13 @@ static int upload_file(void *conn, char *path)
 
     return r;
 }
-static int download_file(void *conn, char *path)
+static int download_file(void *conn, char *fpath)
 {
     mg_stream_t *s=(mg_stream_t*)conn;
     struct mg_http_message *hm = (struct mg_http_message *)s->ev_data;
 
-    struct mg_http_serve_opts opts = {.root_dir = NULL};
-    mg_http_serve_file(s->c, hm, path, &opts);
+    struct mg_http_serve_opts opts={.root_dir=NULL};
+    mg_http_serve_file2(s->c, hm, fpath, &opts);
 
     return 0;
 }
@@ -201,17 +201,16 @@ static int power_to_csv(char *path, status_data_t *data, int ftype)
 static int file_io(void *conn, int ftype, int io)
 {
     int r,flag=0;
-    char tmp[100],path[200];
+    char tmp[200],path[200];
     web_handle_t *wh=&webHandle;
     mg_stream_t *s=(mg_stream_t*)conn;
     struct mg_http_message *hm = (struct mg_http_message *)s->ev_data;
 
+    sys_get_path(tmp, "config.ini");
+    sys_get_path(path, INI_FILE_NAME);
     switch(ftype) {
         case FILE_SYS_CFG:
         {
-            sprintf(tmp, "config.ini");
-            sys_get_path(path, INI_FILE_NAME);
-
             if(io==FILE_IMPORT) {
                 r = upload_file(conn, tmp);
                 if(r==0) {
@@ -223,13 +222,14 @@ static int file_io(void *conn, int ftype, int io)
                         //clear some database table
                         exit(0); //restart smartPDU
                     }
+                    file_remove(tmp);
                 }
             }
             else {
                 file_copy(tmp, path);
                 download_file(conn, tmp);
+                file_remove(tmp);
             }
-            file_remove(tmp);
         }
         break;
 
@@ -272,11 +272,11 @@ static int file_io(void *conn, int ftype, int io)
                 //upload_file(path);
             }
             else {
-                sprintf(path, "%s.csv", "overall");
-                r = power_to_csv(path, &wh->stt, ftype);
+                char *ftmp="overall.csv";
+                r = power_to_csv(ftmp, &wh->stt, ftype);
                 if(r==0) {
-                    download_file(conn, path);
-                    file_remove(path);
+                    download_file(conn, ftmp);
+                    file_remove(ftmp);
                 }
             }
         }
@@ -288,11 +288,11 @@ static int file_io(void *conn, int ftype, int io)
                 //upload_file(path);
             }
             else {
-                sprintf(path, "%s.csv", "channel");
-                r = power_to_csv(path, &wh->stt, ftype);
+                char *ftmp="channel.csv";
+                r = power_to_csv(ftmp, &wh->stt, ftype);
                 if(r==0) {
-                    download_file(conn, path);
-                    file_remove(path);
+                    download_file(conn, ftmp);
+                    file_remove(ftmp);
                 }
             }
         }

+ 1 - 1
pro/src/sys.c

@@ -164,7 +164,7 @@ int sys_get_path(char *path, char *name)
     char *p = strrchr(path, '/');
     if(p && strlen(path)>1) {
         *p = 0;
-        if(p && strlen(name)>0) {
+        if(p && name && strlen(name)>0) {
             strcat(path, "/");
             strcat(path, name);
         }