[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 07/16] generating results


MIME-Version: 1.0
Content-Transfer-Encoding: 8bit

From: arf20 <aruizfernandez05@xxxxxxxxx>

---
 config.c       |  10 +++---
 config.h       |   3 +-
 index.c        |   9 +++--
 index.htm.tmpl |  92 +++++++++++++++++++++++++++++++++++++++++++++----
 main.c         |  52 +++++++++++++++++++++++-----
 search         | Bin 47088 -> 47776 bytes
 search.cfg     |   3 ++
 7 files changed, 143 insertions(+), 26 deletions(-)

diff --git a/config.c b/config.c
index bc9eed6..d99cc2c 100644
--- a/config.c
+++ b/config.c
@@ -28,7 +28,7 @@
 #include <errno.h>
 
 unsigned short port = 0;
-char *tmpl_path = NULL, *root = NULL;
+char *tmpl_path = NULL, *root = NULL, *subdir = NULL;
 
 int
 config_load(const char *conf_path)
@@ -39,10 +39,6 @@ config_load(const char *conf_path)
         return -1;
     }
 
-    //fseek(cfgf , 0, SEEK_END);
-    //size_t cfgsize = ftell(cfgf);
-    //rewind(cfgf);
-
     printf("config:\n");
     
     char line[256];
@@ -75,6 +71,10 @@ config_load(const char *conf_path)
             value[strlen(value) - 1] = '\0';
             root = strdup(value);
             printf("\troot: %s\n", root);
+        } else if (strcmp(line, "subdir") == 0) {
+            value[strlen(value) - 1] = '\0';
+            subdir = strdup(value);
+            printf("\tsubdir: %s\n", subdir);
         } else {
             fprintf(stderr, "[config] unknown key: %s\n", line);
             continue;
diff --git a/config.h b/config.h
index 16e1ca5..b12f226 100644
--- a/config.h
+++ b/config.h
@@ -31,8 +31,7 @@
 
 /* config */
 extern unsigned short port;
-extern char *tmpl_path;
-extern char *root;
+extern char *tmpl_path, *root, *subdir;
 
 
 int config_load(const char *conf_path);
diff --git a/index.c b/index.c
index 57c05d7..3430178 100644
--- a/index.c
+++ b/index.c
@@ -171,6 +171,7 @@ index_recurse(size_t size, const char *dir, int examine, size_t rootlen)
 
         /* stat it */
         node_data_t *data = malloc(sizeof(node_data_t));
+        memset(data, 0, sizeof(node_data_t));
         data->name = strdup(de->d_name);
         data->path = strdup(&path[rootlen]);
         if (stat(path, &data->stat) < 0) {
@@ -182,11 +183,13 @@ index_recurse(size_t size, const char *dir, int examine, size_t rootlen)
 
         /* examine */
         if (examine) {
-            data->mime = magic_file(magic_cookie, path);
-            if (!data->mime)
+            const char *mime = magic_file(magic_cookie, path);
+            if (!mime) {
                 fprintf(stderr, "[index] error magic_file() %s: %s\n", path,
                     magic_error(magic_cookie));
-        }
+            } else 
+                data->mime = strdup(mime);
+        } 
 
         /* recurse */
         map_t *child = NULL;
diff --git a/index.htm.tmpl b/index.htm.tmpl
index fd21578..fdb1b58 100644
--- a/index.htm.tmpl
+++ b/index.htm.tmpl
@@ -5,10 +5,12 @@
         <link rel="stylesheet" type="text/css" href="https://arf20.com/style.css";>
         <title>ARFNET</title>
         <style>
+.searchform {
+    margin-bottom: 2em;
+}
+
 .box {
-    margin: auto;
     width: 50%;
-    padding-top: 20vh;
     min-width: 400px;
     display: block;
 }
@@ -34,6 +36,23 @@
     border: none;
 }
 
+.label {
+    display: inline-block;
+    width: 200px;
+}
+
+.collapse-title {
+    font-weight: bold;
+}
+
+.sort-left {
+    display: inline-block;
+}
+
+.sort-right {
+    display: inline-block;
+}
+
 .result {
     margin-left: 1em;
     margin-bottom: 1em;
@@ -45,9 +64,26 @@
     margin: 0;
 }
 
+.mime {
+    font-size: 10pt;
+    margin-left: 10pt;
+}
+
 .path {
     
 }
+
+.attrib {
+    float: right;
+}
+
+.size {
+
+}
+
+.time {
+    margin-left: 2em;
+}
 </style>
     </head>
 
@@ -59,12 +95,54 @@
         <main>
             <h2 class="center">Search</h2>
             <p>Search all of the ARFNET content fast</p>
-            <div class="box">
-                <form class="form-inline" action="/query" method="get">
+            <form class="searchform" action="/query" method="get">
+                <div class="box form-inline">
                     <input class="input" type="text" name="query" value="%s">
-                    <button type="submit">Search</button>
-                </form>
-            </div>
+                    <button type="submit">Search</button><br>
+                </div>
+                <div>
+                    <details>
+                        <summary class="collapse-title">Advanced</summary>
+                        <input type="radio" id="substr" name="type" value="substr">
+                        <label for="substr">substring</label>
+                        <input type="radio" id="substr_nocase" name="type" value="substr_nocase">
+                        <label for="substr_nocase">case insensitive substring</label>
+                        <input type="radio" id="exact" name="type" value="exact">
+                        <label for="exact">exact</label>
+                        <input type="radio" id="regex" name="type" value="regex">
+                        <label for="regex">regex</label>
+                    </details>
+                    <details>
+                        <summary class="collapse-title">Filtering</summary>
+                            <label class="label" for="mtime_start">Timeframe start</label>
+                            <input type="date" id="mtime_start" name="filter_mtime_start"><br>
+                            <label class="label" for="mtime_end">Timeframe end</label>
+                            <input type="date" id="mtime_end" name="filter_mtime_end"><br>
+                            <label class="label" for="size_start">Size lower bound</label>
+                            <input type="text" id="size_start" name="filter_size_start"><br>
+                            <label class="label" for="size_end">Size upper bound</label>
+                            <input type="text" id="size_end" name="filter_size_end"><br>
+                    </details>
+                    <details>
+                        <summary class="collapse-title">Sorting</summary>
+                        <div class="sort-left">
+                            <input type="radio" name="sort" id="name" value="name">
+                            <label for="name">name</label><br>
+                            <input type="radio" name="sort" id="time" value="time">
+                            <label for="time">time</label><br>
+                            <input type="radio" name="sort" id="size" value="size">
+                            <label for="size">size</label><br>
+                        </div>
+                        <div class="sort-right">
+                            <input type="radio" name="sort_dir" id="asc" value="asc">
+                            <label for="asc">ascending</label><br>
+                            <input type="radio" name="sort_dir" id="desc" value="desc">
+                            <label for="desc">descending</label><br>
+                        </div>
+                    </details>
+                </div>
+            </form>
+            <hr>
             %s
         </main>
     </body>
diff --git a/main.c b/main.c
index 9aa7e76..f3492aa 100644
--- a/main.c
+++ b/main.c
@@ -42,21 +42,48 @@ static char *index_format_template = NULL;
 static index_t g_index = NULL;
 
 static const char *result_html_template = 
-    "<div class=\"result\"><p class=\"name\">%s</p><a class=\"path\">%s</a></div>\n";
+    "<div class=\"result\">\n"
+        "<span class=\"name\">%s</span>""<super class=\"mime\">%s</super><br>\n"
+        "<a class=\"path\" href=\"%s\">%s</a><div class=\"attrib\"><span class=\"size\">%s</span><span class=\"time\">%s</span></div><br>\n"
+    "</div>\n";
 
+static const char *
+sizestr(size_t size)
+{
+    static char buf[32];
+    if (size < 1024)
+        snprintf(buf, 32, "%ld B", size);
+    else if (size < 1024LL * 1024LL)
+        snprintf(buf, 32, "%.2f KiB", (float)size/1024.f);
+    else if (size < 1024LL * 1024LL * 1024LL)
+        snprintf(buf, 32, "%.2f MiB", (float)size/(1024.f*1024.f));
+    else if (size < 1024LL * 1024LL * 1024LL * 1024LL)
+        snprintf(buf, 32, "%.2f GiB", (float)size/(1024.f*1024.f*1024.f));
+    else if (size < 1024LL * 1024LL * 1024LL * 1024LL * 1024LL)
+        snprintf(buf, 32, "%.2f TiB", (float)size/(1024.f*1024.f*1024.f*1024.f));
+    return buf;
+}
 
 static const char *
 generate_results_html(results_t *results)
 {
-    static char buff[65535];
+    static char buff[65535], timebuf[256], urlbuf[4096];
 
     char *pos = buff;
   
     for (int i = 0; i < results->size; i++) {
+        const node_data_t *data = results->results[i];
+        struct tm *tm_mtim = gmtime(&data->stat.st_mtim.tv_sec);
+        strftime(timebuf, 256, "%Y-%m-%d %H:%M:%S", tm_mtim);
+
+        snprintf(urlbuf, 4096, "%s%s", subdir, data->path);
+
         pos += snprintf(pos, 65535 - (pos - buff),
             result_html_template,
-            results->results[i]->name,
-            results->results[i]->path
+            data->name,
+            data->mime ? data->mime : "",
+            urlbuf, data->path,
+            sizestr(data->stat.st_size), timebuf
         );
     }
 
@@ -103,15 +130,22 @@ enum MHD_Result answer_to_connection(
         const char *query = MHD_lookup_connection_value(connection,
             MHD_GET_ARGUMENT_KIND, "query");
 
-        results_t *results = index_lookup(g_index, LOOKUP_SUBSTR, query);
+        results_t *results = NULL;
+        if (g_index)
+            results = index_lookup(g_index, LOOKUP_SUBSTR, query);
 
-        snprintf(buff, BUFF_SIZE, index_format_template, query,
-            generate_results_html(results));
+        if (results)
+            snprintf(buff, BUFF_SIZE, index_format_template, query,
+                generate_results_html(results));
+        else
+            snprintf(buff, BUFF_SIZE, index_format_template, query,
+                "indexing in progress... try again later");
 
         response = MHD_create_response_from_buffer(strlen(buff), (void*)buff,
             MHD_RESPMEM_PERSISTENT);
 
-        results_destroy(results);
+        if (results)
+            results_destroy(results);
 
         printf("%d\n", 200);
         ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
@@ -171,7 +205,7 @@ int main() {
 
     printf("[%s] [index] indexeding started...\n", timestr);
 
-    g_index = index_new(INIT_MAP_CAPACITY, root, 0);
+    g_index = index_new(INIT_MAP_CAPACITY, root, 1);
 
     time_now = time(NULL);
     tm_now = gmtime(&time_now);
diff --git a/search b/search
index e7e95765ddd82b1bffa504818b574659b8a45fe1..8cf64c1d562443614ea28150018d17315e22f96b 100755
GIT binary patch
delta 16847
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
Ef60wV7XSbN

delta 14996
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

diff --git a/search.cfg b/search.cfg
index b8110dd..b0eaed8 100644
--- a/search.cfg
+++ b/search.cfg
@@ -9,3 +9,6 @@ template=index.htm.tmpl
 # root
 root=/home/arf20/projects/arfminesweeper
 
+# http subdirectory for file links
+subdir=/files/
+
-- 
2.47.3


References:
[arfnet2-search PATCH 00/16] Pre-release deploymentarf20 <arf20@xxxxxxxxx>