Website CGI to display Race CTS leaderboards of a Xonotic server.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

111 lines
3.2 KiB

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <sqlite3.h>
typedef enum {
MAP,
PLAYER,
OVERVIEW,
NONE
} Querytype;
inline char *get_filename(const char c, Querytype *q) {
char *qout;
switch(c) {
default:
qout = "queries/mranks.sql";
*q = OVERVIEW;
break;
case 'm':
qout = "queries/mleaderboard-ojoin.sql";
*q = MAP;
break;
case 'p':
qout = "queries/rplayers.sql";
*q = PLAYER;
break;
case 't':
qout = "queries/test.txt";
*q = NONE;
break;
}
return qout;
}
bool executequery(const char *sql, const char *p, int tbl) {
sqlite3 *db;
char *error;
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);
int e;
unsigned int cc, i;
while ((e = sqlite3_step(s)) == SQLITE_ROW) {
cc = sqlite3_column_count(s);
for (i = 0; i < cc; i++) {
printf("%s, ", sqlite3_column_text(s, i));
}
printf("\n");
}
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, *qp;
Querytype qt;
char *fname = get_filename(qs[0], &qt);
if (fname != NULL) {
FILE *f = fopen(fname, "r");
if (f != NULL && qf != 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 = malloc(size);
if (qf != NULL) {
fseek(f, 0, SEEK_SET); // go to the start of file
fread(qf, sizeof(char), size, f);
}
}
}
qp = strchr(qs, '=') + 1; // increment to exclude '='
printf("%s\n", qf);
executequery(qf, qp, qt);
free(qf);
}
void html(void) {
const char *html_top = "Content-Type: text/html\n\n\
<html><head><meta content=\"text/html; charset=UTF-8\" />\
<link rel=\"stylesheet\" type=\"text/css\" href=\"page.css\">\
<title>/v/ - Xonotic</title>\
<p class='hidden'>:-) / nice one<br></p>";
const char *html_bot = "<br><br><p classname='footer'>Pages under construction.<br>\
Service may sporadically become unavailable.<br>\
In-game database is not directly synced with this web server.\
</p>\
</body></html>";
getquery(getenv("QUERY_STRING"));
printf("%s %s", html_top, html_bot);
return;
}
int main(void) {
getquery("map=pornstar-kaine");
}