Want more features on Pastebin? Sign Up, it's FREE!
Guest

Untitled

By: a guest on Jan 7th, 2011  |  syntax: C  |  size: 9.35 KB  |  views: 52  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  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. }
clone this paste RAW Paste Data