📄 session.c
字号:
* @param const char* datadir * * @return int 成功返回0,失败返回非0值 */int sess_load(const char* session_id, const char* datadir) { FILE* fp = NULL; char* buffer = NULL; char* tmp = NULL; SESSION_ITEM_LIST tmp_list = NULL; size_t buffer_length = 2048; int index = 0; if (g_session_data == NULL) { return -1; } #ifdef DEBUG fprintf(stderr, "sess_load() BEGIN -->\n");#endif // 构造 session_data g_session_data->session_id = (char*)malloc((strlen(session_id) + 1) * sizeof(char)); strcpy(g_session_data->session_id, session_id); g_session_data->session_filename = sess_get_filename(g_session_data->session_datadir, g_session_data->session_id);#ifdef DEBUG fprintf(stderr, "sess_load(), session file:%s\n", g_session_data->session_filename);#endif fp = fopen(g_session_data->session_filename, "r"); if (fp == NULL) { // 无效的 session_filename sess_free_resource(); sess_init(datadir); return sess_create(); } buffer = (char*)malloc(buffer_length * sizeof(char)); tmp = buffer; while (!feof(fp)) { if (fgets(tmp, buffer_length, fp) == NULL) { break; } /* if (buffer[strlen(buffer) + 1] != '\n' && !feof(fp)) { // 缓冲区太小,无法容纳该行字符串 buffer_length += buffer_length; tmp = (char*)malloc(buffer_length * sizeof(char)); strcpy(tmp, buffer); free(buffer); buffer = tmp; tmp = buffer += strlen(buffer); continue; } */ // 如果 count >= max_index,则需要增加列表容量 if (g_session_data->count >= g_session_data->max_index) { g_session_data->max_index += 10;#ifdef DEBUG fprintf(stderr, "* items count: %u, max_index grow up to: %u\n", g_session_data->count, g_session_data->max_index);#endif tmp_list = (SESSION_ITEM_LIST)malloc(g_session_data->max_index * sizeof(SESSION_ITEM)); memset(tmp_list, 0, g_session_data->max_index * sizeof(SESSION_ITEM)); if (g_session_data->items != NULL) { memcpy(tmp_list, g_session_data->items, g_session_data->count * sizeof(SESSION_ITEM)); free(g_session_data->items); } g_session_data->items = tmp_list; tmp_list = NULL; } // 添加一个新项目 if ((index % 2) == 0) { tmp = g_session_data->items[g_session_data->count].name;#ifdef DEBUG fprintf(stderr, "read name:");#endif } else { tmp = g_session_data->items[g_session_data->count].string;#ifdef DEBUG fprintf(stderr, "read string:");#endif } if (buffer[strlen(buffer) - 1] == '\n') { buffer[strlen(buffer) - 1] = '\0'; } tmp = sess_unserialize(buffer);#ifdef DEBUG fprintf(stderr, "%s\n", tmp);#endif if ((index % 2) == 0) { g_session_data->items[g_session_data->count].name = tmp; } else { g_session_data->items[g_session_data->count].string = tmp; g_session_data->count++; } // 增加索引,准备读取下一行 tmp = buffer; index++; } free(buffer); fclose(fp); if ((index % 2) != 0) { free(g_session_data->items[g_session_data->count - 1].name); g_session_data->items[g_session_data->count - 1].name = NULL; } #ifdef DEBUG session_dump(stderr);#endif#ifdef DEBUG fprintf(stderr, "sess_load() END -->\n");#endif return 0;}/** * 根据 session_id 生成文件名 * * @param const char* datadir * @param const char* session_id * * @return char* 文件名 */char* sess_get_filename(const char* datadir, const char* session_id) { size_t buffer_size; char* session_filename; char* result; // 再次 md5 是为了避免浏览器送来的畸形 cookie 导致的安全隐患 session_filename = sess_md5_calc(session_id); // 生成 session 文件的完整路径 buffer_size = (strlen(datadir) + strlen(g_session_filename_prefix) + strlen(session_filename)) * sizeof(char); result = (char*)malloc(buffer_size); memset(result, 0, buffer_size); strcpy(result, datadir); strcat(result, g_session_filename_prefix); strcat(result, session_filename); free(session_filename); return result;}/** * 释放 session 资源 */void sess_free_resource() { size_t i; if (g_session_data == NULL) { return; } // 销毁 session 内存映像 for (i = 0; i < g_session_data->max_index; i++) { if (g_session_data->items[i].name == NULL) { continue; } free(g_session_data->items[i].name); free(g_session_data->items[i].string); } free(g_session_data->items); free(g_session_data->session_filename); free(g_session_data->session_id); free(g_session_data->session_datadir); free(g_session_data); g_session_data = NULL;}/** * 根据当前访问者的 IP 地址和浏览器信息等参数生成 session id * * @return char* 保存新 session_id 的缓冲区指针 */char* sess_make_session_id() { char* buffer = NULL; char* session_id = NULL; char* remote_port = NULL; size_t length = 0; remote_port = getenv("REMOTE_PORT"); length = strlen(cgiRemoteAddr); length += strlen(cgiUserAgent); length += strlen(cgiRemoteHost); if (remote_port != NULL) { length += strlen(remote_port); } buffer = (char*)malloc((length + 1) * sizeof(char)); memset(buffer, 0, (length + 1) * sizeof(char)); strcpy(buffer, cgiRemoteAddr); strcat(buffer, cgiUserAgent); strcat(buffer, cgiRemoteHost); if (remote_port != NULL) { strcat(buffer, remote_port); } session_id = sess_md5_calc(buffer); free(buffer); return session_id;}/** * 根据提供的字符串计算 md5 hash * * @param const char* string 要计算 hash 字符串 * * @return char* 保存 md5 hash 的缓冲区指针 */char* sess_md5_calc(const char* string) { MD5_CTX md5ctx; char* buffer = (char*)malloc(33 * sizeof(char)); memset(buffer, 0, 33 * sizeof(char)); MD5Init(&md5ctx); MD5Data(string, strlen(string), buffer); return buffer;}/** * 序列化字符串 * * @param const char* string 要序列化的字符串 * * @return char* 序列化以后的字符串 */ char* sess_serialize(const char* string) { size_t buffer_size = 0; char* buffer = NULL; char* pos = (char *)string; char ch; // 首先确定序列化以后的字符串长度并分配内存 while (*pos) { if (*pos == '\n') { buffer_size += sizeof(char); } buffer_size += sizeof(char); pos++; } buffer_size += sizeof(char); buffer = (char*)malloc(buffer_size); // 将所有的 \n 替换为 \\n pos = buffer; while ((ch = *string) != '\0') { if (ch == '\n') { *pos = '\\'; pos++; ch = 'n'; } *pos = ch; pos++; string++; } *pos = '\0'; return buffer;}/** * 反序列化字符串 * * @param const char* string 要反序列化的字符串 * * @return char* 反序列化以后的字符串 */char* sess_unserialize(const char* string) { size_t buffer_size = (strlen(string) * 2) * sizeof(char); char* buffer = (char*)malloc(buffer_size); char* src = (char *)string; char* dest = buffer; memset(buffer, 0, buffer_size); while (*src) { if (*src == '\\' && *(src + 1) == 'n') { *dest = '\n'; src++; } else { *dest = *src; } src++; dest++; } dest = (char*)malloc((strlen(buffer) + 1) * sizeof(char)); strcpy(dest, buffer); free(buffer); return dest;}/** * 输出 session 的完整内容,用于调试目的 */void session_dump(FILE* fp) { int i; if (g_session_data == NULL) { return; } fprintf(fp, "---------- SESSION dump ----------\n"); fprintf(fp, "session_datadir: %s\n", g_session_data->session_datadir); fprintf(fp, "session_filename: %s\n", g_session_data->session_filename); fprintf(fp, "session_id: %s\n", g_session_data->session_id); fprintf(fp, "count: %u\n", g_session_data->count); fprintf(fp, "max_index: %u\n", g_session_data->max_index); for (i = 0; i < g_session_data->max_index; i++) { if (g_session_data->items[i].name == NULL) { continue; } fprintf(fp, " Item[%u].name = %s\n", i, g_session_data->items[i].name); fprintf(fp, " Item[%u].string = %s\n", i, g_session_data->items[i].string); } fprintf(fp, "---------- Dump end ----------\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -