--------------------------------------------------- | Date: 2004-07-27 02:54:00 | | Filename: webinc.c | | Author: mind@metalshell.com | | | | http://www.metalshell.com/ | --------------------------------------------------- /* Website in C - mind@metalshell.com * * This code was meant to show the flexibility * and speed of coding a site in C. [ Nobody Likes PHP! =) ] * * This example will show how to create a fully developed * website in C, using mysql (optional). * * I did a speed test; Printing 2,000 lines containing 100 'A's * per line using php and C; the results were: C (0.120s) PHP (0.605s) * * Note: I used a version of my own printing example to make * the HTML output look alot nicer.. eprint() is optional. * * libmysqlclient.a: path may be different. * To compile: gcc example.c -o example.cgi -lz /usr/lib/mysql/libmysqlclient.a * * to view VIA web browser: turn ExecCGI on in httpd.conf * and move example.cgi to your html folder. */ #include <stdio.h> #include <string.h> #include <stdarg.h> #include <stdlib.h> /* header path may be different */ #include "/usr/include/mysql/mysql.h" /* To setup your mysql db so the example will work please * open mysql; and paste the following: * * create database Cexample; * * use Cexample; * create TABLE person ( * id mediumint(9) NOT NULL auto_increment, * name char(40) NOT NULL, * birth char(40) NOT NULL, * addy char(40) NOT NULL, * phone char(40) NOT NULL, * PRIMARY KEY (id) * ); * * insert into person VALUES( NULL, 'John Doe', '01-20-66', * 'N. Burboun ST.', '800-123-4567' ); * * insert into person VALUES( NULL, 'Jane Doe', '12-09-72', * 'S. Burboun ST.', '800-987-6543'); * */ /* edit USER, and PASS */ #define MySQL_HOST "localhost" #define MySQL_USER "ChangeME" #define MySQL_PASS "ChangeME" #define MySQL_DATA "Cexample" MYSQL_RES *res; MYSQL_ROW row; int TabMe = 0; void eprint(int b, char *fmt, ...); void ShowError(char *x, char *e); void StartHtml(); void GetBirth(int x); void GetAddress(int x); void GetPhone(int x); void GetShowAll(int x); int StartQuery(); /* This structure is for our apache string parser * when it parses for example id=1&0 our parser will * execute GetBirth(0); */ struct { int id; void (*func)(int); } DefExt[]= { { 1, GetBirth }, { 2, GetAddress }, { 3, GetPhone }, { 4, GetShowAll }, { 0, NULL }, }; int main() { MYSQL mysql; char query[100]; /* Initial start of our site's source */ printf("Content-Type: text/html\n\n"); /* Check to see if any arguments were passed through * our program. If not show front page. */ if ((StartQuery()) == -1) { StartHtml(); if (!(mysql_connect(&mysql, MySQL_HOST, MySQL_USER, MySQL_PASS))) ShowError(NULL, "MySQL SERVER down"); if (mysql_select_db(&mysql, MySQL_DATA)) ShowError(NULL, "MySQL database error"); snprintf(query, sizeof(query), "select * from person order by name"); if (mysql_query(&mysql,query)) ShowError(NULL, "MySQL server error"); res = mysql_store_result(&mysql); while ((row = mysql_fetch_row(res))) { eprint( 0, "<font>%s - </font>\n", row[1]); eprint( 0, "<a href=\"?id=1&%s\">Birth Day</a>\n", row[0]); eprint( 0, "<font> - </font>\n"); eprint( 0, "<a href=\"?id=2&%s\">Address</a>\n", row[0]); eprint( 0, "<font> - </font>\n"); eprint( 0, "<a href=\"?id=3&%s\">Phone</a>\n", row[0]); eprint( 0, "<font> - </font>\n"); eprint( 0, "<a href=\"?id=4&%s\">Show All</a><br>\n", row[0]); } mysql_close(&mysql); mysql_free_result(res); eprint(-1, "</html>\n"); return 1; } eprint(-1, "</html>\n"); return 1; } int StartQuery() { int i, g, b; char *x, *y, *z, *e; (char *)y = malloc(100); (char *)z = malloc(100); (char *)e = malloc(100); /* Apache will set QUERY_STRING=id=x&x */ x = getenv("QUERY_STRING"); /* If it doesn't exsist return a negative value * to initialize our front page */ if (x == NULL || x[0] == 0) { return -1; } /* Always perform checks on everything you write * to prevent program flaws and or overflows */ if (strlen(x) >= 100) { ShowError(x, "Your request was too big"); return 0; } for (i = 0, b = 0, g = 0; i < strlen(x); i++) { if (g == 1) { if (i > 8) { ShowError(x, "Id too long"); return 0; } if (x[i] == '&') { if (x[i+1] == 0) { ShowError(x, "Missing field"); return 0; } g++; b = 0; continue; } else { z[b] = x[i]; b++; continue; } } if (g == 2) { e[b] = x[i]; b++; continue; } if (x[i] == '=') { g++; b = 0; if (!(strncmp(y, "id", 2))) { continue; } else { ShowError(x, "Invalid extention"); return 0; } } y[b] = x[i]; b++; } if (strncmp(y, "id", 2) || z[0] == 0 || e[0] == 0) { ShowError(x, "Invalid extention"); return 0; } b = atoi(z); g = atoi(e); for (i = 0; DefExt[i].id; i++) { if (DefExt[i].id == b) { StartHtml(); DefExt[i].func(g); return 1; } } ShowError(x, "Invalid ID"); return 1; } /* The mysql concept was derived from detour's mysql select * example found at: http://www.metalshell.com/view/source/18/ */ void GetMysql(char *query) { MYSQL mysql; if (strlen(query) < 10) ShowError(NULL, "MySQL query string too low"); if (!(mysql_connect(&mysql, MySQL_HOST, MySQL_USER, MySQL_PASS))) { fprintf(stderr,"mysql_connect() Failed: %s\n",mysql_error(&mysql)); ShowError(NULL, "MySQL SERVER down"); } if (mysql_select_db(&mysql, MySQL_DATA)) ShowError(NULL, "MySQL database error"); if (mysql_query(&mysql,query)) ShowError(NULL, "MySQL server error"); res = mysql_store_result(&mysql); row = mysql_fetch_row(res); mysql_close(&mysql); mysql_free_result(res); } void GetBirth(int x) { char query[100]; snprintf(query, sizeof(query), "select * from person where id = %i", x); GetMysql(query); eprint( 0, "<font> %s's Birth date is: %s</font>\n", row[1], row[2]); } void GetAddress(int x) { char query[100]; snprintf(query, sizeof(query), "select * from person where id = %i", x); GetMysql(query); eprint( 0, "<font> %s's Address is: %s</font>\n", row[1], row[3]); } void GetPhone(int x) { char query[100]; snprintf(query, sizeof(query), "select * from person where id = %i", x); GetMysql(query); eprint( 0, "<font> %s's Phone Number is: %s</font>\n", row[1], row[4]); } void GetShowAll(int x) { char query[100]; snprintf(query, sizeof(query), "select * from person where id = %i", x); GetMysql(query); eprint( 0, "<font> <b><u>%s</b></u> </font><br>\n", row[1]); eprint( 0, "<font> Birth day: %s</font><br>\n", row[2]); eprint( 0, "<font> Address : %s</font><br>\n", row[3]); eprint( 0, "<font> Phone Num: %s</font><br>\n", row[4]); } void StartHtml() { eprint( 0, "<html>\n"); eprint( 1, "<head>\n"); eprint( 1, "<title> Website in C - Example </title>\n"); eprint(-1, "</head>\n\n"); } /* Error printing */ void ShowError(char *x, char *e) { if (e == NULL) strcpy(e, "Unknown Error!"); /* Some prints resized to fit MS source code area */ eprint( 0, "<html>\n"); eprint( 1, "<head>\n"); eprint( 1, "<title>An Error Occured!</title>\n"); eprint(-1, "</head>\n\n"); eprint( 0, "<br><br><br><br><br><br><br>\n"); if (x != NULL) { eprint( 0, "<div align=center><font size=4>An error occured: \"%s\" ", e); printf("While trying to process your request of \"%s\"</font></div>\n", x); }else { eprint( 0, "<div align=center><font size=4>An error occured: \"%s\" ", e); printf("While trying to process your request.</font></div>\n"); } eprint( 0, "<div align=center><font size=4>If this error keeps occuring please "); printf("email the site admin</font></div>\n"); eprint(-1, "</html>\n"); exit(-1); } /* eprint - mind@metalshell.com [http://www.metalshell.com] * * Example: * eprint( 0, "test1\n"); No Change (just print) * eprint( 1, "test2\n"); Add a tab * eprint( 1, "test3\n"); Add a tab * eprint(-1, "test4\n"); Remove a tab * eprint(-1, "test5\n"); Remove a tab * eprint( 0, "test6\n"); No Change (just print) * * ;test1 * ;<tab>test2 * ;<tab><tab>test3 * ;<tab>test4 * ;test5 * ;test6 */ void eprint(int b, char *fmt, ...) { va_list list; char *p, *r; int e, x; if (b == -1) TabMe--; if (b == 1) TabMe++; for (x = 0; x < TabMe; x++) putc('\t', stdout); va_start( list, fmt ); for ( p = fmt ; *p ; ++p ) { if ( *p != '%' ) { putc( *p, stdout ); } else { switch ( *++p ) { case 's': { r = va_arg( list, char * ); printf("%s", r); continue; } case 'i': { e = va_arg( list, int ); printf("%i", e); continue; } default: { if (!x) putc( *p, stdout ); else x = 0; } } } } va_end(list); fflush(stdout); }