int main(int argc, char *argv[]) { char header[] = "Powered-by: ANSI C scripts\r\n"; http_header(HEAD_ADD, header, sizeof(header) - 1, argv); xbuf_cat(get_reply(argv), "Look at the HTTP headers"); return 200; // return an HTTP code (200:'OK') }
void flush(void) { // TODO: flush() can later return some info about the flushed data, e.g. size if (!this->headersSet) { this->flushHeaders(); } xbuf_cat(this->httpOut, (char *) this->payload.c_str()); u32toa(this->httpOut->ptr + this->ptrHeaderSize, this->httpOut->len - this->headersSize); }
int main(int argc, char *argv[]) { xbuf_t data; xbuf_init(&data); xbuf_cat(&data, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sit amet " "quam purus, vitae fermentum turpis. Nam in augue mi. Donec suscipit moles" "tie felis, eget rhoncus risus pharetra in. Sed id diam id felis fringilla" " adipiscing non vitae odio. Etiam vulputate tristique elit, nec eleifend" " mauris scelerisque eu. Vestibulum luctus, enim a luctus posuere, mauris" " mauris rutrum mi, eget fermentum massa tortor id enim. Nulla feugiat " "porta urna quis laoreet. Morbi metus ante, commodo quis dictum vitae, " "rhoncus a libero. Cras viverra feugiat orci id interdum. Duis pulvinar " "neque id erat adipiscing facilisis. Maecenas vitae urna risus, euismod" " sollicitudin risus." ); char gzipped[4096]; u32 len = zlib_cmp(data.ptr, 0, data.len, gzipped, sizeof(gzipped), 1); printf("Original length: %i\n", data.len); printf("Gzipped length: %i\n\n", len); xbuf_t *reply = get_reply(argv); xbuf_xcat(reply, "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "Content-Length: %i\r\n" "Content-Encoding: gzip\r\n\r\n", len ); xbuf_ncat(reply, gzipped, len); xbuf_free(&data); return -1; //custom headers }
int main(int argc, char *argv[]) { //initialize Key-Value store-------------------------------------------------- kv_t **vhost_ptr = (kv_t**)get_env(argv, US_VHOST_DATA), //persistent ptr *forum_store = 0; //convenience pointer (var->m instead of (*var)->m) if (vhost_ptr && !*vhost_ptr) { *vhost_ptr = (kv_t*)malloc(sizeof(kv_t)); //threads and posts stored here kv_init(*vhost_ptr, "forum_store", 1024, 0, 0, 0); } forum_store = *vhost_ptr; //---------------------------------------------------------------------------- //setup GET and POST variables------------------------------------------------ char *act = "", *id = "", *title = "", *body = ""; get_arg("act=", &act, argc, argv); //action ('t' or 'p') get_arg("id=", &id, argc, argv); //id of thread get_arg("title=", &title, argc, argv); //title of thread get_arg("body=", &body, argc, argv); //body of post char *end = 0; u64 int_id = strtoll(id, &end, 10); //string to integer if (*end) int_id = 0; //require a numeric ID //---------------------------------------------------------------------------- //response sent to browser is stored here------------------------------------- //templates are rendered into this buffer xbuf_t *reply = get_reply(argv); xbuf_cat(reply, base_tpl); //set base template //---------------------------------------------------------------------------- //HTTP state of a connection http_t *http = (http_t*)get_env(argv, HTTP_HEADERS); redirect: //simulate HTTP, <meta>, or JavaScript redirect without page reload //choose what to do based on the value of 'act'------------------------------- switch (*act) { //regarding a post case 'p': { switch (http->h_method) //GET or POST { //new post-------------------------------------------------------------- case HTTP_POST: { //get the thread to which this post belongs Thread *thread = (Thread*)kv_get(forum_store, (char*)&int_id, sizeof(int_id)); if (!thread) //thread not found { xbuf_repl(reply, "<!--tpl-->", http_error(404)); return 404; } //allocate memory Post *post = calloc(1, sizeof(*post)); //initialize members xbuf_init(&post->body); //define members post->id = thread->posts.nbr_items + 1; xbuf_cat(&post->body, *body ? body : " "); //add post to thread kv_add(&thread->posts, &(kv_item) { .key = (char*)&post->id, .klen = sizeof(post->id), .val = (char*)post, .flags = 0, }); //setup redirect http->h_method = HTTP_GET; *act = 't'; goto redirect; } break; //---------------------------------------------------------------------- } } break; //regarding a thread case 't': { switch (http->h_method) { //view a thread--------------------------------------------------------- case HTTP_GET: { Thread *thread = (Thread*)kv_get(forum_store, (char*)&int_id, sizeof(int_id)); if (!thread) { xbuf_repl(reply, "<!--tpl-->", http_error(404)); return 404; } //replace template variables with dynamic values xbuf_repl(reply, "<!--form-->", post_form); xbuf_repl(reply, "<!--title-->", thread->title.ptr); xbuf_repl(reply, "<!--id-->", id); //for each post, render its template and insert it into reply kv_do(&thread->posts, 0, 0, (kv_proc_t)&list_posts, (void*)reply); } break; //---------------------------------------------------------------------- //create a thread------------------------------------------------------- case HTTP_POST: { Thread *thread = calloc(1, sizeof(*thread)); xbuf_init(&thread->title); kv_init(&thread->posts, "posts", 1024, 0, 0, 0); thread->id = forum_store->nbr_items + 1; xbuf_cat(&thread->title, *title ? title : " "); //add thread to KV store kv_add(forum_store, &(kv_item) { .key = (char*)&thread->id, .klen = sizeof(thread->id), .val = (char*)thread, .flags = 0, }); http->h_method = HTTP_GET; *act = 0; goto redirect; } break; //---------------------------------------------------------------------- } } break;
// ---------------------------------------------------------------------------- // imported functions: // get_reply(): get a pointer on the 'reply' dynamic buffer from the server // get_env(): get connection's 'environment' variables from the server // xbuf_cat(): like strcat(), but it works in the specified dynamic buffer // gif_build(): build an in-memory GIF image from a bitmap and palette // ---------------------------------------------------------------------------- int main(int argc, char *argv[]) { // ------------------------------------------------------------------------- // build the top of our HTML page // ------------------------------------------------------------------------- static char top[]= "<!DOCTYPE HTML>" "<html lang=\"en\"><head><title>Captcha</title><meta http-equiv" "=\"Content-Type\" content=\"text/html; charset=utf-8\">" "<link href=\"/imgs/style.css\" rel=\"stylesheet\" type=\"text/css\">" "</head><body style=\"margin:0 16px;\"><br><h2>Captcha for Humans</h2>" "<p>Please enter the SUM of all the GREEN FIGURES (not letters) below " "(that's twice the same image, just with a different HTML background " "- the Data-URI-inlined GIF background is transparent):</p><br>\r\n"; xbuf_t *reply = get_reply(argv); xbuf_ncat(reply, top, sizeof(top) - 1); // ------------------------------------------------------------------------- // allocate memory for a raw bitmap // ------------------------------------------------------------------------- const int w = BMP_WIDTH, h = BMP_HEIGHT, wXh = w * h; u8 *bmp = (u8*)calloc(CHAR_WIDTH * w, h); if(!bmp) return 503; // service unavailable // ------------------------------------------------------------------------- // render the captcha in our bitmap // ------------------------------------------------------------------------- u32 seed = (u32)getns(); prnd_t rnd; // pseudo-random generator (period: 1 << 158) sw_init(&rnd, seed); // EPOCH time in nano-seconds // structure needed by G-WAN's frame buffer routines like dr_text() bmp_t img ={ .bmp = bmp, .p = bmp, .bbp = 8, .pen = 1, .bgd = 0, .rect = {0,0, w,h}, .flags = 0, .w = w, .h = h, .x = 0, .y = 0 }; u32 sum = captcha(&img, &rnd); // ------------------------------------------------------------------------- // build the GIF image, gif_build(0:transparent color index, 0: no comment) // ------------------------------------------------------------------------- u8 pal[] = { 255, 255, 255, 223, 255, 191, 132, 164, 100, 0, 0, 0 }; const int nbcolors = (sizeof(pal) / sizeof(u8)) / 3; // RGB values u8 *gif = (u8*)malloc(CHAR_WIDTH * wXh); if(!gif) { free(bmp); return 503; } // service unavailable int gln = gif_build(gif, bmp, w, h, pal, nbcolors, 0, 0); // ------------------------------------------------------------------------- // store the base64 encoded GIF in the 'reply' buffer // ------------------------------------------------------------------------- if(gln > 0) // (gln == -1) if gif_build() failed { // a real captcha test would only display the first of those two views: // (they are shown side-by-side to visualize the background trick) xbuf_cat(reply, "<table><tr>\r\n" "<td style=\"background:#dfffbf;\">\r\n"); u32 img_pos = reply->len; xbuf_xcat(reply, "<img src=\"data:image/gif;base64,%*B\" alt=\"A tree\" " "width=\"%d\" height=\"%d\" /></td>\r\n", gln, gif, w + w, h + h); // scale picture xbuf_xcat(reply, "<td style=\"background:#84a464;\">%.*s</tr>\r\n</table>\n\r", reply->len - img_pos, reply->ptr + img_pos); } free(gif); free(bmp); // ------------------------------------------------------------------------- // close our HTML page // ------------------------------------------------------------------------- xbuf_xcat(reply, "<br>The two sums are: <b>%u</b> and <b>%u</b>... " "for the same Captcha image!<br><br>" "By just changing the <b>HTML background color</b> (mouse cursor " "hovering, previous state or input or shared secret) used for " "the transparent GIF Captcha image we can make something simple " "for humans become difficult or even completely impossible " "for robots.<br><br>" "HTML and GIF are served with one single request: the picture" " is generated on-the-fly and embedded into the HTML code by " " using the base64 encoding (look at the HTML source code)." "<br></body></html>", (sum & 0xffff0000) >> 16, sum & 0x0000ffff); return 200; // return an HTTP code (200:'OK') }