Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "cbook-main.h"
- char *rasprintf(const char *f, ...) {
- char *r = NULL;
- va_list a;
- va_start(a, f);
- vasprintf(&r, f, a);
- va_end(a);
- return r;
- }
- char *htmlEscape(char *s) {
- char *r = malloc(32);
- /*
- l = original string length
- i = current byte of original string
- j = current byte of new string
- b = allocated bytes for new string
- */
- long l = strlen(s), i, j, b = 32;
- for (i = 0, j = 0; i < l; i++) {
- if (j == b - 7) // we could need up to 6 chars
- r = realloc(r, b *= 2);
- if (s[i] == '&') {
- strcpy(&r[j], "&");
- j += 5;
- } else if (s[i] == '<') {
- strcpy(&r[j], "<");
- j += 4;
- } else if (s[i] == '>') {
- strcpy(&r[j], ">");
- j += 4;
- } else if (s[i] == '"') {
- strcpy(&r[j], """);
- j += 6;
- } else if (s[i] == '\'') {
- strcpy(&r[j], "'");
- j += 6;
- } else r[j++] = s[i];
- }
- r[j] = 0;
- return r;
- }
- void printHtml(char *s) {
- char *escaped = htmlEscape(s);
- fputs(escaped, stdout);
- free(escaped);
- }
- void parseConf() {
- cfg_opt_t opts[] = {
- CFG_SIMPLE_STR("mysqlHostname", &config.mysqlHostname),
- CFG_SIMPLE_STR("mysqlUsername", &config.mysqlUsername),
- CFG_SIMPLE_STR("mysqlPassword", &config.mysqlPassword),
- CFG_SIMPLE_STR("mysqlDatabase", &config.mysqlDatabase),
- CFG_SIMPLE_STR("siteName", &config.siteName),
- CFG_END()
- };
- cfg_t *cfg = cfg_init(opts, 0);
- cfg_parse(cfg, CBOOK_CONFFILE);
- }
- void myerror() {
- printf("error: mysql: %u: %s\n", mysql_errno(mysql), mysql_error(mysql));
- exit(1);
- }
- char *myescape(char *q) {
- unsigned long l = strlen(q);
- char *r = malloc(l * 2 + 1);
- unsigned long rl = mysql_real_escape_string(mysql, r, q, l);
- r = realloc(r, rl + 1);
- return r;
- }
- void fail(const char *s) {
- puts(s);
- exit(1);
- }
- void myquery(const char *f, ...) {
- va_list a;
- va_start(a, f);
- char *q = NULL;
- vasprintf(&q, f, a);
- va_end(a);
- if (!q) {
- puts("error: query: vasprintf returned null");
- exit(1);
- }
- if (mysql_query(mysql, q)) myerror();
- free(q);
- }
- void createDatabase() {
- myquery("create database %s character set utf8 collate utf8_general_ci", config.mysqlDatabase);
- if (mysql_select_db(mysql, config.mysqlDatabase)) myerror();
- myquery("create table bookings (\n\
- id bigint not null auto_increment primary key,\n\
- item bigint not null,\n\
- year bigint not null,\n\
- month bigint not null,\n\
- date bigint not null,\n\
- session bigint not null\n\
- )");
- myquery("create table sessions (\n\
- id bigint not null auto_increment primary key,\n\
- name longtext not null\n\
- )");
- }
- void pageHeader(char *title) {
- puts("Content-type: text/html\n");
- puts("<!DOCTYPE html>");
- puts("<html>");
- puts("\t<head>");
- puts("\t\t<meta charset=\"utf-8\">");
- printf("\t\t<title>cbook: ");
- printHtml(config.siteName);
- printf(": ");
- printHtml(title);
- puts("</title>");
- puts("\t\t<style>");
- puts("\t\t\tbody { font-family: sans-serif; font-size: 0.75em; }");
- puts("\t\t\ttable { border-collapse: collapse; margin: 1em 0em; }");
- puts("\t\t\ttd, th { border: 1px solid black; padding: 0.5em; }");
- puts("\t\t</style>");
- puts("\t</head>");
- puts("\t<body>");
- printf("\t\t<h1>cbook: <a href=\"?\">");
- printHtml(config.siteName);
- puts("</a></h1>");
- }
- void pageFooter() {
- puts("\t\t<pre>");
- printQueryHash();
- puts("\t\t</pre>");
- puts("\t</body>");
- puts("</html>");
- }
- void pageHome() {
- pageHeader("home");
- long i;
- MYSQL_RES *res;
- MYSQL_ROW row;
- puts("\t\t<table>");
- puts("\t\t\t<tr>");
- puts("\t\t\t\t<th>");
- for (i = 0; i < 7; i++)
- printf("\t\t\t\t<th>%s\n", constDays[i]);
- myquery("select * from sessions");
- res = mysql_store_result(mysql);
- long hasSessions = 0;
- while (row = mysql_fetch_row(res)) {
- hasSessions = 1;
- puts("\t\t\t<tr>");
- printf("\t\t\t\t<th>");
- printHtml(row[1]);
- printf("\n");
- for (i = 0; i < 7; i++)
- puts("\t\t\t\t<td>");
- }
- if (!hasSessions) {
- puts("\t\t\t<tr>");
- puts("\t\t\t\t<td colspan=\"8\">No sessions available. <a href=\"?p=sessions\">Add some.</a>");
- }
- puts("\t\t</table>");
- mysql_free_result(res);
- pageFooter();
- }
- void pageSessions() {
- pageHeader("sessions");
- MYSQL_RES *res;
- MYSQL_ROW row;
- puts("\t\t<h2>sessions</h2>");
- puts("\t\t<form>");
- puts("\t\t\t<input type=\"hidden\" name=\"p\" value=\"session_add\">");
- puts("\t\t\t<input name=\"name\">");
- puts("\t\t\t<input type=\"submit\" value=\"Add session\">");
- puts("\t\t</form>");
- puts("\t\t<script>");
- puts("\t\t\tdocument.getElementsByName('name')[0].focus();");
- puts("\t\t</script>");
- puts("\t\t<table>");
- puts("\t\t\t<tr>");
- puts("\t\t\t\t<th>id");
- puts("\t\t\t\t<th>session name");
- myquery("select * from sessions");
- res = mysql_store_result(mysql);
- while (row = mysql_fetch_row(res)) {
- puts("\t\t\t<tr>");
- printf("\t\t\t\t<td>");
- printHtml(row[0]);
- printf("\t\t\t\t<td>");
- printHtml(row[1]);
- printf("\n");
- }
- puts("\t\t</table>");
- pageFooter();
- }
- void pageSessionAdd() {
- char *v = g_hash_table_lookup(queryHash, "name");
- v = myescape(v);
- myquery("insert into sessions (name) values ('%s')", v);
- free(v);
- puts("Location: ?p=sessions\n");
- }
- void parseQueryString() {
- queryHash = g_hash_table_new(g_str_hash, g_str_equal);
- char *s = getenv("QUERY_STRING");
- long state = DQUERY_STATE_KEY, i, j = 0, k = 0, l = strlen(s);
- for (i = 0; i <= l; i++) {
- switch (state) {
- case DQUERY_STATE_KEY:
- if (s[i] == '&' || s[i] == 0) {
- g_hash_table_insert(queryHash, urlDecode(strndup(&s[j], i - j)), NULL);
- j = i + 1;
- } else if (s[i] == '=') {
- k = i + 1;
- state = DQUERY_STATE_VALUE;
- }
- break;
- case DQUERY_STATE_VALUE:
- if (s[i] == '&' || s[i] == 0) {
- g_hash_table_insert(queryHash, urlDecode(strndup(&s[j], k - j - 1)), urlDecode(strndup(&s[k], i - k)));
- j = i + 1;
- state = DQUERY_STATE_KEY;
- }
- break;
- default:
- fail("error: parseQueryString: invalid state");
- }
- }
- }
- void printQueryHash() {
- printf("query: '%s'\n", getenv("QUERY_STRING"));
- printf("query hash size: %u\n", g_hash_table_size(queryHash));
- g_hash_table_foreach(queryHash, printQueryHashHelper, NULL);
- }
- void printQueryHashHelper(gpointer key, gpointer value, gpointer user) {
- printf("'%s' = '%s'\n", (char *) key, (char *) value);
- }
- char *urlDecode(char *s) {
- long i, l = strlen(s), state = 0, offset = 0, byte = 0;
- for (i = 0; i <= l; i++) {
- switch (state) {
- case DURI_STATE_WAIT:
- if (s[i + offset] == '%')
- state = DURI_STATE_FIRST;
- else if (s[i + offset] == '+')
- s[i] = ' ';
- else
- s[i] = s[i + offset];
- break;
- case DURI_STATE_FIRST:
- if (s[i + offset] == 0)
- fail("error: urlDecode: string ended waiting for first byte of percent escape");
- if (s[i + offset] != '0' && s[i + offset] != '1' && s[i + offset] != '2' && s[i + offset] != '3' &&
- s[i + offset] != '4' && s[i + offset] != '5' && s[i + offset] != '6' && s[i + offset] != '7' &&
- s[i + offset] != '8' && s[i + offset] != '9' && s[i + offset] != 'A' && s[i + offset] != 'B' &&
- s[i + offset] != 'C' && s[i + offset] != 'D' && s[i + offset] != 'E' && s[i + offset] != 'F' &&
- s[i + offset] != 'a' && s[i + offset] != 'b' && s[i + offset] != 'c' && s[i + offset] != 'd' &&
- s[i + offset] != 'e' && s[i + offset] != 'f') fail("error: urlDecode: expecting first byte to be [0-9A-Fa-f]");
- byte = (s[i + offset] >= '0' && s[i + offset] <= '9') ? ((s[i + offset] - '0') << 4) :
- (s[i + offset] >= 'A' && s[i + offset] <= 'F') ? ((10 + s[i + offset] - 'A') << 4):
- (s[i + offset] >= 'a' && s[i + offset] <= 'f') ? ((10 + s[i + offset] - 'a') << 4) : 0;
- state = DURI_STATE_SECOND;
- break;
- case DURI_STATE_SECOND:
- if (s[i + offset] == 0)
- fail("error: urlDecode: string ended waiting for second byte of percent escape");
- if (s[i + offset] != '0' && s[i + offset] != '1' && s[i + offset] != '2' && s[i + offset] != '3' &&
- s[i + offset] != '4' && s[i + offset] != '5' && s[i + offset] != '6' && s[i + offset] != '7' &&
- s[i + offset] != '8' && s[i + offset] != '9' && s[i + offset] != 'A' && s[i + offset] != 'B' &&
- s[i + offset] != 'C' && s[i + offset] != 'D' && s[i + offset] != 'E' && s[i + offset] != 'F' &&
- s[i + offset] != 'a' && s[i + offset] != 'b' && s[i + offset] != 'c' && s[i + offset] != 'd' &&
- s[i + offset] != 'e' && s[i + offset] != 'f') fail("error: urlDecode: expecting second byte to be [0-9A-Fa-f]");
- byte |= (s[i + offset] >= '0' && s[i + offset] <= '9') ? (s[i + offset] - '0') :
- (s[i + offset] >= 'A' && s[i + offset] <= 'F') ? (10 + s[i + offset] - 'A'):
- (s[i + offset] >= 'a' && s[i + offset] <= 'f') ? (10 + s[i + offset] - 'a') : 0;
- i -= 2;
- offset += 2;
- s[i] = byte;
- state = DURI_STATE_WAIT;
- break;
- default:
- fail("error: urlDecode: invalid state");
- }
- }
- return s;
- }
- int main(int argc, char **argv) {
- parseConf();
- parseQueryString();
- mysql = mysql_init(NULL);
- if (!mysql) myerror();
- if (!mysql_real_connect(mysql, config.mysqlHostname, config.mysqlUsername, config.mysqlPassword, NULL, 0, NULL, 0)) myerror();
- if (mysql_select_db(mysql, config.mysqlDatabase)) createDatabase();
- char *page = g_hash_table_lookup(queryHash, "p");
- if (page)
- if (!strcmp(page, "sessions")) pageSessions();
- else if (!strcmp(page, "session_add")) pageSessionAdd();
- else pageHome();
- else pageHome();
- mysql_close(mysql);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement