227 lines
5.7 KiB
C
227 lines
5.7 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <limits.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
struct session_s {
|
|
char *session_id;
|
|
char *user;
|
|
struct session_s *next;
|
|
};
|
|
|
|
typedef struct session_s session_t;
|
|
|
|
struct hashtable_s {
|
|
int size;
|
|
struct session_s **table;
|
|
};
|
|
|
|
typedef struct hashtable_s hashtable_t;
|
|
|
|
static hashtable_t *ht_create( int size );
|
|
static int ht_hash( hashtable_t *hashtable, char *session_id );
|
|
static session_t *ht_newpair( char *session_id, char *user );
|
|
static session_t *ht_get( hashtable_t *hashtable, char *session_id );
|
|
static void ht_set( hashtable_t *hashtable, char *session_id, char *user );
|
|
static void ht_delete (hashtable_t *hashtable, char *key);
|
|
static char *gen_session_id(int len);
|
|
static char *set_cookie_header( const char *champ, const char separator,
|
|
const char *session_id);
|
|
|
|
|
|
/* Create a new hashtable. */
|
|
hashtable_t *ht_create( int size ) {
|
|
hashtable_t *hashtable = NULL;
|
|
int i;
|
|
|
|
if( size < 1 ) return NULL;
|
|
|
|
/* Allocate the table itself. */
|
|
if( ( hashtable = malloc( sizeof( hashtable_t ) ) ) == NULL ) {
|
|
return NULL;
|
|
|
|
}
|
|
|
|
/* Allocate pointers to the head nodes. */
|
|
if( ( hashtable->table = malloc( sizeof( session_t * ) * size ) ) == NULL ) {
|
|
return NULL;
|
|
}
|
|
for( i = 0; i < size; i++ ) {
|
|
hashtable->table[i] = NULL;
|
|
}
|
|
|
|
hashtable->size = size;
|
|
|
|
return hashtable;
|
|
}
|
|
|
|
/* Hash a string for a particular hash table. */
|
|
int ht_hash( hashtable_t *hashtable, char *session_id ) {
|
|
|
|
unsigned long int hashval = 0;
|
|
int i = 0;
|
|
|
|
/* Convert our string to an integer */
|
|
while( hashval < ULONG_MAX && i < strlen( session_id ) ) {
|
|
hashval = hashval << 8;
|
|
hashval += session_id[ i ];
|
|
i++;
|
|
}
|
|
|
|
return hashval % hashtable->size;
|
|
}
|
|
|
|
/* Create a key-value pair. */
|
|
session_t *ht_newpair( char *session_id, char *user ) {
|
|
session_t *newpair;
|
|
|
|
if( ( newpair = malloc( sizeof( session_t ) ) ) == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
if( ( newpair->session_id = strdup( session_id ) ) == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
if( ( newpair->user = strdup( user ) ) == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
newpair->next = NULL;
|
|
|
|
return newpair;
|
|
}
|
|
|
|
/* Insert a key-value pair into a hash table. */
|
|
static void ht_set( hashtable_t *hashtable, char *session_id, char *user ) {
|
|
int bin = 0;
|
|
session_t *newpair = NULL;
|
|
session_t *next = NULL;
|
|
session_t *last = NULL;
|
|
|
|
bin = ht_hash( hashtable, session_id );
|
|
|
|
next = hashtable->table[ bin ];
|
|
|
|
while( next != NULL && next->session_id != NULL && strcmp( session_id, next->session_id ) > 0 ) {
|
|
last = next;
|
|
next = next->next;
|
|
}
|
|
|
|
/* There's already a pair. Let's replace that string. */
|
|
if( next != NULL && next->session_id != NULL && strcmp( session_id, next->session_id ) == 0 ) {
|
|
|
|
free( next->user );
|
|
next->user = strdup( user );
|
|
|
|
/* Nope, could't find it. Time to grow a pair. */
|
|
} else {
|
|
newpair = ht_newpair( session_id, user );
|
|
|
|
/* We're at the start of the linked list in this bin. */
|
|
if( next == hashtable->table[ bin ] ) {
|
|
newpair->next = next;
|
|
hashtable->table[ bin ] = newpair;
|
|
|
|
/* We're at the end of the linked list in this bin. */
|
|
} else if ( next == NULL ) {
|
|
last->next = newpair;
|
|
|
|
/* We're in the middle of the list. */
|
|
} else {
|
|
newpair->next = next;
|
|
last->next = newpair;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Retrieve a key-value pair from a hash table. */
|
|
static session_t *ht_get( hashtable_t *hashtable, char *session_id ) {
|
|
int bin = 0;
|
|
session_t *pair;
|
|
|
|
bin = ht_hash( hashtable, session_id );
|
|
|
|
/* Step through the bin, looking for our value. */
|
|
pair = hashtable->table[ bin ];
|
|
while( pair != NULL && pair->session_id != NULL && strcmp( session_id, pair->session_id ) > 0 ) {
|
|
pair = pair->next;
|
|
}
|
|
|
|
/* Did we actually find anything? */
|
|
if( pair == NULL || pair->session_id == NULL || strcmp( session_id, pair->session_id ) != 0 )
|
|
{
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
return pair;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void ht_delete (hashtable_t *hashtable, char *key){
|
|
|
|
int bin = 0;
|
|
session_t *pair;
|
|
session_t *prec;
|
|
|
|
bin = ht_hash( hashtable, key );
|
|
/* Step through the bin, looking for our value. */
|
|
pair = hashtable->table[ bin ];
|
|
while( pair != NULL && pair->session_id != NULL && strcmp( key, pair->session_id ) > 0 ) {
|
|
prec = pair;
|
|
pair = pair->next;
|
|
}
|
|
|
|
/* Did we actually find anything? */
|
|
if( pair != NULL || pair->session_id != NULL || strcmp( key, pair->session_id ) == 0 ) {
|
|
free(pair->session_id);
|
|
free(pair->user);
|
|
}
|
|
}
|
|
|
|
char *gen_session_id(int len){
|
|
|
|
int index = 0;
|
|
char session_id[len];
|
|
char char1[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/,.-+~`<>:";
|
|
int c_tmp = 0;
|
|
char *res;
|
|
srand((unsigned int)(time(NULL)));
|
|
|
|
for(index = 0; index < len; index++)
|
|
{
|
|
c_tmp = rand() % sizeof(char1) - 1;
|
|
session_id[index] = char1[c_tmp];
|
|
}
|
|
session_id[len] = '\0';
|
|
res = strdup(session_id);
|
|
|
|
return res;
|
|
}
|
|
|
|
char *set_cookie_header( const char *champ, const char separator,
|
|
const char *session_id) {
|
|
int lch, lse;
|
|
int ls = 0;
|
|
char *result;
|
|
lch = strlen(champ);
|
|
lse = strlen(session_id);
|
|
if (separator)
|
|
ls = 1;
|
|
|
|
result = calloc(lch + ls + lse + 1, sizeof *result);
|
|
|
|
if (result != NULL) {
|
|
memcpy (result, champ, lch);
|
|
if (separator)
|
|
result[lch] = separator;
|
|
|
|
memcpy (result + lch + ls, session_id, lse + 1 );
|
|
}
|
|
return result;
|
|
}
|