📄 session.c
字号:
/** * 实现 session 支持 * * 在 RedHat 9 上成功编译,如果要用于 freebsd,修改 md5 相关部分就行了。 */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <sys/types.h>#include <md5.h>#include "session.h"#include "cgic.h"SESSION_DATA* g_session_data = NULL;const char* g_session_filename_prefix = "sess_";/** * 为当前访问者启用 session * * @param const char* datadir 用于保存 session 数据文件的目录 * * @return int 成功返回0,失败返回非0值 */int session_start(const char* datadir) { char cookie_session_id[34]; int result; if (g_session_data != NULL) { fprintf(cgiOut, "Warning: session_start() calls again.<br />\n"); return -1; } // 初始化 session_data sess_init(datadir); // 根据 cookie 状态确定是创建新 session 还是载入现有的 session result = cgiCookieString("SESSION_ID", cookie_session_id, 33);#ifdef DEBUG fprintf(stderr, "cgiCookieString() result: %u\n", result); fprintf(stderr, "cookie_session_id: %s\n", cookie_session_id);#endif if (result != cgiFormSuccess) { // 没有找到有效的 cookie session_id,创建一个新 session result = sess_create(); } else { result = sess_load(cookie_session_id, datadir); } return result;}/** * 关闭 session 并将 session 数据写入临时文件并关闭 session * * @return int 成功返回0,失败返回非0值 */int session_write_close() { FILE* fp = NULL; size_t i = 0; char* buffer = NULL; if (g_session_data == NULL) { fprintf(cgiOut, "Warning: You must make your calls to session_close()" " AFTER invoking session_start().<br />\n"); return -1; }#ifdef DEBUG fprintf(stderr, "session_write_close() <-- BEGIN\n");#endif fp = fopen(g_session_data->session_filename, "w"); if (fp == NULL) { fprintf(cgiOut, "Warning: Can't create session file: %s.<br />\n", g_session_data->session_filename); return -1; } // 开始写入 session 数据 for (i = 0; i < g_session_data->max_index; i++) { if (g_session_data->items[i].name == NULL) { continue; } buffer = sess_serialize(g_session_data->items[i].name); fputs(buffer, fp); fputs("\n", fp); free(buffer); buffer = NULL; buffer = sess_serialize(g_session_data->items[i].string); fputs(buffer, fp); fputs("\n", fp); free(buffer); buffer = NULL; } fclose(fp); #ifdef DEBUG session_dump(stderr); fprintf(stderr, "session_write_close() END -->\n");#endif // 释放 session 占用的资源 sess_free_resource(); return 0;}/** * 销毁当前访问者的 session * * @return int 成功返回0,失败返回非0值 */int session_destroy() { if (g_session_data == NULL) { fprintf(cgiOut, "Warning: You must make your calls to session_destroy()" " AFTER invoking session_start().<br />\n"); return -1; }#ifdef DEBUG fprintf(stderr, "session_destroy()\n"); session_dump(stderr);#endif // 删除 session 数据文件 remove(g_session_data->session_filename); // 释放 session 占用的资源 sess_free_resource(); return 0;}/** * 设置要保存在 session 中的字符串 * * @param const char* name 字符串的名字 * @param const char* string 字符串 * * @return int 成功返回0,失败返回非0值 */int session_set(const char* name, const char* string) { int i; SESSION_ITEM_LIST tmp_list = NULL; size_t buffer_size; #ifdef DEBUG fprintf(stderr, "session_set(), session file:%s\n", g_session_data->session_filename);#endif for (i = 0; i < g_session_data->max_index; i++) { if (g_session_data->items[i].name == NULL) { // 找到空闲的项目 g_session_data->items[i].name = (char*)malloc((strlen(name) + 1) * sizeof(char)); strcpy(g_session_data->items[i].name, name); g_session_data->items[i].string = (char*)malloc((strlen(string) + 1) * sizeof(char)); strcpy(g_session_data->items[i].string, string); g_session_data->count++; return 0; } } // 需要扩充容量 i = g_session_data->max_index + (g_session_data->max_index / 2) + 2; buffer_size = i * sizeof(SESSION_ITEM); tmp_list = (SESSION_ITEM*)malloc(buffer_size); memset(tmp_list, 0, buffer_size); memcpy(tmp_list, g_session_data->items, g_session_data->max_index * sizeof(SESSION_ITEM)); free(g_session_data->items); g_session_data->items = tmp_list; g_session_data->max_index = i; return session_set(name, string);}/** * 取出保存在 session 中的字符串 * * @param const char* name 字符串的名字 * * @return const char* 保存的字符串,如果没找到则返回 NULL */const char* session_get(const char* name) { size_t i; if (g_session_data == NULL) { fprintf(cgiOut, "Warning: You must make your calls to session_get()" " AFTER invoking session_start().<br />\n"); return NULL; } #ifdef DEBUG fprintf(stderr, "session_get(), session file:%s\n", g_session_data->session_filename);#endif for (i = 0; i < g_session_data->max_index; i++) { if (g_session_data->items[i].name == NULL) { continue; } if (strcmp(g_session_data->items[i].name, name) == 0) { return g_session_data->items[i].string; } } return NULL;}/** * 从 session 中删除指定的字符串 * * @param const char* name 字符串的名字 * * @return int 成功返回0,失败返回非0值 */int session_unset(const char* name) { size_t i; if (g_session_data == NULL) { fprintf(cgiOut, "Warning: You must make your calls to session_unset()" " AFTER invoking session_start().<br />\n"); return -1; } #ifdef DEBUG fprintf(stderr, "session_unset(), session file:%s\n", g_session_data->session_filename);#endif for (i = 0; i < g_session_data->max_index; i++) { if (strcmp(g_session_data->items[i].name, name) == 0) { // 找到匹配的项目 free(g_session_data->items[i].name); free(g_session_data->items[i].string); g_session_data->items[i].name = NULL; g_session_data->items[i].string = NULL; g_session_data->count--; return 0; } } return -1;}/** * 从 session 中删除所有数据 * * @return int 成功返回0,失败返回非0值 */int session_unset_all() { size_t i; if (g_session_data == NULL) { fprintf(cgiOut, "Warning: You must make your calls to session_destroy()" " AFTER invoking session_start().<br />\n"); return -1; } 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); g_session_data->items[i].name = NULL; g_session_data->items[i].string = NULL; } g_session_data->count = 0; return 0;}/** * 初始化 session_data * * @param const char* datadir */void sess_init(const char* datadir) { if (g_session_data != NULL) { return; } // 为 session 数据分配内存 g_session_data = (SESSION_DATA*)malloc(sizeof(SESSION_DATA)); memset(g_session_data, 0, sizeof(SESSION_DATA)); g_session_data->session_datadir = (char*)malloc((strlen(datadir) + 2) * sizeof(char)); strcpy(g_session_data->session_datadir, datadir); if (datadir[strlen(datadir) - 1] != '/') { strcat(g_session_data->session_datadir, "/"); }}/** * 创建一个新 session * * @return int 成功返回0,失败返回非0值 */int sess_create() { const int init_index = 10; int i; if (g_session_data == NULL) { return -1; }#ifdef DEBUG fprintf(stderr, "sess_create()\n");#endif // 构造 session id g_session_data->session_id = sess_make_session_id(); g_session_data->session_filename = sess_get_filename(g_session_data->session_datadir, g_session_data->session_id); // 初始化 session item 列表的存储空间 g_session_data->items = (SESSION_ITEM*)malloc(init_index * sizeof(SESSION_ITEM)); for (i = 0; i < init_index; i++) { g_session_data->items[i].name = NULL; g_session_data->items[i].string = NULL; } g_session_data->max_index = init_index; // 写入 cookie cgiHeaderCookieSetString("SESSION_ID", g_session_data->session_id, 900, "/", cgiServerName); return 0;}/** * 载入现有的 session * * @param const char* session_id 要读取的 session_id
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -