Advertisement
Guest User

Untitled

a guest
Jan 7th, 2011
136
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.35 KB | None | 0 0
  1. #include "cbook-main.h"
  2.  
  3. char *rasprintf(const char *f, ...) {
  4.     char *r = NULL;
  5.     va_list a;
  6.     va_start(a, f);
  7.     vasprintf(&r, f, a);
  8.     va_end(a);
  9.     return r;
  10. }
  11. char *htmlEscape(char *s) {
  12.     char *r = malloc(32);
  13.     /*
  14.         l = original string length
  15.         i = current byte of original string
  16.         j = current byte of new string
  17.         b = allocated bytes for new string
  18.     */
  19.     long l = strlen(s), i, j, b = 32;
  20.     for (i = 0, j = 0; i < l; i++) {
  21.         if (j == b - 7) // we could need up to 6 chars
  22.             r = realloc(r, b *= 2);
  23.         if (s[i] == '&') {
  24.             strcpy(&r[j], "&amp;");
  25.             j += 5;
  26.         } else if (s[i] == '<') {
  27.             strcpy(&r[j], "&lt;");
  28.             j += 4;
  29.         } else if (s[i] == '>') {
  30.             strcpy(&r[j], "&gt;");
  31.             j += 4;
  32.         } else if (s[i] == '"') {
  33.             strcpy(&r[j], "&quot;");
  34.             j += 6;
  35.         } else if (s[i] == '\'') {
  36.             strcpy(&r[j], "&apos;");
  37.             j += 6;
  38.         } else r[j++] = s[i];
  39.     }
  40.     r[j] = 0;
  41.     return r;
  42. }
  43. void printHtml(char *s) {
  44.     char *escaped = htmlEscape(s);
  45.     fputs(escaped, stdout);
  46.     free(escaped);
  47. }
  48. void parseConf() {
  49.     cfg_opt_t opts[] = {
  50.         CFG_SIMPLE_STR("mysqlHostname", &config.mysqlHostname),
  51.         CFG_SIMPLE_STR("mysqlUsername", &config.mysqlUsername),
  52.         CFG_SIMPLE_STR("mysqlPassword", &config.mysqlPassword),
  53.         CFG_SIMPLE_STR("mysqlDatabase", &config.mysqlDatabase),
  54.         CFG_SIMPLE_STR("siteName", &config.siteName),
  55.         CFG_END()
  56.     };
  57.     cfg_t *cfg = cfg_init(opts, 0);
  58.     cfg_parse(cfg, CBOOK_CONFFILE);
  59. }
  60. void myerror() {
  61.     printf("error: mysql: %u: %s\n", mysql_errno(mysql), mysql_error(mysql));
  62.     exit(1);
  63. }
  64. char *myescape(char *q) {
  65.     unsigned long l = strlen(q);
  66.     char *r = malloc(l * 2 + 1);
  67.     unsigned long rl = mysql_real_escape_string(mysql, r, q, l);
  68.     r = realloc(r, rl + 1);
  69.     return r;
  70. }
  71. void fail(const char *s) {
  72.     puts(s);
  73.     exit(1);
  74. }
  75. void myquery(const char *f, ...) {
  76.     va_list a;
  77.     va_start(a, f);
  78.     char *q = NULL;
  79.     vasprintf(&q, f, a);
  80.     va_end(a);
  81.     if (!q) {
  82.         puts("error: query: vasprintf returned null");
  83.         exit(1);
  84.     }
  85.     if (mysql_query(mysql, q)) myerror();
  86.     free(q);
  87. }
  88. void createDatabase() {
  89.     myquery("create database %s character set utf8 collate utf8_general_ci", config.mysqlDatabase);
  90.     if (mysql_select_db(mysql, config.mysqlDatabase)) myerror();
  91.     myquery("create table bookings (\n\
  92.         id bigint not null auto_increment primary key,\n\
  93.         item bigint not null,\n\
  94.         year bigint not null,\n\
  95.         month bigint not null,\n\
  96.         date bigint not null,\n\
  97.         session bigint not null\n\
  98.     )");
  99.     myquery("create table sessions (\n\
  100.         id bigint not null auto_increment primary key,\n\
  101.         name longtext not null\n\
  102.     )");
  103. }
  104. void pageHeader(char *title) {
  105.     puts("Content-type: text/html\n");
  106.     puts("<!DOCTYPE html>");
  107.     puts("<html>");
  108.     puts("\t<head>");
  109.     puts("\t\t<meta charset=\"utf-8\">");
  110.     printf("\t\t<title>cbook: ");
  111.     printHtml(config.siteName);
  112.     printf(": ");
  113.     printHtml(title);
  114.     puts("</title>");
  115.     puts("\t\t<style>");
  116.     puts("\t\t\tbody { font-family: sans-serif; font-size: 0.75em; }");
  117.     puts("\t\t\ttable { border-collapse: collapse; margin: 1em 0em; }");
  118.     puts("\t\t\ttd, th { border: 1px solid black; padding: 0.5em; }");
  119.     puts("\t\t</style>");
  120.     puts("\t</head>");
  121.     puts("\t<body>");
  122.     printf("\t\t<h1>cbook: <a href=\"?\">");
  123.     printHtml(config.siteName);
  124.     puts("</a></h1>");
  125. }
  126. void pageFooter() {
  127.     puts("\t\t<pre>");
  128.     printQueryHash();
  129.     puts("\t\t</pre>");
  130.     puts("\t</body>");
  131.     puts("</html>");
  132. }
  133. void pageHome() {
  134.     pageHeader("home");
  135.     long i;
  136.     MYSQL_RES *res;
  137.     MYSQL_ROW row;
  138.     puts("\t\t<table>");
  139.     puts("\t\t\t<tr>");
  140.     puts("\t\t\t\t<th>");
  141.     for (i = 0; i < 7; i++)
  142.         printf("\t\t\t\t<th>%s\n", constDays[i]);
  143.     myquery("select * from sessions");
  144.     res = mysql_store_result(mysql);
  145.     long hasSessions = 0;
  146.     while (row = mysql_fetch_row(res)) {
  147.         hasSessions = 1;
  148.         puts("\t\t\t<tr>");
  149.         printf("\t\t\t\t<th>");
  150.         printHtml(row[1]);
  151.         printf("\n");
  152.         for (i = 0; i < 7; i++)
  153.             puts("\t\t\t\t<td>");
  154.     }
  155.     if (!hasSessions) {
  156.         puts("\t\t\t<tr>");
  157.         puts("\t\t\t\t<td colspan=\"8\">No sessions available. <a href=\"?p=sessions\">Add some.</a>");
  158.     }
  159.     puts("\t\t</table>");
  160.     mysql_free_result(res);
  161.     pageFooter();
  162. }
  163. void pageSessions() {
  164.     pageHeader("sessions");
  165.     MYSQL_RES *res;
  166.     MYSQL_ROW row;
  167.     puts("\t\t<h2>sessions</h2>");
  168.     puts("\t\t<form>");
  169.     puts("\t\t\t<input type=\"hidden\" name=\"p\" value=\"session_add\">");
  170.     puts("\t\t\t<input name=\"name\">");
  171.     puts("\t\t\t<input type=\"submit\" value=\"Add session\">");
  172.     puts("\t\t</form>");
  173.     puts("\t\t<script>");
  174.     puts("\t\t\tdocument.getElementsByName('name')[0].focus();");
  175.     puts("\t\t</script>");
  176.     puts("\t\t<table>");
  177.     puts("\t\t\t<tr>");
  178.     puts("\t\t\t\t<th>id");
  179.     puts("\t\t\t\t<th>session name");
  180.     myquery("select * from sessions");
  181.     res = mysql_store_result(mysql);
  182.     while (row = mysql_fetch_row(res)) {
  183.         puts("\t\t\t<tr>");
  184.         printf("\t\t\t\t<td>");
  185.         printHtml(row[0]);
  186.         printf("\t\t\t\t<td>");
  187.         printHtml(row[1]);
  188.         printf("\n");
  189.     }
  190.     puts("\t\t</table>");
  191.     pageFooter();
  192. }
  193. void pageSessionAdd() {
  194.     char *v = g_hash_table_lookup(queryHash, "name");
  195.     v = myescape(v);
  196.     myquery("insert into sessions (name) values ('%s')", v);
  197.     free(v);
  198.     puts("Location: ?p=sessions\n");
  199. }
  200. void parseQueryString() {
  201.     queryHash = g_hash_table_new(g_str_hash, g_str_equal);
  202.     char *s = getenv("QUERY_STRING");
  203.     long state = DQUERY_STATE_KEY, i, j = 0, k = 0, l = strlen(s);
  204.     for (i = 0; i <= l; i++) {
  205.         switch (state) {
  206.             case DQUERY_STATE_KEY:
  207.                 if (s[i] == '&' || s[i] == 0) {
  208.                     g_hash_table_insert(queryHash, urlDecode(strndup(&s[j], i - j)), NULL);
  209.                     j = i + 1;
  210.                 } else if (s[i] == '=') {
  211.                     k = i + 1;
  212.                     state = DQUERY_STATE_VALUE;
  213.                 }
  214.                 break;
  215.             case DQUERY_STATE_VALUE:
  216.                 if (s[i] == '&' || s[i] == 0) {
  217.                     g_hash_table_insert(queryHash, urlDecode(strndup(&s[j], k - j - 1)), urlDecode(strndup(&s[k], i - k)));
  218.                     j = i + 1;
  219.                     state = DQUERY_STATE_KEY;
  220.                 }
  221.                 break;
  222.             default:
  223.                 fail("error: parseQueryString: invalid state");
  224.         }
  225.     }
  226. }
  227. void printQueryHash() {
  228.     printf("query: '%s'\n", getenv("QUERY_STRING"));
  229.     printf("query hash size: %u\n", g_hash_table_size(queryHash));
  230.     g_hash_table_foreach(queryHash, printQueryHashHelper, NULL);
  231. }
  232. void printQueryHashHelper(gpointer key, gpointer value, gpointer user) {
  233.     printf("'%s' = '%s'\n", (char *) key, (char *) value);
  234. }
  235. char *urlDecode(char *s) {
  236.     long i, l = strlen(s), state = 0, offset = 0, byte = 0;
  237.     for (i = 0; i <= l; i++) {
  238.         switch (state) {
  239.             case DURI_STATE_WAIT:
  240.                 if (s[i + offset] == '%')
  241.                     state = DURI_STATE_FIRST;
  242.                 else if (s[i + offset] == '+')
  243.                     s[i] = ' ';
  244.                 else
  245.                     s[i] = s[i + offset];
  246.                 break;
  247.             case DURI_STATE_FIRST:
  248.                 if (s[i + offset] == 0)
  249.                     fail("error: urlDecode: string ended waiting for first byte of percent escape");
  250.                 if (s[i + offset] != '0' && s[i + offset] != '1' && s[i + offset] != '2' && s[i + offset] != '3' &&
  251.                     s[i + offset] != '4' && s[i + offset] != '5' && s[i + offset] != '6' && s[i + offset] != '7' &&
  252.                     s[i + offset] != '8' && s[i + offset] != '9' && s[i + offset] != 'A' && s[i + offset] != 'B' &&
  253.                     s[i + offset] != 'C' && s[i + offset] != 'D' && s[i + offset] != 'E' && s[i + offset] != 'F' &&
  254.                     s[i + offset] != 'a' && s[i + offset] != 'b' && s[i + offset] != 'c' && s[i + offset] != 'd' &&
  255.                     s[i + offset] != 'e' && s[i + offset] != 'f') fail("error: urlDecode: expecting first byte to be [0-9A-Fa-f]");
  256.                 byte = (s[i + offset] >= '0' && s[i + offset] <= '9') ? ((s[i + offset] - '0') << 4) :
  257.                         (s[i + offset] >= 'A' && s[i + offset] <= 'F') ? ((10 + s[i + offset] - 'A') << 4):
  258.                         (s[i + offset] >= 'a' && s[i + offset] <= 'f') ? ((10 + s[i + offset] - 'a') << 4) : 0;
  259.                 state = DURI_STATE_SECOND;
  260.                 break;
  261.             case DURI_STATE_SECOND:
  262.                 if (s[i + offset] == 0)
  263.                     fail("error: urlDecode: string ended waiting for second byte of percent escape");
  264.                 if (s[i + offset] != '0' && s[i + offset] != '1' && s[i + offset] != '2' && s[i + offset] != '3' &&
  265.                     s[i + offset] != '4' && s[i + offset] != '5' && s[i + offset] != '6' && s[i + offset] != '7' &&
  266.                     s[i + offset] != '8' && s[i + offset] != '9' && s[i + offset] != 'A' && s[i + offset] != 'B' &&
  267.                     s[i + offset] != 'C' && s[i + offset] != 'D' && s[i + offset] != 'E' && s[i + offset] != 'F' &&
  268.                     s[i + offset] != 'a' && s[i + offset] != 'b' && s[i + offset] != 'c' && s[i + offset] != 'd' &&
  269.                     s[i + offset] != 'e' && s[i + offset] != 'f') fail("error: urlDecode: expecting second byte to be [0-9A-Fa-f]");
  270.                 byte |= (s[i + offset] >= '0' && s[i + offset] <= '9') ? (s[i + offset] - '0') :
  271.                         (s[i + offset] >= 'A' && s[i + offset] <= 'F') ? (10 + s[i + offset] - 'A'):
  272.                         (s[i + offset] >= 'a' && s[i + offset] <= 'f') ? (10 + s[i + offset] - 'a') : 0;
  273.                 i -= 2;
  274.                 offset += 2;
  275.                 s[i] = byte;
  276.                 state = DURI_STATE_WAIT;
  277.                 break;
  278.             default:
  279.                 fail("error: urlDecode: invalid state");
  280.         }
  281.     }
  282.     return s;
  283. }
  284. int main(int argc, char **argv) {
  285.     parseConf();
  286.     parseQueryString();
  287.     mysql = mysql_init(NULL);
  288.     if (!mysql) myerror();
  289.     if (!mysql_real_connect(mysql, config.mysqlHostname, config.mysqlUsername, config.mysqlPassword, NULL, 0, NULL, 0)) myerror();
  290.     if (mysql_select_db(mysql, config.mysqlDatabase)) createDatabase();
  291.     char *page = g_hash_table_lookup(queryHash, "p");
  292.     if (page)
  293.         if (!strcmp(page, "sessions")) pageSessions();
  294.         else if (!strcmp(page, "session_add")) pageSessionAdd();
  295.         else pageHome();
  296.     else pageHome();
  297.     mysql_close(mysql);
  298.     return 0;
  299. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement