| rev | line source | 
| bsw/jbe@4 | 1 #include <stdlib.h> | 
| bsw/jbe@4 | 2 #include <stdio.h> | 
| bsw/jbe@4 | 3 #include <libpq-fe.h> | 
| bsw/jbe@4 | 4 #include <string.h> | 
| bsw/jbe@4 | 5 #include <regex.h> | 
| bsw/jbe@4 | 6 #include <sys/types.h> | 
| bsw/jbe@4 | 7 #include <sys/stat.h> | 
| bsw/jbe@4 | 8 #include <unistd.h> | 
| bsw/jbe@4 | 9 | 
| bsw/jbe@4 | 10 #ifndef GETPIC_CONNINFO | 
| bsw/jbe@4 | 11 #define GETPIC_CONNINFO "dbname=liquid_feedback" | 
| bsw/jbe@4 | 12 #endif | 
| bsw/jbe@4 | 13 | 
| bsw/jbe@4 | 14 #ifndef GETPIC_DEFAULT_AVATAR | 
| bsw/jbe@4 | 15 #define GETPIC_DEFAULT_AVATAR "/opt/liquid_feedback_testing/app/static/avatar.jpg" | 
| bsw/jbe@4 | 16 #endif | 
| bsw/jbe@4 | 17 | 
| bsw/jbe@4 | 18 int main(int argc, const char * const *argv) { | 
| bsw/jbe@4 | 19 | 
| bsw/jbe@4 | 20   char *args_string; | 
| bsw/jbe@4 | 21   char *member_id; | 
| bsw/jbe@4 | 22   char *image_type; | 
| bsw/jbe@52 | 23   const char *sql_member_image_params[2]; | 
| bsw/jbe@4 | 24 | 
| bsw@871 | 25 #ifndef PUBLIC_ACCESS | 
| jbe@1108 | 26 #ifdef PUBLIC_AVATAR_ACCESS | 
| jbe@1108 | 27   int authorization_required = 0; | 
| jbe@1108 | 28 #endif | 
| bsw/jbe@5 | 29   char *cookies; | 
| bsw/jbe@5 | 30   regex_t session_ident_regex; | 
| bsw/jbe@4 | 31   ssize_t start, length; | 
| bsw/jbe@5 | 32   regmatch_t session_ident_regmatch[3]; | 
| bsw/jbe@4 | 33   char *session_ident; | 
| bsw/jbe@52 | 34   const char *sql_session_params[1]; | 
| bsw@871 | 35 #endif | 
| bsw/jbe@4 | 36 | 
| bsw/jbe@5 | 37   PGconn *conn; | 
| bsw/jbe@5 | 38   PGresult *dbr; | 
| bsw/jbe@4 | 39 | 
| bsw/jbe@4 | 40   args_string = getenv("QUERY_STRING"); | 
| bsw@873 | 41   if (!args_string) { | 
| bsw@873 | 42     fputs("Status: 403 Access Denied\n\n", stdout); | 
| bsw@873 | 43     return 0; | 
| bsw@873 | 44   } | 
| jbe@1108 | 45 | 
| jbe@1108 | 46   member_id   = strtok(args_string, "+"); | 
| jbe@1108 | 47   image_type  = strtok(NULL, "+"); | 
| jbe@1108 | 48   if (!member_id || !image_type) { | 
| bsw/jbe@4 | 49     fputs("Status: 403 Access Denied\n\n", stdout); | 
| bsw/jbe@4 | 50     return 0; | 
| bsw/jbe@4 | 51   } | 
| bsw/jbe@4 | 52   sql_member_image_params[0] = member_id; | 
| bsw/jbe@4 | 53   sql_member_image_params[1] = image_type; | 
| bsw/jbe@4 | 54 | 
| bsw@871 | 55 #ifndef PUBLIC_ACCESS | 
| jbe@1108 | 56 #ifdef PUBLIC_AVATAR_ACCESS | 
| jbe@1108 | 57   if (strcmp(image_type, "avatar")) { | 
| jbe@1108 | 58     authorization_required = 1; | 
| jbe@1108 | 59 #endif | 
| jbe@1108 | 60     cookies = getenv("HTTP_COOKIE"); | 
| jbe@1108 | 61     if (!args_string || !cookies) { | 
| jbe@1108 | 62       fputs("Status: 403 Access Denied\n\n", stdout); | 
| jbe@1108 | 63       return 0; | 
| jbe@1108 | 64     } | 
| jbe@1108 | 65     if (regcomp(&session_ident_regex, "(^|[; \t])liquid_feedback_session=([0-9A-Za-z]+)", REG_EXTENDED) != 0) { | 
| jbe@1108 | 66       // shouldn't happen | 
| jbe@1108 | 67       abort(); | 
| jbe@1108 | 68     } | 
| jbe@1108 | 69     if (regexec(&session_ident_regex, cookies, 3, session_ident_regmatch, 0) != 0) { | 
| jbe@1108 | 70       fputs("Status: 403 Access Denied\n\n", stdout); | 
| jbe@1108 | 71       return 0; | 
| jbe@1108 | 72     } | 
| jbe@1108 | 73     start = session_ident_regmatch[2].rm_so; | 
| jbe@1108 | 74     length = session_ident_regmatch[2].rm_eo - session_ident_regmatch[2].rm_so; | 
| jbe@1108 | 75     session_ident = malloc(length + 1); | 
| jbe@1108 | 76     if (!session_ident) abort();  // shouldn't happen | 
| jbe@1108 | 77     strncpy(session_ident, cookies + start, length); | 
| jbe@1108 | 78     session_ident[length] = 0; | 
| jbe@1108 | 79     sql_session_params[0] = session_ident; | 
| jbe@1108 | 80 #ifdef PUBLIC_AVATAR_ACCESS | 
| bsw/jbe@4 | 81   } | 
| jbe@1108 | 82 #endif | 
| bsw@874 | 83 #endif | 
| bsw/jbe@4 | 84 | 
| bsw/jbe@4 | 85   conn = PQconnectdb(GETPIC_CONNINFO); | 
| bsw/jbe@4 | 86   if (!conn) { | 
| bsw/jbe@4 | 87     fputs("Could not create PGconn structure.\n", stderr); | 
| bsw/jbe@4 | 88     return 1; | 
| bsw/jbe@4 | 89   } | 
| bsw/jbe@4 | 90   if (PQstatus(conn) != CONNECTION_OK) { | 
| bsw/jbe@4 | 91     fputs(PQerrorMessage(conn), stderr); | 
| bsw/jbe@5 | 92     PQfinish(conn); | 
| bsw/jbe@4 | 93     return 1; | 
| bsw/jbe@4 | 94   } | 
| bsw/jbe@4 | 95 | 
| bsw@874 | 96 #ifndef PUBLIC_ACCESS | 
| jbe@1108 | 97 #ifdef PUBLIC_AVATAR_ACCESS | 
| jbe@1108 | 98   if (authorization_required) { | 
| jbe@1108 | 99 #endif | 
| jbe@1108 | 100     dbr = PQexecParams(conn, | 
| jbe@1108 | 101       "SELECT NULL FROM session JOIN member ON member.id = session.member_id WHERE session.ident = $1 AND member.active", | 
| jbe@1108 | 102       1, NULL, sql_session_params, NULL, NULL, 0 | 
| jbe@1108 | 103     ); | 
| jbe@1108 | 104     if (PQresultStatus(dbr) != PGRES_TUPLES_OK) { | 
| jbe@1108 | 105       fputs(PQresultErrorMessage(dbr), stderr); | 
| jbe@1108 | 106       PQfinish(conn); | 
| jbe@1108 | 107       return 1; | 
| jbe@1108 | 108     } | 
| jbe@1108 | 109     if (PQntuples(dbr) != 1) { | 
| jbe@1108 | 110       fputs("Status: 403 Access Denied\n\n", stdout); | 
| jbe@1108 | 111       PQfinish(conn); | 
| jbe@1108 | 112       return 0; | 
| jbe@1108 | 113     } | 
| jbe@1108 | 114 #ifdef PUBLIC_AVATAR_ACCESS | 
| bsw/jbe@4 | 115   } | 
| jbe@1108 | 116 #endif | 
| bsw@871 | 117 #endif | 
| bsw/jbe@4 | 118 | 
| bsw/jbe@4 | 119   dbr = PQexecParams(conn, | 
| bsw/jbe@4 | 120     "SELECT content_type, data " | 
| bsw/jbe@4 | 121     "FROM member_image " | 
| bsw/jbe@4 | 122     "WHERE member_id = $1 " | 
| bsw/jbe@4 | 123     "AND image_type = $2 " | 
| bsw/jbe@4 | 124     "AND scaled " | 
| bsw/jbe@4 | 125     "LIMIT 1;", | 
| bsw/jbe@4 | 126     2, NULL, sql_member_image_params, NULL, NULL, 1 | 
| bsw/jbe@4 | 127   ); | 
| bsw/jbe@4 | 128   if (PQresultStatus(dbr) != PGRES_TUPLES_OK) { | 
| bsw/jbe@4 | 129     fputs(PQresultErrorMessage(dbr), stderr); | 
| bsw/jbe@5 | 130     PQfinish(conn); | 
| bsw/jbe@4 | 131     return 1; | 
| bsw/jbe@4 | 132   } | 
| bsw/jbe@4 | 133   if (PQntuples(dbr) == 0) { | 
| bsw/jbe@4 | 134     struct stat sb; | 
| bsw/jbe@4 | 135     PQclear(dbr); | 
| bsw/jbe@4 | 136     PQfinish(conn); | 
| bsw/jbe@4 | 137     fputs("Content-Type: image/jpeg\n\n", stdout); | 
| bsw/jbe@4 | 138     if (stat(GETPIC_DEFAULT_AVATAR, &sb)) return 1; | 
| bsw/jbe@5 | 139     fprintf(stdout, "Content-Length: %i\n", (int)sb.st_size); | 
| bsw/jbe@4 | 140     execl("/bin/cat", "cat", GETPIC_DEFAULT_AVATAR, NULL); | 
| bsw/jbe@4 | 141     return 1; | 
| bsw/jbe@4 | 142   } else { | 
| bsw/jbe@4 | 143     if (PQnfields(dbr) < 0) { | 
| bsw/jbe@4 | 144       fputs("Too few columns returned by database.\n", stderr); | 
| bsw/jbe@5 | 145       PQfinish(conn); | 
| bsw/jbe@4 | 146       return 1; | 
| bsw/jbe@4 | 147     } | 
| bsw/jbe@4 | 148     if (PQfformat(dbr, 0) != 1 || PQfformat(dbr, 1) != 1) { | 
| bsw/jbe@4 | 149       fputs("Database did not return data in binary format.\n", stderr); | 
| bsw/jbe@5 | 150       PQfinish(conn); | 
| bsw/jbe@4 | 151       return 1; | 
| bsw/jbe@4 | 152     } | 
| bsw/jbe@4 | 153     if (PQgetisnull(dbr, 0, 0) || PQgetisnull(dbr, 0, 1)) { | 
| bsw/jbe@4 | 154       fputs("Unexpected NULL in database result.\n", stderr); | 
| bsw/jbe@5 | 155       PQfinish(conn); | 
| bsw/jbe@4 | 156       return 1; | 
| bsw/jbe@4 | 157     } | 
| bsw/jbe@52 | 158     fprintf(stdout, "Content-Type: %s\n\n", PQgetvalue(dbr, 0, 0)); | 
| bsw/jbe@4 | 159     fwrite(PQgetvalue(dbr, 0, 1), PQgetlength(dbr, 0, 1), 1, stdout); | 
| bsw/jbe@4 | 160   } | 
| bsw/jbe@4 | 161   PQfinish(conn); | 
| bsw/jbe@4 | 162   return 0; | 
| bsw/jbe@5 | 163 | 
| bsw/jbe@4 | 164 } |