Commit 377a06f34c141c99d3392d368d89aca86346e00f

Thomas de Grivel 2025-01-30T15:40:00

wip

diff --git a/README.md b/README.md
index 625ed2a..652844a 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,12 @@
-# KC3 v0.1.14
+# KC3 v0.1.15
 
 KC3 is a programming language with meta-programmation and a graph
 database embedded into the language. It aims to be the language
 for semantic programming, and programming the semantic web.
 
-This is a stable release, for the development branch see
-[the KC3 git repository master branch](https://git.kmx.io/kc3-lang/kc3).
+This is a development branch see
+[KC3 v0.1.14](https://git.kmx.io/kc3-lang/kc3/_tree/v0.1.14)
+for a stable release.
 
 KC3 is currently a programming language project, inspired by C, Elixir
 and Common Lisp. It could be described as C with Elixir modules,
diff --git a/env b/env
index c160898..8923f71 100644
--- a/env
+++ b/env
@@ -1,4 +1,4 @@
-export LD_LIBRARY_PATH="$PWD/libkc3/.libs:$PWD/ekc3/.libs:$PWD/http/.libs:$PWD/markdown/.libs:$PWD/lib/kc3/0.1:$LD_LIBRARY_PATH"
+export LD_LIBRARY_PATH="$PWD/libkc3/.libs:$PWD/ekc3/.libs:$PWD/http/.libs:$PWD/markdown/.libs:$PWD/lib/kc3/0.1:$PWD/window/.libs:$PWD/window/sdl2/.libs:$LD_LIBRARY_PATH"
 export DYLD_LIBRARY_PATH="$PWD/libkc3/.libs:$PWD/ekc3/.libs:$PWD/http/.libs:$PWD/markdown/.libs:$PWD/lib/kc3/0.1:$DYLD_LIBRARY_PATH"
 export KC3_HTTPD_HOST=0.0.0.0
 export KC3_HTTPD_PORT=58000
diff --git a/http/http_request.c b/http/http_request.c
index f617f47..6c4b687 100644
--- a/http/http_request.c
+++ b/http/http_request.c
@@ -18,8 +18,10 @@
 
 s_tag * http_request_buf_parse (s_tag *req, s_buf *buf)
 {
+  bool b;
   s_tag  body;
   s_str *body_str;
+  s_str boundary;
   const s_str content_length_str = {{NULL}, 14, {"Content-Length"}};
   uw          content_length_uw = 0;
   s_str      *content_type = NULL;
@@ -29,6 +31,8 @@ s_tag * http_request_buf_parse (s_tag *req, s_buf *buf)
   s_str line;
   s_tag method_key = {0};
   s_tag method_value = {0};
+  static const s_str multipart_form_data =
+    {{NULL}, 30, {"multipart/form-data; boundary="}};
   s_buf_save save;
   s_list **tail;
   s_tag tmp = {0};
@@ -109,23 +113,38 @@ s_tag * http_request_buf_parse (s_tag *req, s_buf *buf)
       err_inspect_str(body_str);
       err_write_1("\n");
     }
-    if (content_type &&
-        ! compare_str_case_insensitive(&urlencoded, content_type)) {
-      if (! url_www_form_decode(body_str, &body))
-        goto restore;
-      if (false) {
-        err_write_1("http_request_buf_parse: body: ");
-        err_inspect_tag(&body);
-        err_write_1("\n");
+    if (content_type) {
+      if (! compare_str_case_insensitive(&urlencoded, content_type)) {
+        if (! url_www_form_decode(body_str, &body))
+          goto restore;
+        if (false) {
+          err_write_1("http_request_buf_parse: body: ");
+          err_inspect_tag(&body);
+          err_write_1("\n");
+        }
+        if (alist_get(body.data.list,
+                      &method_key, &method_value)) {
+          http_request_method_from_str(&method_value.data.str,
+                                       &tmp_req.method);
+          tag_clean(&method_value);
+        }
+        str_clean(body_str);
+        tmp_req.body = body;
       }
-      if (alist_get(body.data.list,
-                    &method_key, &method_value)) {
-        http_request_method_from_str(&method_value.data.str,
-                                     &tmp_req.method);
-        tag_clean(&method_value);
+    }
+    if (! str_starts_with_case_insensitive(content_type,
+                                           &multipart_form_data,
+                                           &b)) {
+      if (b) {
+        if (! str_init_slice(&boundary, content_type,
+                             multipart_form_data.size, -1))
+          goto restore;
+        if (true) {
+          err_write_1("http_request_buf_parse: boundary ");
+          err_inspect_str(&boundary);
+          err_write_1("\n");
+        }
       }
-      str_clean(body_str);
-      tmp_req.body = body;
     }
   }
   if (! tag_init_struct(&tmp, sym_1("HTTP.Request")))
diff --git a/kc3.version b/kc3.version
index 71d6a66..c34958a 100644
--- a/kc3.version
+++ b/kc3.version
@@ -1 +1 @@
-0.1.14
+0.1.15
diff --git a/libkc3/str.c b/libkc3/str.c
index ce97797..de70557 100644
--- a/libkc3/str.c
+++ b/libkc3/str.c
@@ -1405,6 +1405,42 @@ bool * str_starts_with (const s_str *str, const s_str *start,
   return dest;
 }
 
+bool * str_starts_with_case_insensitive (const s_str *str,
+                                         const s_str *start,
+                                         bool *dest)
+{
+  character str_c;
+  s_str     str_i;
+  character start_c;
+  s_str     start_i;
+  assert(str);
+  assert(start);
+  if (! start->size) {
+    *dest = true;
+    return dest;
+  }
+  if (str->size < start->size) {
+    *dest = false;
+    return dest;
+  }
+  str_i = *str;
+  start_i = *start;
+  while (start_i.size > 0) {
+    if (str_read_character_utf8(&start_i, &start_c) < 0)
+      return NULL;
+    if (str_read_character_utf8(&str_i, &str_c) < 0)
+      return NULL;
+    start_c = character_to_lower(start_c);
+    str_c = character_to_lower(str_c);
+    if (start_c != str_c) {
+      *dest = false;
+      return dest;
+    }
+  }
+  *dest = true;
+  return dest;
+}
+
 uw * str_sw_pos_to_uw (sw pos, uw max_pos, uw *dest)
 {
   assert(dest);
diff --git a/libkc3/str.h b/libkc3/str.h
index 3d36a89..82a6dc9 100644
--- a/libkc3/str.h
+++ b/libkc3/str.h
@@ -138,6 +138,9 @@ s_list **     str_split (const s_str *str, const s_str *separator,
                          s_list **dest);
 bool *        str_starts_with (const s_str *str, const s_str *start,
                                bool *dest);
+bool *        str_starts_with_case_insensitive (const s_str *str,
+                                                const s_str *start,
+                                                bool *dest);
 uw *          str_sw_pos_to_uw (sw pos, uw max_pos, uw *dest);
 s_str *       str_to_hex (const s_str *str, s_str *dest);
 s_ident *     str_to_ident (const s_str *str, s_ident *dest);
diff --git a/window/sdl2/Makefile b/window/sdl2/Makefile
index b9b5416..2faa40c 100644
--- a/window/sdl2/Makefile
+++ b/window/sdl2/Makefile
@@ -21,6 +21,7 @@ DISTCLEANFILES = ${CLEANFILES} config.h config.mk
 build:
 	${MAKE} ${LIB}
 	${MAKE} -C demo build
+	${MAKE} -C kubz build
 
 all:
 	${MAKE} build
diff --git a/window/window.c b/window/window.c
index 19f60e8..86964c5 100644
--- a/window/window.c
+++ b/window/window.c
@@ -35,7 +35,8 @@ bool window_animate (s_window *window)
   seq->frame++;
   seq->t = t;
   /* printf("window_animate: %f\n", t); */
-  if (t > seq->duration &&
+  if (seq->duration > 0 &&
+      t > seq->duration &&
       ! window_set_sequence_pos(window, (window->sequence_pos + 1) %
                                 window->sequence_count))
     return false;