]> git.seodisparate.com - c_simple_http/commitdiff
Impl. path-to-cache-filename, fixes to strip-path
authorStephen Seo <seo.disparate@gmail.com>
Mon, 23 Sep 2024 05:58:28 +0000 (14:58 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Mon, 23 Sep 2024 05:58:28 +0000 (14:58 +0900)
src/html_cache.c
src/http.c
src/test.c

index 7d04da4e155aff4658ae1f54f24a9041d58bf5f3..cbf5f1751edf21e091d395981a59f2c5b7a775cf 100644 (file)
 // OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
+// Standard library includes.
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
 // Third-party includes.
-//#include <SimpleArchiver/src/data_structures/linked_list.h>
+#include <SimpleArchiver/src/data_structures/linked_list.h>
+#include <SimpleArchiver/src/helpers.h>
+
+// Local includes.
+#include "http.h"
+#include "helpers.h"
 
 char *c_simple_http_path_to_cache_filename(const char *path) {
-//  SDArchiverLinkedList *parts = simple_archiver_list_init();
-  // TODO
+  __attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
+  char *stripped_path = c_simple_http_strip_path(path, strlen(path));
 
-  return 0;
+  if (!stripped_path) {
+    return NULL;
+  }
+
+  if (strcmp(stripped_path, "/") == 0) {
+    char *buf = malloc(5);
+    memcpy(buf, "ROOT", 5);
+    return buf;
+  }
+
+  __attribute__((cleanup(simple_archiver_list_free)))
+  SDArchiverLinkedList *parts = simple_archiver_list_init();
+
+  size_t idx = 0;
+  size_t prev_idx = 0;
+  const size_t path_len = strlen(stripped_path);
+  size_t size;
+
+  for (; idx < path_len && stripped_path[idx] != 0; ++idx) {
+    if (stripped_path[idx] == '/') {
+      size = idx - prev_idx + 1;
+      char *temp_buf = malloc(size);
+      memcpy(temp_buf, stripped_path + prev_idx, size - 1);
+      temp_buf[size - 1] = 0;
+      c_simple_http_add_string_part(parts, temp_buf, 0);
+      free(temp_buf);
+
+      temp_buf = malloc(5);
+      memcpy(temp_buf, "0x2F", 5);
+      c_simple_http_add_string_part(parts, temp_buf, 0);
+      free(temp_buf);
+
+      prev_idx = idx + 1;
+    }
+  }
+
+  if (idx > prev_idx) {
+    size = idx - prev_idx + 1;
+    char *temp_buf = malloc(size);
+    memcpy(temp_buf, stripped_path + prev_idx, size - 1);
+    temp_buf[size - 1] = 0;
+    c_simple_http_add_string_part(parts, temp_buf, 0);
+    free(temp_buf);
+  }
+
+  if (prev_idx == 0) {
+    return stripped_path;
+  } else {
+    return c_simple_http_combine_string_parts(parts);
+  }
 }
 
 int c_simple_http_cache_path(
index 08165dba0ef88d838348d0d34b9eeaf9ceeeb0c5..ceccbcd9ec4f148fd943c3436edfd62ec8368915 100644 (file)
 
 // Third party includes.
 #include <SimpleArchiver/src/helpers.h>
+#include <SimpleArchiver/src/data_structures/linked_list.h>
 
 // Local includes
+#include "SimpleArchiver/src/data_structures/priority_heap.h"
 #include "constants.h"
 #include "http_template.h"
 #include "helpers.h"
@@ -193,6 +195,14 @@ char *c_simple_http_request_response(
 }
 
 char *c_simple_http_strip_path(const char *path, size_t path_size) {
+  if (path_size == 1 && path[0] == '/') {
+    // Edge case: root path.
+    char *buf = malloc(2);
+    buf[0] = '/';
+    buf[1] = 0;
+    return buf;
+  }
+
   size_t idx = 0;
   for (; idx < path_size && path[idx] != 0; ++idx) {
     if (path[idx] == '?' || path[idx] == '#') {
@@ -204,7 +214,72 @@ char *c_simple_http_strip_path(const char *path, size_t path_size) {
   memcpy(stripped_path, path, idx);
   stripped_path[idx] = 0;
 
+  // Strip multiple '/' into one.
+  __attribute((cleanup(simple_archiver_list_free)))
+  SDArchiverLinkedList *parts = simple_archiver_list_init();
+
+  idx = 0;
+  size_t prev_idx = 0;
+  size_t size;
+  char *buf;
+  uint_fast8_t slash_visited = 0;
+
+  for (; stripped_path[idx] != 0; ++idx) {
+    if (stripped_path[idx] == '/') {
+      if (slash_visited) {
+        // Intentionally left blank.
+      } else {
+        slash_visited = 1;
+
+        if (idx > prev_idx) {
+          size = idx - prev_idx + 1;
+          buf = malloc(size);
+          memcpy(buf, stripped_path + prev_idx, size - 1);
+          buf[size - 1] = 0;
+
+          c_simple_http_add_string_part(parts, buf, 0);
+          free(buf);
+        }
+      }
+    } else {
+      if (slash_visited) {
+        buf = malloc(2);
+        buf[0] = '/';
+        buf[1] = 0;
+
+        c_simple_http_add_string_part(parts, buf, 0);
+        free(buf);
+
+        prev_idx = idx;
+      }
+
+      slash_visited = 0;
+    }
+  }
+
+  if (!slash_visited && idx > prev_idx) {
+    size = idx - prev_idx + 1;
+    buf = malloc(size);
+    memcpy(buf, stripped_path + prev_idx, size - 1);
+    buf[size - 1] = 0;
+
+    c_simple_http_add_string_part(parts, buf, 0);
+    free(buf);
+  } else if (slash_visited && prev_idx == 0) {
+    buf = malloc(2);
+    buf[0] = '/';
+    buf[1] = 0;
+
+    c_simple_http_add_string_part(parts, buf, 0);
+    free(buf);
+  }
+
+  free(stripped_path);
+
+  stripped_path = c_simple_http_combine_string_parts(parts);
+
   // Strip trailing '/'.
+  idx = strlen(stripped_path);
   while (idx-- > 1) {
     if (stripped_path[idx] == '/' || stripped_path[idx] == 0) {
       stripped_path[idx] = 0;
index afcc0c985217f34b3e2ce800180edfda13c839d4..86cc92af9275aa32a86e4de2d589a57ba2101e5c 100644 (file)
@@ -9,6 +9,7 @@
 #include "helpers.h"
 #include "http_template.h"
 #include "http.h"
+#include "html_cache.h"
 
 // Third party includes.
 #include <SimpleArchiver/src/helpers.h>
@@ -308,7 +309,7 @@ int main(void) {
     buf = c_simple_http_path_to_generated(
         "/", &config, &output_buf_size, &filenames_list);
     ASSERT_TRUE(buf != NULL);
-    printf("%s\n", buf);
+    //printf("%s\n", buf);
     ASSERT_TRUE(
       strcmp(
         buf,
@@ -374,7 +375,7 @@ int main(void) {
     buf = c_simple_http_path_to_generated(
         "/", &config, &output_buf_size, &filenames_list);
     ASSERT_TRUE(buf != NULL);
-    printf("%s\n", buf);
+    //printf("%s\n", buf);
     ASSERT_TRUE(
       strcmp(
         buf,
@@ -465,7 +466,7 @@ int main(void) {
     buf = c_simple_http_path_to_generated(
         "/", &config, &output_buf_size, &filenames_list);
     ASSERT_TRUE(buf != NULL);
-    printf("%s\n", buf);
+    //printf("%s\n", buf);
     ASSERT_TRUE(
       strcmp(
         buf,
@@ -519,28 +520,39 @@ int main(void) {
     free(stripped_path_buf);
 
     stripped_path_buf = c_simple_http_strip_path("/someurl/", 9);
+    //printf("stripped path: %s\n", stripped_path_buf);
     CHECK_STREQ(stripped_path_buf, "/someurl");
     free(stripped_path_buf);
 
     stripped_path_buf = c_simple_http_strip_path("/someurl/////", 13);
+    //printf("stripped path: %s\n", stripped_path_buf);
     CHECK_STREQ(stripped_path_buf, "/someurl");
     free(stripped_path_buf);
 
     stripped_path_buf = c_simple_http_strip_path("/someurl?key=value", 18);
+    //printf("stripped path: %s\n", stripped_path_buf);
     CHECK_STREQ(stripped_path_buf, "/someurl");
     free(stripped_path_buf);
 
     stripped_path_buf = c_simple_http_strip_path("/someurl#client_data", 20);
+    //printf("stripped path: %s\n", stripped_path_buf);
     CHECK_STREQ(stripped_path_buf, "/someurl");
     free(stripped_path_buf);
 
     stripped_path_buf = c_simple_http_strip_path("/someurl////?key=value", 22);
+    //printf("stripped path: %s\n", stripped_path_buf);
     CHECK_STREQ(stripped_path_buf, "/someurl");
     free(stripped_path_buf);
 
     stripped_path_buf = c_simple_http_strip_path("/someurl///#client_data", 23);
+    //printf("stripped path: %s\n", stripped_path_buf);
     CHECK_STREQ(stripped_path_buf, "/someurl");
     free(stripped_path_buf);
+
+    stripped_path_buf = c_simple_http_strip_path("/someurl/////inner", 18);
+    //printf("stripped path: %s\n", stripped_path_buf);
+    CHECK_STREQ(stripped_path_buf, "/someurl/inner");
+    free(stripped_path_buf);
   }
 
   // Test helpers.
@@ -558,6 +570,37 @@ int main(void) {
     ASSERT_TRUE(strcmp(buf, "one\ntwo\nthree\n") == 0);
   }
 
+  // Test html_cache.
+  {
+    char *ret = c_simple_http_path_to_cache_filename("/");
+    CHECK_TRUE(strcmp(ret, "ROOT") == 0);
+    free(ret);
+
+    ret = c_simple_http_path_to_cache_filename("////");
+    CHECK_TRUE(strcmp(ret, "ROOT") == 0);
+    free(ret);
+
+    ret = c_simple_http_path_to_cache_filename("/inner");
+    CHECK_TRUE(strcmp(ret, "0x2Finner") == 0);
+    free(ret);
+
+    ret = c_simple_http_path_to_cache_filename("/inner////");
+    CHECK_TRUE(strcmp(ret, "0x2Finner") == 0);
+    free(ret);
+
+    ret = c_simple_http_path_to_cache_filename("/outer/inner");
+    CHECK_TRUE(strcmp(ret, "0x2Fouter0x2Finner") == 0);
+    free(ret);
+
+    ret = c_simple_http_path_to_cache_filename("/outer/inner////");
+    CHECK_TRUE(strcmp(ret, "0x2Fouter0x2Finner") == 0);
+    free(ret);
+
+    ret = c_simple_http_path_to_cache_filename("/outer///inner");
+    CHECK_TRUE(strcmp(ret, "0x2Fouter0x2Finner") == 0);
+    free(ret);
+  }
+
   RETURN()
 }