From 54c205e9314ac4ecbe79aff1f707f8f2e8d12b9a Mon Sep 17 00:00:00 2001 From: Heck Dennis Date: Tue, 13 Jan 2026 07:59:47 +0100 Subject: [PATCH 1/5] creating draft PR --- config/youpi_banane.conf | 12 ++- src/main.cpp | 5 +- .../YoupiBanane/Yeah/not_happy.bad_extension | 0 www/YoupiBanane/index.html | 1 + {tests => www}/YoupiBanane/nop/other.pouic | 0 .../YoupiBanane/nop/youpi.bad_extension | 0 www/YoupiBanane/youpi.bad_extension | 1 + {tests => www}/YoupiBanane/youpi.bla | 0 www/eval/assets/hello.txt | 2 + .../eval/cgi-bin/echo.bla | 0 www/eval/cgi-bin/env.bla | 9 ++ www/eval/cgi-bin/upload_save.bla | 11 +++ www/eval/cgi-py/cgi_upper.py | 30 ++++++ www/eval/delete_me/victim.txt | 1 + www/eval/errors/404.html | 4 + www/eval/errors/405.html | 4 + www/eval/errors/500.html | 4 + www/eval/index.html | 94 +++++++++++++++++++ www/eval/style.css | 28 ++++++ www/eval/upload/.keep | 0 20 files changed, 200 insertions(+), 6 deletions(-) rename {tests => www}/YoupiBanane/Yeah/not_happy.bad_extension (100%) create mode 100644 www/YoupiBanane/index.html rename {tests => www}/YoupiBanane/nop/other.pouic (100%) rename {tests => www}/YoupiBanane/nop/youpi.bad_extension (100%) create mode 100644 www/YoupiBanane/youpi.bad_extension rename {tests => www}/YoupiBanane/youpi.bla (100%) create mode 100644 www/eval/assets/hello.txt rename tests/YoupiBanane/youpi.bad_extension => www/eval/cgi-bin/echo.bla (100%) mode change 100644 => 100755 create mode 100755 www/eval/cgi-bin/env.bla create mode 100755 www/eval/cgi-bin/upload_save.bla create mode 100755 www/eval/cgi-py/cgi_upper.py create mode 100644 www/eval/delete_me/victim.txt create mode 100644 www/eval/errors/404.html create mode 100644 www/eval/errors/405.html create mode 100644 www/eval/errors/500.html create mode 100644 www/eval/index.html create mode 100644 www/eval/style.css create mode 100644 www/eval/upload/.keep diff --git a/config/youpi_banane.conf b/config/youpi_banane.conf index 0c98ed8..0d372ab 100644 --- a/config/youpi_banane.conf +++ b/config/youpi_banane.conf @@ -1,19 +1,23 @@ server { listen 8080; - root ./tests; - allow_methods GET; + root ./www/YoupiBanane; - cgi_handler .bla /cgi_tester; + cgi_handler .bla /cgi-bin/cgi_tester; cgi_allow_methods POST; + location / { + allow_methods GET; + } + location /post_body { allow_methods POST; client_max_body_size 100; + allow_uploads on; + upload_store ./www/YoupiBanane/uploads; } location /directory/ { - /YoupiBanane; allow_methods GET; index youpi.bad_extension; } diff --git a/src/main.cpp b/src/main.cpp index 5bdce98..a7c84e3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,9 +10,10 @@ int main(void) setup_signal_handlers(); try { + // HttpConfig cfg = load_http_config("config/youpi_banane.conf"); // HttpConfig cfg = load_http_config("config/vitepress.conf"); - HttpConfig cfg = load_http_config("config/site1.conf"); - + // HttpConfig cfg = load_http_config("config/python.conf"); + HttpConfig cfg = load_http_config("config/eval.conf"); Server server(cfg.servers[0]); server.init(); server.run(); diff --git a/tests/YoupiBanane/Yeah/not_happy.bad_extension b/www/YoupiBanane/Yeah/not_happy.bad_extension similarity index 100% rename from tests/YoupiBanane/Yeah/not_happy.bad_extension rename to www/YoupiBanane/Yeah/not_happy.bad_extension diff --git a/www/YoupiBanane/index.html b/www/YoupiBanane/index.html new file mode 100644 index 0000000..0ee3895 --- /dev/null +++ b/www/YoupiBanane/index.html @@ -0,0 +1 @@ +Some content diff --git a/tests/YoupiBanane/nop/other.pouic b/www/YoupiBanane/nop/other.pouic similarity index 100% rename from tests/YoupiBanane/nop/other.pouic rename to www/YoupiBanane/nop/other.pouic diff --git a/tests/YoupiBanane/nop/youpi.bad_extension b/www/YoupiBanane/nop/youpi.bad_extension similarity index 100% rename from tests/YoupiBanane/nop/youpi.bad_extension rename to www/YoupiBanane/nop/youpi.bad_extension diff --git a/www/YoupiBanane/youpi.bad_extension b/www/YoupiBanane/youpi.bad_extension new file mode 100644 index 0000000..6c2750e --- /dev/null +++ b/www/YoupiBanane/youpi.bad_extension @@ -0,0 +1 @@ +youpi.bad_extension diff --git a/tests/YoupiBanane/youpi.bla b/www/YoupiBanane/youpi.bla similarity index 100% rename from tests/YoupiBanane/youpi.bla rename to www/YoupiBanane/youpi.bla diff --git a/www/eval/assets/hello.txt b/www/eval/assets/hello.txt new file mode 100644 index 0000000..31e5b3d --- /dev/null +++ b/www/eval/assets/hello.txt @@ -0,0 +1,2 @@ +Hello evaluator πŸ‘‹ +This is a static GET file served by webserv. diff --git a/tests/YoupiBanane/youpi.bad_extension b/www/eval/cgi-bin/echo.bla old mode 100644 new mode 100755 similarity index 100% rename from tests/YoupiBanane/youpi.bad_extension rename to www/eval/cgi-bin/echo.bla diff --git a/www/eval/cgi-bin/env.bla b/www/eval/cgi-bin/env.bla new file mode 100755 index 0000000..4799676 --- /dev/null +++ b/www/eval/cgi-bin/env.bla @@ -0,0 +1,9 @@ +#!/bin/sh +echo "Content-Type: text/plain" +echo +echo "CGI env (sample):" +echo "REQUEST_METHOD=$REQUEST_METHOD" +echo "PATH_INFO=$PATH_INFO" +echo "QUERY_STRING=$QUERY_STRING" +echo "CONTENT_LENGTH=$CONTENT_LENGTH" +echo "CONTENT_TYPE=$CONTENT_TYPE" diff --git a/www/eval/cgi-bin/upload_save.bla b/www/eval/cgi-bin/upload_save.bla new file mode 100755 index 0000000..b9fed01 --- /dev/null +++ b/www/eval/cgi-bin/upload_save.bla @@ -0,0 +1,11 @@ +#!/bin/sh +# Saves request body to a timestamped file in /www/upload/ +# Requires that your server exposes /www as root (so /www/upload exists on disk). + +OUT="/www/upload/$(date +%s).txt" + +echo "Content-Type: text/plain" +echo +echo "Saving body to: $OUT" +cat > "$OUT" +echo "Done." diff --git a/www/eval/cgi-py/cgi_upper.py b/www/eval/cgi-py/cgi_upper.py new file mode 100755 index 0000000..0d53157 --- /dev/null +++ b/www/eval/cgi-py/cgi_upper.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 + +import os +import sys + +def main(): + # Read input + method = os.environ.get("REQUEST_METHOD", "") + data = "" + + if method == "GET": + data = os.environ.get("QUERY_STRING", "") + elif method == "POST": + length = int(os.environ.get("CONTENT_LENGTH", "0")) + data = sys.stdin.read(length) + + # Transform input + result = data.upper() + content_length = len(result) + + # Output CGI response + print("Status: 200 OK") + print("Content-Type: text/plain") + print("Content-Length: " + str(content_length)) + print() + print(result, end="") + sys.stdout.flush() + +if __name__ == "__main__": + main() diff --git a/www/eval/delete_me/victim.txt b/www/eval/delete_me/victim.txt new file mode 100644 index 0000000..ffb9bbd --- /dev/null +++ b/www/eval/delete_me/victim.txt @@ -0,0 +1 @@ +If DELETE works, this file should disappear. diff --git a/www/eval/errors/404.html b/www/eval/errors/404.html new file mode 100644 index 0000000..12ff205 --- /dev/null +++ b/www/eval/errors/404.html @@ -0,0 +1,4 @@ + + +

404 Not Found

+

Custom error page from /www/errors/404.html

diff --git a/www/eval/errors/405.html b/www/eval/errors/405.html new file mode 100644 index 0000000..dde3ef0 --- /dev/null +++ b/www/eval/errors/405.html @@ -0,0 +1,4 @@ + + +

405 Method Not Allowed

+

Custom error page from /www/errors/405.html

diff --git a/www/eval/errors/500.html b/www/eval/errors/500.html new file mode 100644 index 0000000..0354dbb --- /dev/null +++ b/www/eval/errors/500.html @@ -0,0 +1,4 @@ + + +

500 Internal Server Error

+

Custom error page from /www/errors/500.html

diff --git a/www/eval/index.html b/www/eval/index.html new file mode 100644 index 0000000..6bb840c --- /dev/null +++ b/www/eval/index.html @@ -0,0 +1,94 @@ + + + + + + webserv evaluation demo + + + + + +

webserv evaluation demo

+

This website demonstrates GET, POST, DELETE and CGI features.

+ +
+

GET – Static files

+ +
+ +
+

GET – CGI

+ +
+ +
+

POST – Simple body endpoint

+

POST request to /post_body (server-side handler).

+
+
+ +
+
+ +
+

POST – CGI (binary or shell)

+
+ + +
+
+ +
+

POST – Python CGI

+

Python CGI script uppercases request body.

+
+ + +
+
+ +
+

DELETE

+

Target file: /delete_me/victim.txt

+
+curl -i -X DELETE http://localhost:8080/delete_me/victim.txt
+  
+
+ +
+

Quick curl commands

+
+# GET static
+curl -i http://localhost:8080/assets/hello.txt
+
+# GET Python CGI
+curl -i "http://localhost:8080/cgi-py/upper.bla?abc=def"
+
+# POST body
+curl -i -X POST http://localhost:8080/post_body -d "abc=123"
+
+# POST Python CGI
+curl -i -X POST http://localhost:8080/cgi-py/upper.bla -d "hello world"
+
+# DELETE
+curl -i -X DELETE http://localhost:8080/delete_me/victim.txt
+  
+
+ + + + diff --git a/www/eval/style.css b/www/eval/style.css new file mode 100644 index 0000000..dfd15f7 --- /dev/null +++ b/www/eval/style.css @@ -0,0 +1,28 @@ +body { + font-family: sans-serif; + margin: 2rem; + max-width: 900px; +} + +h1 { + margin-bottom: 0.25rem; +} + +section { + border: 1px solid #ddd; + padding: 1rem; + margin: 1rem 0; + border-radius: 8px; +} + +code, +pre { + background: #f6f6f6; + padding: 0.15rem 0.3rem; + border-radius: 4px; +} + +pre { + padding: 0.75rem; + overflow: auto; +} diff --git a/www/eval/upload/.keep b/www/eval/upload/.keep new file mode 100644 index 0000000..e69de29 From fd7130d395be1e62ee95e9c078405814e3bd8839 Mon Sep 17 00:00:00 2001 From: Heck Dennis Date: Tue, 13 Jan 2026 09:18:29 +0100 Subject: [PATCH 2/5] rebasing on dev --- config/eval.conf | 37 +++++++++ www/eval/index.html | 183 ++++++++++++++++++++++++-------------------- www/eval/style.css | 163 +++++++++++++++++++++++++++++++++++---- 3 files changed, 285 insertions(+), 98 deletions(-) create mode 100644 config/eval.conf diff --git a/config/eval.conf b/config/eval.conf new file mode 100644 index 0000000..b4ebc48 --- /dev/null +++ b/config/eval.conf @@ -0,0 +1,37 @@ +server { + listen 8080; + + root www/eval; + index index.html; + + error_page 404 /errors/404.html; + error_page 405 /errors/405.html; + error_page 500 /errors/500.html; + + location / { + allow_methods GET; + + } + + location /post_body { + allow_methods POST; + } + + location /assets/ { + allow_methods GET; + } + + location /delete_me/ { + allow_methods GET DELETE; + } + + location /cgi-py/ { + allow_methods GET POST; + cgi_handler .py /usr/bin/python3; + } + + location /cgi-bin/ { + allow_methods GET POST; + cgi_handler .bla /bin/sh; + } +} diff --git a/www/eval/index.html b/www/eval/index.html index 6bb840c..d64c58d 100644 --- a/www/eval/index.html +++ b/www/eval/index.html @@ -3,92 +3,111 @@ - webserv evaluation demo + + webserv β€” File Box - -

webserv evaluation demo

-

This website demonstrates GET, POST, DELETE and CGI features.

- -
-

GET – Static files

- -
- -
-

GET – CGI

- -
- -
-

POST – Simple body endpoint

-

POST request to /post_body (server-side handler).

-
-
- -
-
- -
-

POST – CGI (binary or shell)

-
- - -
-
- -
-

POST – Python CGI

-

Python CGI script uppercases request body.

-
- - -
-
- -
-

DELETE

-

Target file: /delete_me/victim.txt

-
-curl -i -X DELETE http://localhost:8080/delete_me/victim.txt
-  
-
- -
-

Quick curl commands

-
-# GET static
-curl -i http://localhost:8080/assets/hello.txt
-
-# GET Python CGI
-curl -i "http://localhost:8080/cgi-py/upper.bla?abc=def"
-
-# POST body
-curl -i -X POST http://localhost:8080/post_body -d "abc=123"
-
-# POST Python CGI
-curl -i -X POST http://localhost:8080/cgi-py/upper.bla -d "hello world"
-
-# DELETE
-curl -i -X DELETE http://localhost:8080/delete_me/victim.txt
-  
-
- +
+
+
+

File Box

+

+ Upload and delete files in one folder: /upload/ +

+
+
webserv eval
+
+ +
+

Quick GET sanity check

+

Static file (should always work):

+

GET /assets/hello.txt

+
+ +
+

Upload to /upload/

+

+ Select a file and upload it. The server should store it under + www/eval/upload/<filename>. +

+ +
+ + +
+ +
+ Equivalent curl +
curl -i -X POST http://localhost:8080/upload/ \
+  -F "file=@./myfile.txt"
+
+
+ +
+

Delete from /upload/

+

+ Enter the exact filename to delete. No listing β€” you remember the name. +

+ +
+ + +
+ +

+ Sends: DELETE /upload/<name> +

+ +
+ Equivalent curl +
curl -i -X DELETE "http://localhost:8080/upload/example.txt"
+
+
+ +
+

Extra (optional) curl tests

+
# GET uploaded file by name (optional if you serve /upload/)
+curl -i http://localhost:8080/upload/example.txt
+
+# Upload
+curl -i -X POST http://localhost:8080/upload/ -F "file=@./example.txt"
+
+# Delete (same folder)
+curl -i -X DELETE http://localhost:8080/upload/example.txt
+
+# Keep your old DELETE test file if you want
+curl -i -X DELETE http://localhost:8080/delete_me/victim.txt
+
+ +
+ CGI intentionally omitted for now. +
+
+ + diff --git a/www/eval/style.css b/www/eval/style.css index dfd15f7..4f0a853 100644 --- a/www/eval/style.css +++ b/www/eval/style.css @@ -1,28 +1,159 @@ +:root { + --bg: #0b0f17; + --card: #111827; + --muted: #9ca3af; + --text: #e5e7eb; + --line: rgba(255, 255, 255, 0.08); + --btn: #2563eb; + --btn2: #dc2626; +} + +* { + box-sizing: border-box; +} + +html, body { - font-family: sans-serif; - margin: 2rem; - max-width: 900px; + height: 100%; +} + +body { + margin: 0; + font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif; + background: radial-gradient(1200px 600px at 20% 0%, #111827 0%, var(--bg) 55%); + color: var(--text); +} + +.wrap { + max-width: 860px; + margin: 0 auto; + padding: 28px 16px 40px; +} + +.top { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; + padding: 10px 6px 18px; } h1 { - margin-bottom: 0.25rem; + margin: 0; + font-size: 34px; + letter-spacing: -0.02em; } -section { - border: 1px solid #ddd; - padding: 1rem; - margin: 1rem 0; - border-radius: 8px; +.sub { + margin: 6px 0 0; + color: var(--muted); +} + +.pill { + font-size: 12px; + color: var(--muted); + border: 1px solid var(--line); + padding: 6px 10px; + border-radius: 999px; + white-space: nowrap; +} + +.card { + background: rgba(17, 24, 39, 0.86); + border: 1px solid var(--line); + border-radius: 16px; + padding: 18px 18px 16px; + margin: 14px 0; + box-shadow: 0 12px 30px rgba(0, 0, 0, 0.25); +} + +.card h2 { + margin: 0 0 8px; + font-size: 18px; +} + +.muted { + color: var(--muted); + margin: 0 0 14px; +} + +.small { + font-size: 13px; } -code, -pre { - background: #f6f6f6; - padding: 0.15rem 0.3rem; - border-radius: 4px; +.row { + display: flex; + gap: 10px; + align-items: center; + flex-wrap: wrap; } -pre { - padding: 0.75rem; +.file, +.text { + flex: 1; + min-width: 240px; + padding: 10px 12px; + border-radius: 12px; + border: 1px solid var(--line); + background: rgba(0, 0, 0, 0.25); + color: var(--text); +} + +.btn { + padding: 10px 14px; + border: 0; + border-radius: 12px; + background: var(--btn); + color: white; + font-weight: 600; + cursor: pointer; +} + +.btn.danger { + background: var(--btn2); +} + +.btn:hover { + filter: brightness(1.05); +} + +.details { + margin-top: 12px; + border-top: 1px solid var(--line); + padding-top: 10px; +} + +details summary { + cursor: pointer; + color: var(--muted); + user-select: none; +} + +.code { + margin: 10px 0 0; + padding: 12px; + border-radius: 12px; + border: 1px solid var(--line); + background: rgba(0, 0, 0, 0.25); overflow: auto; } + +code { + background: rgba(0, 0, 0, 0.25); + border: 1px solid var(--line); + padding: 1px 6px; + border-radius: 8px; +} + +.link { + color: var(--text); +} + +.link:hover { + opacity: 0.9; +} + +.foot { + margin-top: 10px; + padding: 10px 6px 0; +} From b1dbe6716558a577a575ef94087083e734ed8088 Mon Sep 17 00:00:00 2001 From: Dennis Heck Date: Tue, 13 Jan 2026 16:32:24 +0100 Subject: [PATCH 3/5] bug --- config/eval.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/eval.conf b/config/eval.conf index b4ebc48..9c15470 100644 --- a/config/eval.conf +++ b/config/eval.conf @@ -13,8 +13,9 @@ server { } - location /post_body { + location /upload { allow_methods POST; + allow_uploads on; } location /assets/ { From 295815b071b37785a0f325defbcbdff493f0e8b0 Mon Sep 17 00:00:00 2001 From: Dennis Heck Date: Tue, 13 Jan 2026 18:09:41 +0100 Subject: [PATCH 4/5] update repo for Ibouk --- config/eval.conf | 3 ++- src/router/router.cpp | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/config/eval.conf b/config/eval.conf index 9c15470..edf179e 100644 --- a/config/eval.conf +++ b/config/eval.conf @@ -14,7 +14,7 @@ server { } location /upload { - allow_methods POST; + allow_methods POST DELETE; allow_uploads on; } @@ -34,5 +34,6 @@ server { location /cgi-bin/ { allow_methods GET POST; cgi_handler .bla /bin/sh; + allow_uploads on; } } diff --git a/src/router/router.cpp b/src/router/router.cpp index dce6778..c232f2d 100644 --- a/src/router/router.cpp +++ b/src/router/router.cpp @@ -68,13 +68,15 @@ const RouteConfig& Router::find_best_route(const std::string& request_path) cons // This seems to be valid in some cases but we ignore it right now. static bool is_cgi_request(const HttpRequest& request, const RouteConfig& route) { + LOG(DEBUG) << "shared.ext" << route.shared.cgi.extension; if (route.shared.cgi.extension.empty()) return false; size_t dot = request.path.find_last_of("."); if (dot == std::string::npos) return false; - + std::string ext = request.path.substr(dot); + LOG(DEBUG) << "ext = " << ext; return request.path.substr(dot) == route.shared.cgi.extension; } From 9c85f7b14a4d66ea77f71b3d95f048afe799e4b6 Mon Sep 17 00:00:00 2001 From: Heck Dennis Date: Wed, 14 Jan 2026 07:16:59 +0100 Subject: [PATCH 5/5] WIP --- config/eval.conf | 8 + www/eval/assets/cold_fusion.txt | 1 + www/eval/assets/hello.txt | 2 - www/eval/cgi-bin/echo.bla | 4 + www/eval/index.html | 412 +++++++++++++++++++++++++++----- www/eval/style.css | 216 ++++++++++------- 6 files changed, 499 insertions(+), 144 deletions(-) create mode 100644 www/eval/assets/cold_fusion.txt delete mode 100644 www/eval/assets/hello.txt diff --git a/config/eval.conf b/config/eval.conf index edf179e..1a6aacf 100644 --- a/config/eval.conf +++ b/config/eval.conf @@ -16,6 +16,14 @@ server { location /upload { allow_methods POST DELETE; allow_uploads on; + autoindex on; + } + + location /post_body { + return 302 /upload; + allow_methods POST DELETE; + allow_uploads on; + autoindex on; } location /assets/ { diff --git a/www/eval/assets/cold_fusion.txt b/www/eval/assets/cold_fusion.txt new file mode 100644 index 0000000..504797f --- /dev/null +++ b/www/eval/assets/cold_fusion.txt @@ -0,0 +1 @@ +TOP SECRET cold fusion diff --git a/www/eval/assets/hello.txt b/www/eval/assets/hello.txt deleted file mode 100644 index 31e5b3d..0000000 --- a/www/eval/assets/hello.txt +++ /dev/null @@ -1,2 +0,0 @@ -Hello evaluator πŸ‘‹ -This is a static GET file served by webserv. diff --git a/www/eval/cgi-bin/echo.bla b/www/eval/cgi-bin/echo.bla index e69de29..9c8c67c 100755 --- a/www/eval/cgi-bin/echo.bla +++ b/www/eval/cgi-bin/echo.bla @@ -0,0 +1,4 @@ +#!/bin/sh +echo "Content-Type: text/plain" +echo +echo "OK" diff --git a/www/eval/index.html b/www/eval/index.html index d64c58d..b912131 100644 --- a/www/eval/index.html +++ b/www/eval/index.html @@ -3,111 +3,407 @@ + webserv evaluation demo - webserv β€” File Box -
-
-
-

File Box

-

- Upload and delete files in one folder: /upload/ -

+
+

webserv evaluation demo

+

+ Demonstrates GET, POST, DELETE and CGI using a small test site. +

+
+ +
+ +
+

GET – Static file

+ + + +

Equivalent curl:

+
curl -i http://localhost:8080/assets/cold_fusion.txt
+
+ +
+

POST – Upload (repeatable)

+ +

+ Sends a raw body to /upload/<filename> (matches your working curl). +

+ +
+ + +
-
webserv eval
-
+ + + + +

Equivalent curl:

+
+curl -X POST http://localhost:8080/upload/hello.txt \
+  -H "Content-Type: text/plain" \
+  --data "some content xy"
+      
+ +

Server response:

+

+        
 
         
-

Quick GET sanity check

-

Static file (should always work):

-

GET /assets/hello.txt

+

DELETE – Remove an uploaded file

+ +

+ Deletes /upload/<filename>. Use it after uploading a file above. +

+ +
+ + + + + (Optional) Open Upload+Delete UI + +
+ +

Equivalent curl:

+
curl -i -X DELETE http://localhost:8080/upload/hello.txt
+ +

Server response:

+

         
-

Upload to /upload/

-

- Select a file and upload it. The server should store it under - www/eval/upload/<filename>. +

POST – Body endpoint (redirection test)

+ +

+ In the config, /post_body responds with 302 redirect to /upload. + This section is here to demonstrate that your server returns the correct status and + Location header. +

+ +

+ What should happen: +
β€’ POST to /post_body β†’ 302 + Location: /upload +
β€’ If the client follows the redirect, it will request /upload (typically via GET)

-
- - -
+
+ + +
+ + + + +

Equivalent curl (show redirect response):

+
curl -i -X POST http://localhost:8080/post_body -d "test redirect"
-
- Equivalent curl -
curl -i -X POST http://localhost:8080/upload/ \
-  -F "file=@./myfile.txt"
-
+

Equivalent curl (follow redirect):

+
curl -i -L -X POST http://localhost:8080/post_body -d "test redirect"
+ +

Server response:

+

         
+ +
-

Delete from /upload/

-

- Enter the exact filename to delete. No listing β€” you remember the name. +

POST – CGI (bash /bin/sh)

+ +

+ Sends a raw POST body to a CGI script in /cgi-bin/. + Your echo.bla should typically print the body.

- - + +
-

- Sends: DELETE /upload/<name> + + + +

+ + Open (GET) +
+ +

Equivalent curl:

+
curl -i -X POST http://localhost:8080/cgi-bin/echo.bla -d "hello from bash CGI"
+ +

Server response:

+

+        
+ +
+

POST – CGI (Python)

+ +

+ Sends a raw POST body to /cgi-py/upper.bla, which uppercases the input. + (If your file is upper.py, change the path below accordingly.)

-
- Equivalent curl -
curl -i -X DELETE "http://localhost:8080/upload/example.txt"
-
+
+ + +
+ + + + +
+ + + Open (GET with query) + +
+ +

Equivalent curl:

+
curl -i -X POST http://localhost:8080/cgi-py/upper.bla -d "hello from python cgi"
+ +

Server response:

+

         
-

Extra (optional) curl tests

-
# GET uploaded file by name (optional if you serve /upload/)
-curl -i http://localhost:8080/upload/example.txt
+            

GET – CGI (optional quick checks)

-# Upload -curl -i -X POST http://localhost:8080/upload/ -F "file=@./example.txt" + +

Equivalent curl:

+
curl -i http://localhost:8080/cgi-bin/env.bla
-# Delete (same folder) -curl -i -X DELETE http://localhost:8080/upload/example.txt +
-# Keep your old DELETE test file if you want -curl -i -X DELETE http://localhost:8080/delete_me/victim.txt
+ +

Equivalent curl:

+
curl -i "http://localhost:8080/cgi-py/upper.bla?hello=world"
-
- CGI intentionally omitted for now. -
+
+ Tip: the β€œEquivalent curl” commands are what you can type live during evaluation. +
+ + diff --git a/www/eval/style.css b/www/eval/style.css index 4f0a853..c4dc7d0 100644 --- a/www/eval/style.css +++ b/www/eval/style.css @@ -1,11 +1,28 @@ +/* Readable, non-white page theme for eval */ + :root { - --bg: #0b0f17; - --card: #111827; - --muted: #9ca3af; + --bg: #0f172a; + /* dark slate */ + --bg2: #111827; + /* slightly different dark */ + --card: #0b1220; + /* card background */ + --border: #243041; + /* border */ --text: #e5e7eb; - --line: rgba(255, 255, 255, 0.08); - --btn: #2563eb; - --btn2: #dc2626; + /* light text */ + --muted: #a7b0bd; + /* muted text */ + --codebg: #0a0f1a; + /* code background */ + --btn: #111b2d; + /* button background */ + --btnHover: #16233a; + /* button hover */ + --primary: #2563eb; + /* blue */ + --primaryHover: #1d4ed8; + --shadow: rgba(0, 0, 0, 0.35); } * { @@ -20,140 +37,171 @@ body { body { margin: 0; font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif; - background: radial-gradient(1200px 600px at 20% 0%, #111827 0%, var(--bg) 55%); color: var(--text); + background: radial-gradient(1200px 700px at 20% 10%, var(--bg2), var(--bg)); + line-height: 1.5; } -.wrap { - max-width: 860px; +.hero { + max-width: 980px; margin: 0 auto; - padding: 28px 16px 40px; -} - -.top { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 16px; - padding: 10px 6px 18px; + padding: 2rem 1.25rem 0.75rem 1.25rem; } h1 { - margin: 0; - font-size: 34px; - letter-spacing: -0.02em; + margin: 0 0 0.5rem 0; + font-size: 2rem; + letter-spacing: 0.2px; } .sub { - margin: 6px 0 0; + margin: 0 0 1rem 0; color: var(--muted); } -.pill { - font-size: 12px; - color: var(--muted); - border: 1px solid var(--line); - padding: 6px 10px; - border-radius: 999px; - white-space: nowrap; +main { + max-width: 980px; + margin: 0 auto; + padding: 0 1.25rem 2rem 1.25rem; } .card { - background: rgba(17, 24, 39, 0.86); - border: 1px solid var(--line); - border-radius: 16px; - padding: 18px 18px 16px; - margin: 14px 0; - box-shadow: 0 12px 30px rgba(0, 0, 0, 0.25); + background: linear-gradient(180deg, rgba(255, 255, 255, 0.03), rgba(255, 255, 255, 0.01)); + border: 1px solid var(--border); + border-radius: 14px; + padding: 1.1rem; + margin: 1rem 0; + box-shadow: 0 8px 30px var(--shadow); } -.card h2 { - margin: 0 0 8px; - font-size: 18px; +h2 { + margin: 0 0 0.85rem 0; + font-size: 1.25rem; +} + +hr { + border: 0; + border-top: 1px solid var(--border); + margin: 1rem 0; } -.muted { +a { + color: var(--text); +} + +a:hover { + color: #ffffff; +} + +.label { + display: inline-block; + margin: 0.25rem 0 0.35rem 0; color: var(--muted); - margin: 0 0 14px; + font-size: 0.95rem; } -.small { - font-size: 13px; +.hint { + color: var(--muted); + margin: 0.65rem 0 0.25rem 0; + font-size: 0.95rem; } .row { display: flex; - gap: 10px; - align-items: center; + gap: 0.75rem; flex-wrap: wrap; + align-items: center; + margin: 0.25rem 0 0.7rem 0; } -.file, -.text { - flex: 1; - min-width: 240px; - padding: 10px 12px; +/* Buttons */ +.btn, +button.btn { + display: inline-block; + padding: 0.55rem 0.9rem; + border: 1px solid var(--border); border-radius: 12px; - border: 1px solid var(--line); - background: rgba(0, 0, 0, 0.25); + background: var(--btn); + cursor: pointer; + text-decoration: none; color: var(--text); + transition: background 120ms ease, transform 120ms ease; } -.btn { - padding: 10px 14px; - border: 0; - border-radius: 12px; - background: var(--btn); - color: white; - font-weight: 600; - cursor: pointer; +.btn:hover, +button.btn:hover { + background: var(--btnHover); + transform: translateY(-1px); } -.btn.danger { - background: var(--btn2); +.btn-primary { + background: var(--primary); + border-color: rgba(255, 255, 255, 0.15); } -.btn:hover { - filter: brightness(1.05); +.btn-primary:hover { + background: var(--primaryHover); } -.details { - margin-top: 12px; - border-top: 1px solid var(--line); - padding-top: 10px; +input[type="text"] { + padding: 0.55rem 0.7rem; + border-radius: 12px; + border: 1px solid var(--border); + background: rgba(0, 0, 0, 0.25); + color: var(--text); + min-width: 220px; + outline: none; } -details summary { - cursor: pointer; - color: var(--muted); - user-select: none; +input[type="text"]:focus { + border-color: rgba(37, 99, 235, 0.7); } -.code { - margin: 10px 0 0; - padding: 12px; +textarea { + width: 100%; + max-width: 920px; border-radius: 12px; - border: 1px solid var(--line); + border: 1px solid var(--border); + padding: 0.8rem; background: rgba(0, 0, 0, 0.25); - overflow: auto; + color: var(--text); + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; + font-size: 0.95rem; + outline: none; } +textarea:focus { + border-color: rgba(37, 99, 235, 0.7); +} + +/* Code blocks */ code { background: rgba(0, 0, 0, 0.25); - border: 1px solid var(--line); - padding: 1px 6px; + border: 1px solid rgba(255, 255, 255, 0.06); + padding: 0.15rem 0.35rem; border-radius: 8px; } -.link { +pre { + background: var(--codebg); + border: 1px solid var(--border); + border-radius: 14px; + padding: 0.85rem; + overflow: auto; + white-space: pre-wrap; color: var(--text); + margin: 0.5rem 0 0 0; } -.link:hover { - opacity: 0.9; +pre.out { + min-height: 3.25rem; } -.foot { - margin-top: 10px; - padding: 10px 6px 0; +/* Footer */ +.footer { + max-width: 980px; + margin: 0 auto; + padding: 0 1.25rem 2rem 1.25rem; + color: var(--muted); + font-size: 0.95rem; }