/** * @short Gets the sessionid cookie, if any, and sets it to req->session_id. * @memberof onion_request_t */ void onion_request_guess_session_id(onion_request *req){ if (req->session_id) // already known. return; const char *v=onion_dict_get(req->headers, "Cookie"); ONION_DEBUG("Session ID, maybe from %s",v); char *r=NULL; onion_dict *session; do{ // Check all possible sessions if (r) free(r); if (!v) return; v=strstr(v,"sessionid="); if (!v) // exit point, no session found. return; v+=10; r=strdup(v); // Maybe allocated more memory, not much anyway. char *p=r; while (*p!='\0' && *p!=';') p++; *p='\0'; ONION_DEBUG0("Checking if %s exists in sessions", r); session=onion_sessions_get(req->server->sessions, r); }while(!session); req->session_id=r; req->session=session; ONION_DEBUG("Session ID, from cookie, is %s",req->session_id); }
/** * @short Returns the session dict. * @memberof onion_request_t * * If it does not exists it creates it. If there is a cookie with a proper name it is used, * even for creation. * * Returned dictionary can be freely managed (added new keys...) and this is the session data. */ onion_dict *onion_request_get_session_dict(onion_request *req){ if (!req->session){ onion_request_guess_session_id(req); if (!req->session){ // Maybe old session is not to be used anymore req->session_id=onion_sessions_create(req->server->sessions); req->session=onion_sessions_get(req->server->sessions, req->session_id); } } return req->session; }
/** * @short Returns the session dict. * @memberof onion_request_t * * If it does not exists it creates it. If there is a cookie with a proper name it is used, * even for creation. * * Sessions HAVE TO be gotten before sending any header, or user may face double sessionid, ghost sessions and some other * artifacts, as the cookie is not set if session is not used. If this condition happen (send headers and then ask for session) a * WARNING is written. * * Session is not automatically retrieved as it is a slow operation and not used normally, only on "active" handlers. * * Returned dictionary can be freely managed (added new keys...) and this is the session data. * * @return session dictionary for current request. */ onion_dict *onion_request_get_session_dict(onion_request *req) { if (!req->session) { if (req->flags & OR_HEADER_SENT) { ONION_WARNING("Asking for session AFTER sending headers. This may result in double sessionids, and wrong session behaviour. Please modify your handlers to ask for session BEFORE sending any data."); } onion_request_guess_session_id(req); if (!req->session) { // Maybe old session is not to be used anymore req->session_id=onion_sessions_create(req->connection.listen_point->server->sessions); req->session=onion_sessions_get(req->connection.listen_point->server->sessions, req->session_id); } } return req->session; }
/** * @short Gets the sessionid cookie, if any, and sets it to req->session_id. * @memberof onion_request_t */ void onion_request_guess_session_id(onion_request *req) { if (req->session_id) // already known. return; const char *ov=onion_dict_get(req->headers, "Cookie"); const char *v=ov; ONION_DEBUG("Session ID, maybe from %s",v); char *r=NULL; onion_dict *session=NULL; do { // Check all possible sessions if (r) { onion_low_free(r); r=NULL; } if (!v) return; v=strstr(v,"sessionid="); if (!v) // exit point, no session found. return; if (v>ov && isalnum(v[-1])) { ONION_DEBUG("At -1: %c %d (%p %p)",v[-1],isalnum(v[-1]),v,ov); v=strstr(v,";"); } else { v+=10; r=onion_low_strdup(v); // Maybe allocated more memory, not much anyway. char *p=r; while (*p!='\0' && *p!=';') p++; *p='\0'; ONION_DEBUG0("Checking if %s exists in sessions", r); session=onion_sessions_get(req->connection.listen_point->server->sessions, r); } } while(!session); req->session_id=r; req->session=session; ONION_DEBUG("Session ID, from cookie, is %s",req->session_id); }
void t01_test_session(){ INIT_LOCAL(); onion_sessions *sessions=onion_sessions_new(); // create a session onion_dict *ses=onion_sessions_get(sessions, "s01"); FAIL_IF_NOT_EQUAL(ses, NULL); // It does not auto create the sessions, to avoid problems char *s01=onion_sessions_create(sessions); ses=onion_sessions_get(sessions, s01); FAIL_IF_EQUAL(ses, NULL); // It does not auto create the sessions, to avoid problems // get another pointer to the same session onion_dict *ses2=onion_sessions_get(sessions, s01); FAIL_IF_NOT_EQUAL(ses, ses2); //Check it is really the same onion_dict_add(ses, "foo", "bar", 0); FAIL_IF_NOT_EQUAL_STR("bar", onion_dict_get(ses2, "foo")); // When removed, it should refcount-- onion_dict_free(ses2); ses2=onion_sessions_get(sessions, s01); FAIL_IF_NOT_EQUAL(ses, ses2); // also all removal, should stay at the sessions onion_dict_free(ses); onion_dict_free(ses2); ses2=onion_sessions_get(sessions, s01); FAIL_IF_NOT_EQUAL_STR("bar", onion_dict_get(ses2, "foo")); onion_dict_free(ses2); // Create a second session char *s02=onion_sessions_create(sessions); ses2=onion_sessions_get(sessions, s02); onion_dict_add(ses2, "hello", "world", 0); ses=onion_sessions_get(sessions, s01); FAIL_IF_EQUAL_STR(onion_dict_get(ses, "hello"), onion_dict_get(ses2, "hello")); FAIL_IF_EQUAL_STR(onion_dict_get(ses, "foo"), onion_dict_get(ses2, "foo")); onion_dict_free(ses); onion_dict_free(ses2); // And finally really remove it onion_sessions_remove(sessions, s01); ses2=onion_sessions_get(sessions, s01); FAIL_IF_NOT_EQUAL(ses2, NULL); // this created a new one free(s01); s01=onion_sessions_create(sessions); ses2=onion_sessions_get(sessions, s01); FAIL_IF_EQUAL_STR("bar", onion_dict_get(ses2, "foo")); onion_dict_free(ses2); // This should remove the sessions, and still hanging s02 onion_sessions_free(sessions); free(s01); free(s02); END_LOCAL(); }