add donate cgi-bin to repo - www.codemadness.org - www.codemadness.org saait content files
(HTM) git clone git://git.codemadness.org/www.codemadness.org
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
(DIR) commit 134683ca1f57d8487892de1bee1dcd5d38315ff6
(DIR) parent a755a0e8c7a3263cf2aeb5c2bd6d80e4270e2461
(HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date: Tue, 17 Sep 2024 10:48:37 +0200
add donate cgi-bin to repo
Diffstat:
A cgi-bin/donate/Makefile | 5 +++++
A cgi-bin/donate/README | 1 +
A cgi-bin/donate/httpd.conf | 5 +++++
A cgi-bin/donate/index.html | 56 +++++++++++++++++++++++++++++++
A cgi-bin/donate/main.c | 179 +++++++++++++++++++++++++++++++
A cgi-bin/donate/testsuite.sh | 2 ++
6 files changed, 248 insertions(+), 0 deletions(-)
---
(DIR) diff --git a/cgi-bin/donate/Makefile b/cgi-bin/donate/Makefile
@@ -0,0 +1,5 @@
+build: clean
+ ${CC} -o main main.c -static -Os -Wall
+
+clean:
+ rm -f *.o main
(DIR) diff --git a/cgi-bin/donate/README b/cgi-bin/donate/README
@@ -0,0 +1 @@
+"Donations" CGI program, for fun.
(DIR) diff --git a/cgi-bin/donate/httpd.conf b/cgi-bin/donate/httpd.conf
@@ -0,0 +1,5 @@
+ location "/cgi-bin/donate" {
+ request strip 1
+ root "/cgi-bin/donate"
+ fastcgi socket "/run/slowcgi.sock"
+ }
(DIR) diff --git a/cgi-bin/donate/index.html b/cgi-bin/donate/index.html
@@ -0,0 +1,56 @@
+<title>Donation</title>
+
+<style type="text/css">
+body {
+ background-color: #fff;
+ font-family: sans;
+}
+.form {
+ margin: 0 auto;
+ width: 80ex;
+}
+
+textarea, input {
+ font-size: 140%;
+}
+</style>
+
+<div class="form">
+<h1>Donation</h1>
+
+<form method="get" action="/cgi-bin/donate">
+
+<p>
+<label for=""><b>Type of donation:</b></label>
+</p>
+
+<p>
+<input type="radio" name="type" id="compliment" value="c" selected /> <label for="compliment">A nice compliment</label>
+<input type="radio" name="type" id="hate" value="h" /> <label for="hate">Pure hatred</label>
+<input type="radio" name="type" id="joke" value="j" /> <label for="joke">A joke</label>
+<input type="radio" name="type" id="million" value="m" /> <label for="million">One million dollars</label>
+</p>
+
+<p>
+<label for="msg"><b>Message:</b></label>
+</p>
+
+<p>
+ <textarea name="msg" cols="69" rows="3" id="msg" required></textarea>
+</p>
+
+<p>
+ <label for="captcha"><b>Captcha question: do captchas suck?<br/>
+ Type "yes" without quotes in the field below:</b></label>
+</p>
+
+<p>
+ <input type="text" name="captcha" id="captcha" value="" placeholder="yes" required size="3" />
+</p>
+
+<p>
+ <input type="submit" name="pay" value="Pay" />
+</p>
+
+</form>
+</div>
(DIR) diff --git a/cgi-bin/donate/main.c b/cgi-bin/donate/main.c
@@ -0,0 +1,179 @@
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifdef __OpenBSD__
+#include <unistd.h>
+#else
+#define pledge(p1,p2) 0
+#define unveil(p1,p2) 0
+#endif
+
+int
+hexdigit(int c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ else if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ else if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+
+ return 0;
+}
+
+/* decode until NUL separator or end of "key". */
+int
+decodeparam(char *buf, size_t bufsiz, const char *s)
+{
+ size_t i;
+
+ if (!bufsiz)
+ return -1;
+
+ for (i = 0; *s && *s != '&'; s++) {
+ switch (*s) {
+ case '%':
+ if (i + 3 >= bufsiz)
+ return -1;
+ if (!isxdigit((unsigned char)*(s+1)) ||
+ !isxdigit((unsigned char)*(s+2)))
+ return -1;
+ buf[i++] = hexdigit(*(s+1)) * 16 + hexdigit(*(s+2));
+ s += 2;
+ break;
+ case '+':
+ if (i + 1 >= bufsiz)
+ return -1;
+ buf[i++] = ' ';
+ break;
+ default:
+ if (i + 1 >= bufsiz)
+ return -1;
+ buf[i++] = *s;
+ break;
+ }
+ }
+ buf[i] = '\0';
+
+ return i;
+}
+
+char *
+getparam(const char *query, const char *s)
+{
+ const char *p, *last = NULL;
+ size_t len;
+
+ len = strlen(s);
+ for (p = query; (p = strstr(p, s)); p += len) {
+ if (p[len] == '=' && (p == query || p[-1] == '&' || p[-1] == '?'))
+ last = p + len + 1;
+ }
+
+ return (char *)last;
+}
+
+void
+error(const char *s)
+{
+ fputs("Status: 400 Bad Request\r\n", stdout);
+ fputs("Content-Type: text/plain\r\n", stdout);
+ fputs("\r\n", stdout);
+ fputs(s, stdout);
+ exit(0);
+}
+
+int
+main(void)
+{
+ time_t now;
+ FILE *fp;
+ char filename[256];
+ char _type[32], msg[4096], captcha[16];
+ char *p, *query;
+ int r, valid;
+
+ if (unveil("/donations", "rwc") == -1)
+ return 1;
+ if (pledge("stdio rpath cpath wpath", NULL) == -1)
+ return 1;
+
+ query = getenv("QUERY_STRING");
+ if (!query)
+ query = "";
+ if (query[0] == '?')
+ query++;
+
+ valid = 0;
+ if ((p = getparam(query, "captcha"))) {
+ r = decodeparam(captcha, sizeof(captcha), p);
+ if (r != -1 && !strcmp(captcha, "yes"))
+ valid = 1;
+ }
+ if (!valid)
+ error("Captcha must be: yes\n");
+
+ valid = 0;
+ if ((p = getparam(query, "type"))) {
+ r = decodeparam(_type, sizeof(_type), p);
+ if (r != -1 && (_type[0] == 'c' || _type[0] == 'h' || _type[0] == 'j' || _type[0] == 'm'))
+ valid = 1;
+ }
+ if (!valid)
+ error("Please select a type of donation\n");
+
+ valid = 0;
+ if ((p = getparam(query, "msg"))) {
+ r = decodeparam(msg, sizeof(msg), p);
+ if (msg[0])
+ valid = 1;
+ }
+ if (!valid)
+ error("Please type a message\n");
+
+ if (!(p = getparam(query, "pay")))
+ error("Please click the pay button\n");
+
+ /* future scaling improvement: multiple parallel donations at the same time won't work */
+ now = time(NULL);
+ r = snprintf(filename, sizeof(filename), "/donations/%c_%lld.txt", _type[0], (long long)now);
+ if (r < 0 || (size_t)r >= sizeof(filename))
+ error("shit happens\n");
+
+ fp = fopen(filename, "w+b");
+ if (!fp)
+ error("Cannot receive donation, thanks anyway.\n");
+
+ switch (_type[0]) {
+ case 'c':
+ fputs("Some person sent a compliment:\n\n", fp);
+ break;
+ case 'h':
+ fputs("Some person sent pure hatred:\n\n", fp);
+ break;
+ case 'j':
+ fputs("Some person sent a joke:\n\n", fp);
+ break;
+ }
+
+ fputs(msg, fp);
+ fclose(fp);
+
+ if (_type[0] == 'm') {
+ fputs("Status: 302 Found\r\n", stdout);
+
+ fputs("Location: https://www.codemadness.org/downloads/1_million_dollars.webm\r\n", stdout);
+ } else {
+ fputs("Status: 200 OK\r\n", stdout);
+ }
+
+ fputs("Content-Type: text/plain\r\n", stdout);
+ fputs("\r\n", stdout);
+ fputs("Thank you for your donation!\n", stdout);
+ return 0;
+
+ return 0;
+}
(DIR) diff --git a/cgi-bin/donate/testsuite.sh b/cgi-bin/donate/testsuite.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+QUERY_STRING="?captcha=yes&type=j&msg=a&pay=1" ./main