summaryrefslogtreecommitdiff
path: root/bin/infinity.c
diff options
context:
space:
mode:
authorSam Nystrom <sam@samnystrom.dev>2024-10-15 13:29:10 -0400
committerSam Nystrom <sam@samnystrom.dev>2024-10-15 13:29:10 -0400
commit2c98bbacc8db3b251e1679f9da84cf1f5ed5726a (patch)
tree10d44c9b82d275d66d880ff8ec33992cddda12b5 /bin/infinity.c
parentc8c79e6c6a5c4bb1e0ba44f309ce5ae612f97e1c (diff)
update ~/bin
Diffstat (limited to 'bin/infinity.c')
-rw-r--r--bin/infinity.c216
1 files changed, 216 insertions, 0 deletions
diff --git a/bin/infinity.c b/bin/infinity.c
new file mode 100644
index 0000000..10a45b0
--- /dev/null
+++ b/bin/infinity.c
@@ -0,0 +1,216 @@
+/*
+ infinity.c: the Book of Infinity, adapted for skalibs.
+ Original work by David Madore: http://www.madore.org/~david/
+ Adaptation by Laurent Bercot: http://skarnet.org/
+ License: GNU GPL v2, with the special plea that the text of the Book
+ not be modified.
+ The original code can be found at:
+ http://www.madore.org/~david/programs/programs-1.36.html#prog_infinity
+*/
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <skalibs/bytestr.h>
+#include <skalibs/env.h>
+#include <skalibs/buffer.h>
+#include <skalibs/stralloc.h>
+#include <skalibs/sha256.h>
+
+static char const STRING1[] = "Wake! For the Sun, who scatter'd into flight\n" ;
+static char const STRING2[] = "The Stars before him from the Field of Night,\n" ;
+static char const STRING3[] = "\240\240\240Drives Night along with them from Heav'n, and strikes\n" ;
+static char const STRING4[] = "The Sult\341n's Turret with a Shaft of Light.\n" ;
+
+#define die() return(111)
+
+
+typedef struct magic_string_state_s magic_string_state_t, *magic_string_state_t_ref ;
+struct magic_string_state_s
+{
+ char vowel ;
+ char sequent ;
+} ;
+
+#define MAGIC_STRING_STATE_ZERO { 0, 0 } ;
+
+static char const *magic_string (unsigned char data_byte, magic_string_state_t_ref st, char final)
+{
+ char const *s ;
+ char oldsequent = st->sequent ;
+ if (((data_byte % 7) == 0 ) && st->sequent && !final)
+ {
+ st->sequent = 0 ;
+ return " " ;
+ }
+ st->sequent = 1 ;
+ if (st->vowel)
+ {
+ st->vowel = 0 ;
+ if (data_byte < 40) s = "a" ;
+ else if (data_byte < 80) s = "e" ;
+ else if (data_byte < 115) s = "i" ;
+ else if (data_byte < 145) s = "o" ;
+ else if (data_byte < 175) s = "u" ;
+ else if (data_byte < 195) s = "y" ;
+ else if (data_byte < 200) s = "ai" ;
+ else if (data_byte < 205) s = "ei" ;
+ else if (data_byte < 210) s = "oi" ;
+ else if (data_byte < 215) s = "au" ;
+ else if (data_byte < 220) s = "eu" ;
+ else if (data_byte < 225) s = "ou" ;
+ else if (data_byte < 230) s = "ae" ;
+ else if (data_byte < 235) s = "oe" ;
+ else if (data_byte < 240) s = "aa" ;
+ else if (data_byte < 250) s = "'" ;
+ else
+ {
+ s = "" ;
+ st->sequent = oldsequent ;
+ }
+ }
+ else
+ {
+ st->vowel = 1 ;
+ if ( data_byte < 12 ) s = "p" ;
+ else if (data_byte < 24) s = "b" ;
+ else if (data_byte < 36) s = "t" ;
+ else if (data_byte < 48) s = "d" ;
+ else if (data_byte < 60) s = "k" ;
+ else if (data_byte < 72) s = "g" ;
+ else if (data_byte < 84) s = "s" ;
+ else if (data_byte < 96) s = "z" ;
+ else if (data_byte < 108) s = "sh" ;
+ else if (data_byte < 120) s = "zh" ;
+ else if (data_byte < 132) s = "f" ;
+ else if (data_byte < 144) s = "v" ;
+ else if (data_byte < 156) s = "ch" ;
+ else if (data_byte < 168) s = "j" ;
+ else if (data_byte < 174) s = "ks" ;
+ else if (data_byte < 180) s = "x" ;
+ else if (data_byte < 192) { s = "h" ; st->vowel = (data_byte < 190) ; }
+ else if (data_byte < 204) { s = "n" ; st->vowel = (data_byte < 198) ; }
+ else if (data_byte < 216) { s = "r" ; st->vowel = (data_byte < 210) ; }
+ else if (data_byte < 222) s = "st" ;
+ else if (data_byte < 228) s = "zd" ;
+ else if (data_byte < 234) s = "ts" ;
+ else if (data_byte < 240) s = "dz" ;
+ else if (data_byte < 242) s = "pn" ;
+ else if (data_byte < 244) s = "bn" ;
+ else if (data_byte < 247) s = "sht" ;
+ else if (data_byte < 250) s = "zhd" ;
+ else
+ {
+ s = "" ;
+ st->sequent = oldsequent ;
+ }
+ }
+ return s ;
+}
+
+static int page_make_name (stralloc *sa, char const *seed, unsigned int seedlen)
+{
+ SHA256Schedule context = SHA256_INIT() ;
+ magic_string_state_t st = MAGIC_STRING_STATE_ZERO ;
+ char data[64] ;
+
+ sha256_update(&context, STRING1, sizeof(STRING1) - 1) ;
+ sha256_update(&context, seed, seedlen) ;
+ sha256_update(&context, STRING2, sizeof(STRING2) - 1) ;
+ sha256_update(&context, seed, seedlen) ;
+ sha256_final(&context, data) ;
+ sha256_init(&context) ;
+ sha256_update(&context, STRING3, sizeof(STRING3) - 1) ;
+ sha256_update(&context, seed, seedlen) ;
+ sha256_update(&context, STRING4, sizeof(STRING4) - 1) ;
+ sha256_update(&context, seed, seedlen) ;
+ sha256_final(&context, data + 32) ;
+
+ {
+ unsigned int i = 0 ;
+ for (; i < 64 ; i++)
+ if (!stralloc_cats(sa, magic_string(data[i], &st, i == 63)))
+ return 0 ;
+ }
+ return 1 ;
+}
+
+int main (void)
+{
+ stralloc url_start = STRALLOC_ZERO ;
+ stralloc page_name = STRALLOC_ZERO ;
+ stralloc new_path = STRALLOC_ZERO ;
+ stralloc new_page_name = STRALLOC_ZERO ;
+ char const *script_name = getenv("SCRIPT_NAME") ;
+ unsigned int new_path_start ;
+ unsigned int i = 0 ;
+
+ if (!script_name) script_name = "infinity.cgi" ;
+
+ {
+ char const *x = getenv("PATH_INFO") ;
+ if (!x || !*x) x = "/" ;
+ if (!stralloc_cats(&new_path, x)) die() ;
+ x = getenv("SERVER_NAME") ;
+ if (x)
+ {
+ if (!stralloc_cats(&url_start, "//")) die() ;
+ if (!stralloc_cats(&url_start, x)) die() ;
+ x = getenv("SERVER_PORT") ;
+ if (x && strcmp(x, "80"))
+ {
+ if (!stralloc_catb(&url_start, ":", 1)) die() ;
+ if (!stralloc_cats(&url_start, x)) die() ;
+ }
+ }
+ }
+
+ if (!page_make_name(&page_name, new_path.s, new_path.len)) die() ;
+ buffer_puts(buffer_1, "Last-Modified: Wed, 24 May 2017 12:20:00 GMT\r\nContent-Type: text/html\r\n\r\n<html>\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\r\n<meta http-equiv=\"Content-Language\" content=\"en\" />\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\r\n<title>") ;
+ buffer_put(buffer_1, page_name.s, page_name.len) ;
+ buffer_puts(buffer_1, "</title>\r\n<meta name=\"robots\" content=\"noindex, nofollow\" />\r\n<meta name=\"description\" content=\"One Page from the Book of Infinity\" />\r\n<meta name=\"keywords\" content=\"infinite web space ") ;
+ buffer_put(buffer_1, page_name.s, page_name.len) ;
+ buffer_puts(buffer_1, "\" />\r\n</head>\r\n<body>\r\n<h1>") ;
+ buffer_put(buffer_1, page_name.s, page_name.len) ;
+ buffer_puts(buffer_1, "</h1>\r\n<p> You are in a maze of twisty little web pages, all alike. </p>\r\n<p> From here you can get to the following places: </p>\r\n<ul>\r\n") ;
+
+ new_path_start = new_path.len ;
+ for (; i < 14 ; i++)
+ {
+ new_path.len = new_path_start ;
+ buffer_puts(buffer_1, "<li>") ;
+ switch (i)
+ {
+ case 0 :
+ case 13 :
+ {
+ while (new_path.len > 1) if (new_path.s[--new_path.len - 1] == '/') break ;
+ if (!i) buffer_puts(buffer_1, "Back to ") ;
+ else
+ {
+ if (!stralloc_catb(&new_path, page_name.s, byte_chr(page_name.s, page_name.len, ' '))) die() ;
+ if (!stralloc_catb(&new_path, "/", 1)) die() ;
+ }
+ break ;
+ }
+ default:
+ {
+ char const *const zodiac[12] = { "aries", "taurus", "gemini", "cancer", "leo", "virgo", "libra", "scorpius", "sagittarius", "capricornus", "aquarius", "pisces" } ;
+ if (!stralloc_cats(&new_path, zodiac[i-1])) die() ;
+ if (!stralloc_catb(&new_path, "/", 1)) die() ;
+ }
+ }
+ buffer_puts(buffer_1, "<a href=\"") ;
+ if (url_start.s) buffer_put(buffer_1, url_start.s, url_start.len) ;
+ buffer_puts(buffer_1, script_name) ;
+ buffer_put(buffer_1, new_path.s, new_path.len) ;
+ buffer_puts(buffer_1, "\">") ;
+ new_page_name.len = 0 ;
+ if (!page_make_name(&new_page_name, new_path.s, new_path.len)) die() ;
+ buffer_put(buffer_1, new_page_name.s, new_page_name.len) ;
+ buffer_puts(buffer_1, "</a></li>\r\n") ;
+ }
+ buffer_putsflush(buffer_1, "</ul>\r\n</body>\r\n</html>\r\n") ;
+ return 0 ;
+}
+