00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef mycgisession_c
00023 #define mycgisession_c
00024
00025 #include "mycgisession.h"
00026
00027 #include <stdio.h>
00028 #include <string.h>
00029 #include <stdlib.h>
00030
00031 #define SESSION_TIMEOUT 600
00032 #define SESSION_TABLE "cgi_session"
00033
00034 #define ERROR 1;
00035
00036 #define ENC_TYPE_NONE 0
00037 #define ENC_TYPE_BASE64 1
00038
00039 #define MAX_TABLE_NAME 64
00040
00041 static MYSQL *cgisession_mysql_conn = NULL;
00042 static char cgisession_table_name[MAX_TABLE_NAME];
00043 static int have_connection = 0;
00044
00045 struct CGISESSION_struct {
00046 char *key;
00047 char *data;
00048 unsigned int size;
00049 unsigned int timeout;
00050 unsigned int timestamp;
00051 int encoding;
00052 int stored;
00053 };
00054
00055 static struct CGISESSION_struct cs;
00056
00057
00058 static void cgisession_init();
00059 static int cgisession_database_init();
00060 static int cgisession_delete_expired();
00061 static int cgisession_update();
00062 static int cgisession_load_all();
00063 static char *cgisession_genkey();
00064 static char *cgisession_encode_data();
00065 static int cgisession_decode_data(char *encoded, long enc_size);
00066
00067
00068
00069
00070
00076 int
00077 cgisession_init_mysql_connection(char *host, char *username,
00078 char *password, char *database,
00079 unsigned int port)
00080 {
00081 cgisession_mysql_conn = mysql_init(NULL);
00082
00083 if (NULL == mysql_real_connect(cgisession_mysql_conn,
00084 host, username, password, database,
00085 port, NULL, 0)) {
00086 #ifdef DEBUG1
00087 printf("mysql_real_connect failed: "
00088 "host: %s, user: %s, database: %s, password: %s\n",
00089 host, username, database, password);
00090 #endif
00091 return -ERROR;
00092 }
00093
00094 cgisession_init();
00095
00096 return cgisession_database_init();
00097 }
00098
00103 int cgisession_have_mysql_connection(MYSQL * m)
00104 {
00105 if (!m)
00106 return -ERROR;
00107
00108 cgisession_mysql_conn = m;
00109
00110 have_connection = 1;
00111
00112 cgisession_init();
00113
00114 return cgisession_database_init();
00115 }
00116
00127 int cgisession_load(char *key)
00128 {
00129 if (key) {
00130 if (0 != cgisession_update(key))
00131 return -ERROR;
00132 if (0 != cgisession_load_all())
00133 return -ERROR;
00134 } else {
00135 return -ERROR;
00136 }
00137
00138 cs.stored = 1;
00139 return 0;
00140 }
00141
00145 int cgisession_save()
00146 {
00147 char *query;
00148 char *encoded_data;
00149 int ret = 0;
00150
00151 encoded_data = cgisession_encode_data();
00152
00153 query = (char *) malloc(sizeof(encoded_data) + 1024);
00154
00155 if (cs.stored) {
00156 if (encoded_data) {
00157 sprintf(query, "update %s set mtime=now(), "
00158 "timeout='%d', data='%s', datasize='%d' where session_key='%s'",
00159 cgisession_table_name, cs.timeout, encoded_data, cs.size, cs.key);
00160 } else {
00161 sprintf(query, "update %s set mtime=now(), "
00162 "timeout='%d' where session_key='%s'",
00163 cgisession_table_name, cs.timeout, cs.key);
00164 }
00165 } else {
00166
00167 if (encoded_data) {
00168 sprintf(query,
00169 "insert into %s (session_key, mtime, timeout, data, datasize) "
00170 "values ('%s', now(), %d, '%s', '%d')", cgisession_table_name,
00171 cs.key, cs.timeout, encoded_data, cs.size);
00172 } else {
00173 sprintf(query,
00174 "insert into %s (session_key, mtime, timeout, data, datasize) "
00175 "values ('%s', now(), %d, null, 0)", cgisession_table_name,
00176 cs.key, cs.timeout);
00177 }
00178 }
00179
00180 if ((ret = mysql_query(cgisession_mysql_conn, query))) {
00181 #ifdef DEBUG1
00182 printf("\nquery %s failed with return code %d\n", query, ret);
00183 return -ERROR;
00184 #endif
00185 }
00186
00187 free(query);
00188 if (NULL!=encoded_data)
00189 free(encoded_data);
00190 return ret;
00191 }
00192
00198 int cgisession_new()
00199 {
00200 cs.key = cgisession_genkey();
00201 if (!cs.key)
00202 return -ERROR;
00203 return 0;
00204 }
00205
00206 void cgisession_free()
00207 {
00208 if (!have_connection)
00209 mysql_close(cgisession_mysql_conn);
00210 }
00211
00212
00216 int cgisession_set_data(void *data, unsigned int size)
00217 {
00218 if (cs.data)
00219 free(cs.data);
00220
00221 cs.data = malloc(size);
00222 memcpy(cs.data, data, size);
00223 cs.size = size;
00224 return 0;
00225 }
00226
00230 void *cgisession_get_data()
00231 {
00232 return cs.data;
00233 }
00234
00238 char *cgisession_get_key()
00239 {
00240 return cs.key;
00241 }
00242
00246 void cgisession_dump() {
00247 printf("\n**** cgisession dump ****\n");
00248 printf("key: %s\n", cs.key?cs.key:"null");
00249 printf("data: %s\n", cs.data?cs.data:"null");
00250 printf("size: %d\n", cs.size);
00251 printf("timeout: %d\n", cs.timeout);
00252 printf("encoding: %d\n", cs.encoding);
00253 printf("stored: %d\n", cs.stored);
00254 printf("**** dump ends ****\n");
00255 }
00256
00257
00259
00260
00264 int cgisession_option_encoding(int enc)
00265 {
00266 switch (enc) {
00267 case ENC_TYPE_NONE:
00268 case ENC_TYPE_BASE64:
00269 cs.encoding = enc;
00270 return 0;
00271 default:
00272 return -ERROR;
00273 }
00274 }
00275
00279 int cgisession_option_timeout(unsigned int secs)
00280 {
00281 cs.encoding = secs;
00282 return 0;
00283 }
00284
00288 int cgisession_option_table(char *table_name)
00289 {
00290 if (strlen(table_name) > MAX_TABLE_NAME)
00291 return -ERROR;
00292 strcpy(cgisession_table_name, table_name);
00293 return 0;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303 static void cgisession_init()
00304 {
00305 cs.key = NULL;
00306 cs.data = NULL;
00307 cs.size = 0;
00308 cs.timeout = 0;
00309 cs.timestamp = 0;
00310 cs.encoding = ENC_TYPE_NONE;
00311 cs.stored = 0;
00312 strcpy(cgisession_table_name, "cgi_sessions");
00313 }
00314
00318 static int cgisession_database_init()
00319 {
00320 char query[1024];
00321 int ret = 0;
00322
00323 sprintf(query, "create table if not exists %s "
00324 "(session_key varchar(20) primary key, "
00325 "mtime timestamp, timeout int, data blob, datasize int)",
00326 cgisession_table_name);
00327 if ((ret = mysql_query(cgisession_mysql_conn, query))) {
00328 #ifdef DEBUG1
00329 printf("query: %s failed with error code %d", query, ret);
00330 #endif
00331 return ret;
00332 }
00333
00334 if ((ret = cgisession_delete_expired()))
00335 return ret;
00336
00337 return ret;
00338 }
00339
00343 static int cgisession_delete_expired()
00344 {
00345 char query[1024];
00346 int ret;
00347
00348 sprintf(query, "delete from %s where mtime<'now()-%d'",
00349 cgisession_table_name, cs.timeout);
00350
00351 ret = mysql_query(cgisession_mysql_conn, query);
00352 #ifdef DEBUG1
00353 if (ret)
00354 printf("query: %s failed with error code %d", query, ret);
00355 #endif
00356 return ret;
00357 }
00358
00362 int cgisession_update(char *key)
00363 {
00364 char *new_session_key;
00365 char query[1024];
00366 MYSQL_RES *res;
00367 int ret;
00368
00369 sprintf(query, "select * from %s where session_key='%s'",
00370 cgisession_table_name, key);
00371
00372 if (0 != (ret = mysql_query(cgisession_mysql_conn, query))) {
00373 #ifdef DEBUG1
00374 printf("\nquery: %s failed with error code %d\n", query, ret);
00375 #endif
00376 return -ERROR;
00377 }
00378
00379 if (NULL==(res = mysql_store_result(cgisession_mysql_conn))) {
00380 #ifdef DEBUG1
00381 printf("\nmysql_store_result failed\n");
00382 return -ERROR;
00383 #endif
00384 }
00385
00386 if (1 != (ret = mysql_num_rows(res))) {
00387 #ifdef DEBUG1
00388 printf("\ninvalid number of rows: %d\n", ret);
00389 #endif
00390 return -ERROR;
00391 }
00392
00393
00394
00395
00396
00397
00398 new_session_key = cgisession_genkey();
00399
00400 sprintf(query, "update %s set session_key='%s' "
00401 "where session_key='%s'", cgisession_table_name,
00402 new_session_key, key);
00403
00404 if (0!=(ret = mysql_query(cgisession_mysql_conn, query))) {
00405 #ifdef DEBUG1
00406 printf("query: %s failed with error code %d", query, ret);
00407 #endif
00408 return -ERROR;
00409 }
00410
00411 if (cs.key != NULL)
00412 free(cs.key);
00413 cs.key = new_session_key;
00414
00415 return 0;
00416 }
00417
00418 static int cgisession_load_all()
00419 {
00420 char query[1024];
00421 char buf[1024];
00422 MYSQL_RES *res;
00423 MYSQL_ROW row;
00424 unsigned long *lengths;
00425 int ret;
00426
00427 sprintf(query, "select * from %s where session_key='%s'",
00428 cgisession_table_name, cs.key);
00429
00430 if (0!=(ret = mysql_query(cgisession_mysql_conn, query))) {
00431 #ifdef DEBUG1
00432 printf("query: %s failed with error code %d", query, ret);
00433 #endif
00434 return -ERROR;
00435 }
00436
00437 if (NULL == (res = mysql_store_result(cgisession_mysql_conn)))
00438 return -ERROR;
00439
00440 if (NULL == (row = mysql_fetch_row(res)))
00441 return -ERROR;
00442
00443 lengths = mysql_fetch_lengths(res);
00444
00445
00446 memcpy(buf, row[1], lengths[1]);
00447 buf[lengths[1]] = '\0';
00448 cs.timestamp = atoi(buf);
00449
00450
00451 memcpy(buf, row[2], lengths[2]);
00452 buf[lengths[2]] = '\0';
00453 cs.timeout = atoi(buf);
00454
00455 if (0 != cgisession_decode_data(row[3], lengths[3]))
00456 return -ERROR;
00457
00458 mysql_free_result(res);
00459
00460 return 0;
00461 }
00462
00467 static char *cgisession_genkey()
00468 {
00469 MYSQL_ROW row;
00470 MYSQL_RES *res;
00471 char *new_session = NULL;
00472 char *query = "select password(rand())";
00473 unsigned long *lengths;
00474 int ret;
00475
00476
00477
00478 if (0!=(ret = mysql_query(cgisession_mysql_conn, query))) {
00479 #ifdef DEBUG1
00480 printf("\nquery: %s failed with code %d\n", query, ret);
00481 #endif
00482 return NULL;
00483 }
00484
00485 if (NULL==(res = mysql_store_result(cgisession_mysql_conn)))
00486 return NULL;
00487
00488 if (NULL==(row = mysql_fetch_row(res)))
00489 return NULL;
00490
00491 lengths = mysql_fetch_lengths(res);
00492
00493
00494 new_session = (char *) malloc(lengths[0] + 1);
00495 if (new_session == NULL)
00496 return NULL;
00497
00498 memcpy(new_session, row[0], lengths[0]);
00499
00500 new_session[lengths[0]] = '\0';
00501
00502 mysql_free_result(res);
00503
00504 return new_session;
00505 }
00506
00507
00508 static char *cgisession_encode_data()
00509 {
00510 char *encoded = NULL;
00511 switch (cs.encoding) {
00512 case ENC_TYPE_NONE:
00513 if (NULL==cs.data)
00514 return NULL;
00515 encoded = malloc(cs.size);
00516 memcpy(encoded, cs.data, cs.size);
00517 break;
00518 default:
00519 #ifdef DEBUG1
00520 printf("cgisession_encode_data: unknown encoding type!");
00521 #endif
00522 return NULL;
00523 }
00524
00525 return encoded;
00526 }
00527
00528
00529
00530
00531 static int cgisession_decode_data(char *encoded, long enc_size)
00532 {
00533
00534
00535 if (NULL != cs.data)
00536 free(cs.data);
00537
00538 switch (cs.encoding) {
00539 case ENC_TYPE_NONE:
00540 cs.data = malloc(enc_size);
00541 memcpy(cs.data, encoded, enc_size);
00542 cs.data[enc_size]='\0';
00543 cs.size = enc_size;
00544 return 0;
00545 case ENC_TYPE_BASE64:
00546 exit(1000);
00547 return -ERROR;
00548 }
00549
00550 return -ERROR;
00551 }
00552
00553 #endif