~ysu/gemini-chatroom

91028756563599c78745ae4d5447ab09b88a7403 — vps 3 years ago a680799
rewrote in c
9 files changed, 193 insertions(+), 50 deletions(-)

A bin/chat0/Makefile
A bin/chat0/TODO
A bin/chat0/config.h
D bin/chat0/index.gmi
D bin/chat0/post
A bin/chat0/post.c
D bin/chat0/postuser
A bin/chat0/postuser.c
A bin/chat0/view.c
A bin/chat0/Makefile => bin/chat0/Makefile +15 -0
@@ 0,0 1,15 @@
all: index.gmi post postuser

CFLAGS=-O3 -Wall -Wextra -pedantic -Wpedantic

index.gmi: view.c config.h
	cc $(CFLAGS) view.c -o index.gmi

post: post.c config.h
	cc $(CFLAGS) post.c -o post

postuser: postuser.c config.h
	cc $(CFLAGS) postuser.c -o postuser

clean:
	rm -f index.gmi post postuser

A bin/chat0/TODO => bin/chat0/TODO +3 -0
@@ 0,0 1,3 @@
[ ] Implement spam protection
[ ] Implement multi line support
[ ] add message ids

A bin/chat0/config.h => bin/chat0/config.h +4 -0
@@ 0,0 1,4 @@
#pragma once

#define CHAT_NUM "2"
#define BUFF_SIZE 600

D bin/chat0/index.gmi => bin/chat0/index.gmi +0 -14
@@ 1,14 0,0 @@
#! /bin/dash

echo "20 text/gemini\r\n"
echo "# Chatroom 0"
echo "=> postuser post"
echo "=> post post anonymously"
echo "=> $GEMINI_URL refresh"
printf "\n"

echo ---
echo "\`\`\` Messages"
tac message_log | awk '$1 != '\n' {print $0}'
echo "\`\`\`"
echo ---

D bin/chat0/post => bin/chat0/post +0 -24
@@ 1,24 0,0 @@
#! /bin/bash

chatNum=0

if [ -z "$QUERY_STRING" ]; then
	echo -e "10 Message\r\n"
fi

user=$(echo $PATH_INFO | cut -d '/' -f 2)

if [ -z "$user" ]; then
	user="anon"
fi

nstr=$(echo $QUERY_STRING | sed 's/\(%0A\|
\)/ /g' | sed 's/%/\\x/g')
nuser=$(echo ${user//[!A-z]/})

if [ $(cat last_message) != $nstr ]; then
	printf "($(date "+%Y/%m/%d %R %Z")) $(echo $nuser: $nstr | awk '{printf "%9s %s\n", $1, $2}')\n" >> message_log
	echo $nstr > last_message
	echo -e "30 /bin/chat$chatNum\r\n"
else
	echo -e "40 Message failed! Reason: Spam protection\r\n"
fi

A bin/chat0/post.c => bin/chat0/post.c +95 -0
@@ 0,0 1,95 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "config.h"

char *
removeExtraChars(char user[9])
{
	static char nUser[9];
	unsigned int nUserLen = 0;

	for (unsigned int i = 0; i < 9; i++) {
		if ((user[i] >= 'a' && user[i] <= 'z') || (user[i] >= 'A' && user[i] <= 'Z') || (user[i] >= '0' && user[i] <= '9'))
			nUser[nUserLen++] = user[i];
		else if (user[i] == '\0')
			break;
	}
	return nUser;
}

void
convert(char *str, char **nstr)
{ /* free ret after */
	size_t strsize = strlen(str), retsize = 0;
	char *ret = malloc(strsize);
	char tmp[2];

	for (unsigned int i = 0; i < strsize; i++) {
		if (str[i] == '%') {
			ret = realloc(ret, ++retsize);
			tmp[0] = str[++i];
			tmp[1] = str[++i];
			sscanf(tmp, "%x", (unsigned int *)&ret[retsize - 1]);
		} else  ret[retsize++] = str[i];
	}
	ret[retsize] = '\0';
	*nstr = ret;
}

void
getTime(char **timestr)
{
	time_t t = time(NULL);
	struct tm tm = *localtime(&t);
	sprintf(*timestr, "(%d/%02d/%02d %02d:%02d)", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min);
}

int
main()
{
	/* variables */
	char *PATH_INFO = getenv("PATH_INFO");
	char *QUERY_STRING = getenv("QUERY_STRING");
	char user[9];
	FILE *ml;

	/* get username */
	if (PATH_INFO == NULL || !strcmp(PATH_INFO, ""))
		memcpy(user, "anon\0", 5);
	else {
		if (strlen(PATH_INFO) > 9) {
			puts("40 Message failed! Reason: Username must be below 9 characters\r");
			exit(0);
		} else memcpy(user, removeExtraChars(PATH_INFO), 9);
	}

	/* get input */
	if (QUERY_STRING == NULL)
		puts("10 Message\r");
	if (QUERY_STRING == NULL)
		exit(0);

	/* 
	 * write message to file
	 */
	ml = fopen("message_log", "a");
	/* get time */
	char *timestr = malloc(19);
	getTime(&timestr);

	/* replace % with \x */
	char *message;
	convert(QUERY_STRING, &message);

	/* print to file */
	fprintf(ml, "%s %8s: %s\n", timestr, user, message);
	free(timestr);
	free(message);
	fclose(ml);

	/* redirect back to messages */
	puts("30 /bin/chat"CHAT_NUM"/\r");
}

D bin/chat0/postuser => bin/chat0/postuser +0 -12
@@ 1,12 0,0 @@
#! /bin/dash

if [ -z $QUERY_STRING ]; then
	echo "10 Username\r\n"
fi

if [ ${#QUERY_STRING} -gt 9 ]; then
	echo "40 Message failed! Reason: Username must be below 9 characters\r\n"
	exit 0
fi

echo "30 post/$QUERY_STRING\r\n"

A bin/chat0/postuser.c => bin/chat0/postuser.c +11 -0
@@ 0,0 1,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int
main()
{
	if (getenv("QUERY_STRING") == NULL)
		puts("10 username \r");
	printf("30 post/%s\r\n", getenv("QUERY_STRING"));
}

A bin/chat0/view.c => bin/chat0/view.c +65 -0
@@ 0,0 1,65 @@
#include <stdio.h>
#include <string.h>

#include "config.h"

char *
fgetsr(char *str, unsigned int size, FILE *fp)	/* fgets, reversed */
{
	/* Stop if we're at the beginning of the file */
	if (ftell(fp) == 0)
		return NULL;

	unsigned int i;
	for (i = 0; ftell(fp) != 0 && i < size; i++ ) {
		fseek(fp, -1, SEEK_CUR);
		str[i] = (char)fgetc(fp);

		if (str[i] == '\n' && i != 0 ) {
		    break;
		}

		fseek(fp, -1, SEEK_CUR);
	}
	str[i] = '\0';
	return str;
}

void
reverseStr(char *start)
{
	size_t len = strlen(start);

	for (char *end = &start[len - 1]; start < end; start++, end--) {
		char tmp = start[0];
		start[0] = end[0];
		end[0] = tmp;
	}
}

int
main()
{
	/* open file and navigate to the end */
	FILE *ml = fopen("message_log", "r");	/* message log */
	fseek(ml, 0, SEEK_END);
 
	/* write links */
	puts("20 text/gemini\r");
	puts("# Chatroom 0");
	puts("=> postuser post");
	puts("=> post post anonymously");
	puts("=> /bin/chat"CHAT_NUM"/ refresh\n");

	/* print file backwards */
	char buff[BUFF_SIZE];
	puts("---");
	puts("``` messages");
	while (fgetsr(buff, BUFF_SIZE, ml) != NULL) {
		reverseStr(buff);
		printf("%s", buff);
	}
	fclose(ml);
	puts("```");
	puts("---");
}