#include #include #include #include #include inline char *get_filename(const char *c) { char *qout = "queries/mranks.sql"; if (c != NULL) { switch(*c) { case 'm': qout = "queries/mleaderboard-ojoin.sql"; break; case 'p': qout = "queries/rplayers.sql"; break; case 't': qout = "queries/test.txt"; break; } } return qout; } inline void print_tblheader(const char *c) { char *labels; switch (*c) { default: labels = "\ \ \ \ \ \ \ "; break; case 'm': labels = "


Map List

NameRecordsBest TimeHeld By
\ \ \ \ \ \ "; break; case 'p': labels = "


Leaderboard

RankNameTime
\ \ \ \ \ \ "; break; } printf("%s", labels); } // input is an integer as a string. // the time is in centiseconds. // this means the longest XDF run this can support is // 21,474,836.47 seconds // someone would need to idle in-game for 248 days void print_time(const unsigned char *strcs) { const unsigned int num = strtoul((const char*)strcs, NULL, 10); unsigned int s = num/100; const unsigned int cs = num % 100; const unsigned int min = s/60; s = s % 60; if (min > 0) { printf("", min, s, cs); } else { printf("", s, cs); } } // display and format the results of the query. void qresult(sqlite3_stmt * const sp, const char *c) { int e; unsigned int i; unsigned int cc = sqlite3_column_count(sp); print_tblheader(c); while ((e = sqlite3_step(sp)) == SQLITE_ROW) { printf(""); for (i = 0; i < cc; i++) { if ((*c == 'm' && i == 1) || (*c == '\0' && i == 3) || (*c == 'p' && i == 0)) { printf("", sqlite3_column_text(sp, i)); } else if ((i == 0 && *c == '\0') || (i == 1 && *c == 'p') ) { printf("", sqlite3_column_text(sp, i), sqlite3_column_text(sp, i)); } else if (i == 2 && (*c == 'm' || *c == '\0')) { print_time(sqlite3_column_text(sp, i)); } else { printf("", sqlite3_column_text(sp, i)); } } printf(""); } printf("


Ranks

NameMapRank
%u:%.2u.%.2u%u.%.2u
%s%s%s
"); } // const char 'sql' is never NULL. // const char 'str' may be NULL, however it is only when // the contents of mranks.sql is in const char 'sql'. bool executequery(const char *sql, const char *str) { const char *p = (str != NULL) ? strchr(str, '=') + 1 : NULL; const char qc = (str != NULL) ? str[0] : '\0'; sqlite3 *db; int con = sqlite3_open("db/cts.db", &db); if (con != SQLITE_OK) { fprintf(stderr, "Can not open database: %s\n", sqlite3_errmsg(db)); return false; } sqlite3_stmt *s; // prepare sql to s, reading until null character. con = sqlite3_prepare_v2(db, sql, -1, &s, NULL); if (con != SQLITE_OK) { fprintf(stderr, "Could not prepare SQL statement: %s\n", sqlite3_errmsg(db)); return false; } // bind parameter with a string length that is the # of bytes to null char. con = sqlite3_bind_text(s, 1, p, -1, NULL); qresult(s, &qc); sqlite3_finalize(s); sqlite3_close(db); return true; } // both allocates and frees memory used up by the string.. // containing the data from query files. void getquery(const char *qs) { char *qf = NULL; char *fname = get_filename(qs); if (fname != NULL) { FILE *f = fopen(fname, "r"); if (f != NULL) { // change from fseek/SEEK_END when sql queries are >2 GB in size. fseek(f, 0, SEEK_END); // go to the end of file unsigned int size = ftell(f); qf = calloc(size, sizeof(char)); if (qf != NULL) { fseek(f, 0, SEEK_SET); // go to the start of file fread(qf, sizeof(char), size, f); } } fclose(f); } executequery(qf, qs); free(qf); } void html(void) { const char *html_top = "Content-Type: text/html\n\n\ \ \ /v/ - Xonotic\ "; const char *html_bot = "

Pages under construction.
\ Service may sporadically become unavailable.
\ In-game database is not directly synced with this web server.\

\ "; printf("%s", html_top); // getquery(getenv("QUERY_STRING")); // getquery("map=pornstar-kaine"); getquery(NULL); printf("%s", html_bot); } int main(void) { html(); // getquery("player=duHTyaSGpdTk7oebwPFoo899xPoTwP9bja4DUjCjTLo="); return 0; }