From 640aa303a762eb851eac85e270700c62cb13e305 Mon Sep 17 00:00:00 2001
From: Neil Edelman
Date: Sun, 11 Sep 2016 02:35:22 -0400
Subject: [PATCH] New version control.
---
Mac.c | 390 +++++++++++++++++++
Mac.h | 1 +
Makefile | 19 +
Oss.c | 475 +++++++++++++++++++++++
Oss.h | 16 +
Room.c | 1058 +++++++++++++++++++++++++++++++++++++++++++++++++++
Room.h | 3 +
badass | 7 +
copying.txt | 16 +
gpl.txt | 619 ++++++++++++++++++++++++++++++
index.html | 42 ++
readme.txt | 7 +
12 files changed, 2653 insertions(+)
create mode 100644 Mac.c
create mode 100644 Mac.h
create mode 100644 Makefile
create mode 100644 Oss.c
create mode 100644 Oss.h
create mode 100644 Room.c
create mode 100644 Room.h
create mode 100644 badass
create mode 100644 copying.txt
create mode 100644 gpl.txt
create mode 100644 index.html
create mode 100644 readme.txt
diff --git a/Mac.c b/Mac.c
new file mode 100644
index 0000000..9037ad4
--- /dev/null
+++ b/Mac.c
@@ -0,0 +1,390 @@
+/* Copyright 2000, 2009, 2011, 2012 Neil Edelman, distributed under the terms
+ of the GNU General Public License, see copying.txt */
+
+/* AlexV hacked the game; thanks for the recomendations -- Jan 2011
+I'm using Olivier Gay's SHA-256 implementation, slightly modified */
+
+#include
+#include "Mac.h"
+
+#define SHA256_BLOCK_SIZE (512 / 8)
+
+void hmac_sha256(unsigned char *key,
+ unsigned char *message, unsigned int message_len,
+ unsigned char *mac, unsigned mac_size);
+
+char *Mac(const char *str) {
+ static const char *mime = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+ static const char *key =
+#ifdef SECRET
+ SECRET
+#else
+ "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"
+#endif
+ ;
+ int i;
+ static char mac[SHA256_BLOCK_SIZE+1];
+
+ hmac_sha256((unsigned char *)key, (unsigned char *)str, strlen(str), (unsigned char *)mac, SHA256_BLOCK_SIZE);
+
+ /* URI stringise the MAC (loss of 2-bits) */
+ for(i = 0; i < SHA256_BLOCK_SIZE; i++) mac[i] = mime[mac[i] & 63];
+ mac[i] = '\0';
+
+ return mac;
+}
+
+/*-
+ * HMAC-SHA-224/256/384/512 implementation
+ * Last update: 06/15/2005
+ * Issue date: 06/15/2005
+ *
+ * Copyright (C) 2005 Olivier Gay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include
+
+#define SHA256_DIGEST_SIZE ( 256 / 8)
+
+#define SHFR(x, n) (x >> n)
+#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
+#define CH(x, y, z) ((x & y) ^ (~x & z))
+#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+
+#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
+#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
+
+#define UNPACK32(x, str) \
+{ \
+ *((str) + 3) = (uint8) ((x) ); \
+ *((str) + 2) = (uint8) ((x) >> 8); \
+ *((str) + 1) = (uint8) ((x) >> 16); \
+ *((str) + 0) = (uint8) ((x) >> 24); \
+}
+
+#define PACK32(str, x) \
+{ \
+ *(x) = ((uint32) *((str) + 3) ) \
+ | ((uint32) *((str) + 2) << 8) \
+ | ((uint32) *((str) + 1) << 16) \
+ | ((uint32) *((str) + 0) << 24); \
+}
+
+/* Macros used for loops unrolling */
+
+#define SHA256_SCR(i) \
+{ \
+ w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
+ + SHA256_F3(w[i - 15]) + w[i - 16]; \
+}
+
+#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \
+{ \
+ t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
+ + sha256_k[j] + w[j]; \
+ t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
+ wv[d] += t1; \
+ wv[h] = t1 + t2; \
+}
+
+typedef uint8_t uint8;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
+
+const static uint32 sha256_h0[8] = {
+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
+
+uint32 sha256_k[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
+
+/* sha2 */
+
+typedef struct {
+ unsigned int tot_len;
+ unsigned int len;
+ unsigned char block[2 * SHA256_BLOCK_SIZE];
+ uint32 h[8];
+} sha256_ctx;
+
+void sha256_transf(sha256_ctx *ctx, const unsigned char *message,
+ unsigned int block_nb)
+{
+ uint32 w[64];
+ uint32 wv[8];
+ uint32 t1, t2;
+ const unsigned char *sub_block;
+ int i;
+
+ for (i = 0; i < (int) block_nb; i++) {
+ sub_block = message + (i << 6);
+
+ PACK32(&sub_block[ 0], &w[ 0]); PACK32(&sub_block[ 4], &w[ 1]);
+ PACK32(&sub_block[ 8], &w[ 2]); PACK32(&sub_block[12], &w[ 3]);
+ PACK32(&sub_block[16], &w[ 4]); PACK32(&sub_block[20], &w[ 5]);
+ PACK32(&sub_block[24], &w[ 6]); PACK32(&sub_block[28], &w[ 7]);
+ PACK32(&sub_block[32], &w[ 8]); PACK32(&sub_block[36], &w[ 9]);
+ PACK32(&sub_block[40], &w[10]); PACK32(&sub_block[44], &w[11]);
+ PACK32(&sub_block[48], &w[12]); PACK32(&sub_block[52], &w[13]);
+ PACK32(&sub_block[56], &w[14]); PACK32(&sub_block[60], &w[15]);
+
+ SHA256_SCR(16); SHA256_SCR(17); SHA256_SCR(18); SHA256_SCR(19);
+ SHA256_SCR(20); SHA256_SCR(21); SHA256_SCR(22); SHA256_SCR(23);
+ SHA256_SCR(24); SHA256_SCR(25); SHA256_SCR(26); SHA256_SCR(27);
+ SHA256_SCR(28); SHA256_SCR(29); SHA256_SCR(30); SHA256_SCR(31);
+ SHA256_SCR(32); SHA256_SCR(33); SHA256_SCR(34); SHA256_SCR(35);
+ SHA256_SCR(36); SHA256_SCR(37); SHA256_SCR(38); SHA256_SCR(39);
+ SHA256_SCR(40); SHA256_SCR(41); SHA256_SCR(42); SHA256_SCR(43);
+ SHA256_SCR(44); SHA256_SCR(45); SHA256_SCR(46); SHA256_SCR(47);
+ SHA256_SCR(48); SHA256_SCR(49); SHA256_SCR(50); SHA256_SCR(51);
+ SHA256_SCR(52); SHA256_SCR(53); SHA256_SCR(54); SHA256_SCR(55);
+ SHA256_SCR(56); SHA256_SCR(57); SHA256_SCR(58); SHA256_SCR(59);
+ SHA256_SCR(60); SHA256_SCR(61); SHA256_SCR(62); SHA256_SCR(63);
+
+ wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
+ wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
+ wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
+ wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
+
+ SHA256_EXP(0,1,2,3,4,5,6,7, 0); SHA256_EXP(7,0,1,2,3,4,5,6, 1);
+ SHA256_EXP(6,7,0,1,2,3,4,5, 2); SHA256_EXP(5,6,7,0,1,2,3,4, 3);
+ SHA256_EXP(4,5,6,7,0,1,2,3, 4); SHA256_EXP(3,4,5,6,7,0,1,2, 5);
+ SHA256_EXP(2,3,4,5,6,7,0,1, 6); SHA256_EXP(1,2,3,4,5,6,7,0, 7);
+ SHA256_EXP(0,1,2,3,4,5,6,7, 8); SHA256_EXP(7,0,1,2,3,4,5,6, 9);
+ SHA256_EXP(6,7,0,1,2,3,4,5,10); SHA256_EXP(5,6,7,0,1,2,3,4,11);
+ SHA256_EXP(4,5,6,7,0,1,2,3,12); SHA256_EXP(3,4,5,6,7,0,1,2,13);
+ SHA256_EXP(2,3,4,5,6,7,0,1,14); SHA256_EXP(1,2,3,4,5,6,7,0,15);
+ SHA256_EXP(0,1,2,3,4,5,6,7,16); SHA256_EXP(7,0,1,2,3,4,5,6,17);
+ SHA256_EXP(6,7,0,1,2,3,4,5,18); SHA256_EXP(5,6,7,0,1,2,3,4,19);
+ SHA256_EXP(4,5,6,7,0,1,2,3,20); SHA256_EXP(3,4,5,6,7,0,1,2,21);
+ SHA256_EXP(2,3,4,5,6,7,0,1,22); SHA256_EXP(1,2,3,4,5,6,7,0,23);
+ SHA256_EXP(0,1,2,3,4,5,6,7,24); SHA256_EXP(7,0,1,2,3,4,5,6,25);
+ SHA256_EXP(6,7,0,1,2,3,4,5,26); SHA256_EXP(5,6,7,0,1,2,3,4,27);
+ SHA256_EXP(4,5,6,7,0,1,2,3,28); SHA256_EXP(3,4,5,6,7,0,1,2,29);
+ SHA256_EXP(2,3,4,5,6,7,0,1,30); SHA256_EXP(1,2,3,4,5,6,7,0,31);
+ SHA256_EXP(0,1,2,3,4,5,6,7,32); SHA256_EXP(7,0,1,2,3,4,5,6,33);
+ SHA256_EXP(6,7,0,1,2,3,4,5,34); SHA256_EXP(5,6,7,0,1,2,3,4,35);
+ SHA256_EXP(4,5,6,7,0,1,2,3,36); SHA256_EXP(3,4,5,6,7,0,1,2,37);
+ SHA256_EXP(2,3,4,5,6,7,0,1,38); SHA256_EXP(1,2,3,4,5,6,7,0,39);
+ SHA256_EXP(0,1,2,3,4,5,6,7,40); SHA256_EXP(7,0,1,2,3,4,5,6,41);
+ SHA256_EXP(6,7,0,1,2,3,4,5,42); SHA256_EXP(5,6,7,0,1,2,3,4,43);
+ SHA256_EXP(4,5,6,7,0,1,2,3,44); SHA256_EXP(3,4,5,6,7,0,1,2,45);
+ SHA256_EXP(2,3,4,5,6,7,0,1,46); SHA256_EXP(1,2,3,4,5,6,7,0,47);
+ SHA256_EXP(0,1,2,3,4,5,6,7,48); SHA256_EXP(7,0,1,2,3,4,5,6,49);
+ SHA256_EXP(6,7,0,1,2,3,4,5,50); SHA256_EXP(5,6,7,0,1,2,3,4,51);
+ SHA256_EXP(4,5,6,7,0,1,2,3,52); SHA256_EXP(3,4,5,6,7,0,1,2,53);
+ SHA256_EXP(2,3,4,5,6,7,0,1,54); SHA256_EXP(1,2,3,4,5,6,7,0,55);
+ SHA256_EXP(0,1,2,3,4,5,6,7,56); SHA256_EXP(7,0,1,2,3,4,5,6,57);
+ SHA256_EXP(6,7,0,1,2,3,4,5,58); SHA256_EXP(5,6,7,0,1,2,3,4,59);
+ SHA256_EXP(4,5,6,7,0,1,2,3,60); SHA256_EXP(3,4,5,6,7,0,1,2,61);
+ SHA256_EXP(2,3,4,5,6,7,0,1,62); SHA256_EXP(1,2,3,4,5,6,7,0,63);
+
+ ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
+ ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
+ ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
+ ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
+ }
+}
+
+void sha256_init(sha256_ctx *ctx)
+{
+ ctx->h[0] = sha256_h0[0]; ctx->h[1] = sha256_h0[1];
+ ctx->h[2] = sha256_h0[2]; ctx->h[3] = sha256_h0[3];
+ ctx->h[4] = sha256_h0[4]; ctx->h[5] = sha256_h0[5];
+ ctx->h[6] = sha256_h0[6]; ctx->h[7] = sha256_h0[7];
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void sha256_update(sha256_ctx *ctx, const unsigned char *message,
+ unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SHA256_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SHA256_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SHA256_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ sha256_transf(ctx, ctx->block, 1);
+ sha256_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SHA256_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 6],
+ rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 6;
+}
+
+void sha256_final(sha256_ctx *ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+ block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
+ < (ctx->len % SHA256_BLOCK_SIZE)));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 6;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ sha256_transf(ctx, ctx->block, block_nb);
+
+ UNPACK32(ctx->h[0], &digest[ 0]);
+ UNPACK32(ctx->h[1], &digest[ 4]);
+ UNPACK32(ctx->h[2], &digest[ 8]);
+ UNPACK32(ctx->h[3], &digest[12]);
+ UNPACK32(ctx->h[4], &digest[16]);
+ UNPACK32(ctx->h[5], &digest[20]);
+ UNPACK32(ctx->h[6], &digest[24]);
+ UNPACK32(ctx->h[7], &digest[28]);
+}
+
+void sha256(const unsigned char *message, unsigned int len, unsigned char *digest)
+{
+ sha256_ctx ctx;
+
+ sha256_init(&ctx);
+ sha256_update(&ctx, message, len);
+ sha256_final(&ctx, digest);
+}
+
+/* hmac-sha2 */
+
+typedef struct {
+ sha256_ctx ctx_inside;
+ sha256_ctx ctx_outside;
+
+ /* for hmac_reinit */
+ sha256_ctx ctx_inside_reinit;
+ sha256_ctx ctx_outside_reinit;
+
+ unsigned char block_ipad[SHA256_BLOCK_SIZE];
+ unsigned char block_opad[SHA256_BLOCK_SIZE];
+} hmac_sha256_ctx;
+
+void hmac_sha256_init(hmac_sha256_ctx *ctx, unsigned char *key)
+{
+ unsigned int num;
+
+ unsigned char *key_used;
+ int i;
+
+ key_used = key;
+ num = SHA256_BLOCK_SIZE;
+
+ for (i = 0; i < num; i++) {
+ ctx->block_ipad[i] = key_used[i] ^ 0x36;
+ ctx->block_opad[i] = key_used[i] ^ 0x5c;
+ }
+
+ sha256_init(&ctx->ctx_inside);
+ sha256_update(&ctx->ctx_inside, ctx->block_ipad, SHA256_BLOCK_SIZE);
+
+ sha256_init(&ctx->ctx_outside);
+ sha256_update(&ctx->ctx_outside, ctx->block_opad,
+ SHA256_BLOCK_SIZE);
+
+ /* for hmac_reinit */
+ memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside,
+ sizeof(sha256_ctx));
+ memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside,
+ sizeof(sha256_ctx));
+}
+
+void hmac_sha256_reinit(hmac_sha256_ctx *ctx)
+{
+ memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit,
+ sizeof(sha256_ctx));
+ memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit,
+ sizeof(sha256_ctx));
+}
+
+void hmac_sha256_update(hmac_sha256_ctx *ctx, unsigned char *message,
+ unsigned int message_len)
+{
+ sha256_update(&ctx->ctx_inside, message, message_len);
+}
+
+void hmac_sha256_final(hmac_sha256_ctx *ctx, unsigned char *mac,
+ unsigned int mac_size)
+{
+ unsigned char digest_inside[SHA256_DIGEST_SIZE];
+ unsigned char mac_temp[SHA256_DIGEST_SIZE];
+
+ sha256_final(&ctx->ctx_inside, digest_inside);
+ sha256_update(&ctx->ctx_outside, digest_inside, SHA256_DIGEST_SIZE);
+ sha256_final(&ctx->ctx_outside, mac_temp);
+ memcpy(mac, mac_temp, mac_size);
+}
+
+void hmac_sha256(unsigned char *key,
+ unsigned char *message, unsigned int message_len,
+ unsigned char *mac, unsigned mac_size)
+{
+ hmac_sha256_ctx ctx;
+
+ hmac_sha256_init(&ctx, key);
+ hmac_sha256_update(&ctx, message, message_len);
+ hmac_sha256_final(&ctx, mac, mac_size);
+}
diff --git a/Mac.h b/Mac.h
new file mode 100644
index 0000000..7f1df6a
--- /dev/null
+++ b/Mac.h
@@ -0,0 +1 @@
+char *Mac(const char *str);
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..592719c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,19 @@
+PROJ := oss.cgi
+OBJS := Oss.o Room.o Mac.o
+SRCS := $(OBJS:.o=.c)
+H := $(OBJS:.o=.h)
+
+CC := gcc
+CF := -Wall -O3 -fasm -fomit-frame-pointer -ffast-math -funroll-loops -fasm -fomit-frame-pointer -ffast-math -funroll-loops -pedantic -ansi
+
+default: $(PROJ)
+
+$(PROJ): $(OBJS)
+ $(CC) $(CF) -o $@ $(OBJS)
+
+.c.o:
+ $(CC) $(CF) -c $< -D NEIL #DEBUG
+
+.PHONY: clean
+clean:
+ -rm $(OBJS)
diff --git a/Oss.c b/Oss.c
new file mode 100644
index 0000000..8f5032b
--- /dev/null
+++ b/Oss.c
@@ -0,0 +1,475 @@
+/* Copyright 2000, 2009, 2011, 2012 Neil Edelman, distributed under the terms
+ of the GNU General Public License, see copying.txt */
+
+/* it's the OSS game, by Neil Edelman (Dec. 2000) */
+/* let's make it playable on the web (Dec 2009) */
+
+#include /* malloc free */
+#include /* fprintf */
+#include
+#include /* manipulating query strings */
+#include /* isalnum */
+#include /* time */
+#include "Oss.h"
+#include "Mac.h"
+#include "Room.h"
+
+/* constants */
+static const char *year = "2000, 2011, 2012";
+static const int versionMajor = 3;
+static const int versionMinor = 0;
+#define SCORES 8
+extern const int nowhereroom;
+extern const int startroom; /* def in Room */
+static const char *title = "OSS Game";
+static const char *inputname = "choice";
+static const char *exec = "oss.cgi";
+static const char *scorefile = "badass";
+static const unsigned long forget_time = 1024; /* about 15 minutes */
+/* my sever name */
+#ifdef NEIL
+static const char *valid = "http://neil.chaosnet.org/cgi-bin/oss-game/oss.cgi";
+static const char *start = "http://neil.chaosnet.org/cgi-bin/oss-game/";
+#endif
+
+/* private */
+struct Hi {
+ char last_ip[16]; /* xxx.xxx.xxx.xxx */
+ char last_game[HISTSIZE];
+ unsigned long last_time;
+ struct Oss score[SCORES];
+ int size;
+};
+
+/* C89 (in which we compile, maybe) doesn't have this prototype (pedantic) */
+/*int snprintf(char *str, size_t size, const char *format, ...);*/
+
+static void Oss(struct Oss *oss);
+static struct Oss *history(const char *history);
+static int osscomp(const struct Oss *a, const struct Oss *b);
+static char *query(void);
+static char *get_next(char **queryp, const char *want);
+static char *status(const struct Oss *o);
+static char load(struct Oss *oss);
+static int simplify(char *str);
+static void printoss(const struct Oss *oss);
+static int Hi(struct Hi *hi);
+static void HiPrint(struct Hi *hi);
+static void HiSave(struct Oss *oss);
+static void usage(const char *argvz);
+
+/** initialise */
+static void Oss(struct Oss *oss) {
+ if(!oss) return;
+ oss->room = startroom;
+ oss->flags = 0;
+ oss->points = 0;
+ oss->friends = 0;
+ oss->enemies = 0;
+ oss->education = 0;
+ oss->trouble = 0;
+ oss->history[0]= '\0';
+ oss->name[0] = '\0';
+}
+
+/** options */
+void OssMessage(const struct Oss *o, const char *message, ...) {
+ va_list ap;
+ char *option, letter = 'a';
+
+ /* print the text */
+ printf("%s
\n\n", message);
+ printf("
\n");
+}
+
+/* private */
+
+/** given a history in choices, let it play out and return the result */
+static struct Oss *history(const char *history) {
+ void (*fn)(struct Oss *, const char, const int);
+ static struct Oss oss;
+ char *h;
+
+ Oss(&oss);
+ for(h = (char *)history; *h; h++) {
+ if(!(fn = RoomFn(oss.room))) break;
+#ifdef DEBUG
+ printf("%s: %s(%c)
\n\n", RoomName(oss.room), h, *h);
+ printoss(&oss);
+#endif
+ (*fn)(&oss, *h, 0);
+ }
+ return &oss;
+}
+
+/** compares the oss games, returns 0 if they're equal */
+static int osscomp(const struct Oss *a, const struct Oss *b) {
+ if(!a || !b) return 1;
+ if(a->room != b->room) return -1;
+ if(a->points != b->points) return -2;
+ if(a->friends != b->friends) return -3;
+ if(a->enemies != b->enemies) return -4;
+ if(a->education != b->education) return -5;
+ if(a->trouble != b->trouble) return -6;
+ if(a->flags != b->flags) return -7;
+ return 0;
+}
+
+/** get the query string */
+static char *query(void) {
+ /*'mac=[64]&room=xx&flags=xxxx&points=xxx&friends=xxx&ememies=xxx&education=xxx&trouble=xxx&choice=xx'*/
+ /*'mac=[64]&room=xx&flags=xxxx&points=xxx&friends=xxx&ememies=xxx&education=xxx&trouble=xxx&name=xxxxxxx'*/
+ static char post[192];
+ char *query = 0, *method;
+
+ if(!(method = getenv("REQUEST_METHOD"))) return 0;
+ if(!strcmp("POST", method)) {
+ fgets(post, sizeof(post), stdin);
+ query = post;
+ } else if(!strcmp("GET", method)) {
+ query = getenv("QUERY_STRING");
+ } else {
+ printf("Undefined request method, "%s."
\n\n", method);
+ }
+
+ return query;
+}
+
+/** gets a query string "want" and advances the queryPtr, or does nothing if
+ "want" is not arg */
+static char *get_next(char **queryp, const char *want) {
+ char *thing = 0, *query;
+
+ /* paranoid */
+ if(!queryp || !(query = *queryp) || !want) return 0;
+ /* thing is at '=', make sure the 'want' is actually what we have */
+ if(!(thing = strpbrk(query, "="))) return 0;
+ if(strncmp(query, want, thing - query)) return 0;
+ thing++;
+ /* move to the next arg, return it and advance the query */
+ if((query = strpbrk(thing, "&"))) {
+ *query = '\0';
+ query++;
+ *queryp = query;
+ } else {
+ *queryp = 0;
+ }
+
+ return thing;
+}
+
+/** for MAC */
+static char *status(const struct Oss *o) {
+ static char status[64];
+ /* rXXfXXpXXfXXeXXeXXtXX */
+ snprintf(status, 64, "r%df%dp%df%de%de%dt%d", o->room, o->flags,
+ o->points, o->friends, o->enemies, o->education, o->trouble);
+ return status;
+}
+
+/** load game */
+static char load(struct Oss *oss) {
+ char *env, *q;
+ char *sRoom, *sFlags, *sPoints, *sFriends, *sEnemies, *sEducation;
+ char *sTrouble, *sChoice, *sHistory, choice;
+ char *sMac, *cMac, *sName;
+ int histSize;
+ struct Oss *check;
+
+ /* initial game state */
+ Oss(oss);
+ /* check env vars */
+ if(!(env = getenv("REQUEST_METHOD")) || strcmp(env, "POST")) return 0;
+ /* not valid referrer, show the hi-scores */
+#ifdef NEIL
+ if(!(env = getenv("HTTP_REFERER")) || strncmp(env, valid, strlen(valid))) {
+ struct Hi hi;
+ if(Hi(&hi)) HiPrint(&hi);
+ else printf("Error loading high scores.
\n\n");
+ printf("Go back to the start of OSS game.
", start);
+ printf("