#include #include #include #include #include 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; }