/* 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 #include #include #include #include #include #include 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) { MD5Schedule context = MD5_INIT() ; magic_string_state_t st = MAGIC_STRING_STATE_ZERO ; char data[64] ; md5_update(&context, STRING1, sizeof(STRING1) - 1) ; md5_update(&context, seed, seedlen) ; md5_final(&context, data) ; md5_init(&context) ; md5_update(&context, STRING2, sizeof(STRING2) - 1) ; md5_update(&context, seed, seedlen) ; md5_final(&context, data + 16) ; md5_init(&context) ; md5_update(&context, STRING3, sizeof(STRING3) - 1) ; md5_update(&context, seed, seedlen) ; md5_final(&context, data + 32) ; md5_init(&context) ; md5_update(&context, STRING4, sizeof(STRING4) - 1) ; md5_update(&context, seed, seedlen) ; md5_final(&context, data + 48) ; { 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\r\n\r\n\r\n\r\n\r\n") ; buffer_put(buffer_1, page_name.s, page_name.len) ; buffer_puts(buffer_1, "\r\n\r\n\r\n\r\n\r\n\r\n

") ; buffer_put(buffer_1, page_name.s, page_name.len) ; buffer_puts(buffer_1, "

\r\n

You are in a maze of twisty little web pages, all alike.

\r\n

From here you can get to the following places:

\r\n
    \r\n") ; new_path_start = new_path.len ; for (; i < 14 ; i++) { new_path.len = new_path_start ; buffer_puts(buffer_1, "
  • ") ; 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, "") ; 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, "
  • \r\n") ; } buffer_putsflush(buffer_1, "
\r\n\r\n\r\n") ; return 0 ; }