本文最后更新于 2227 天前,其中的信息可能已经有所发展或是发生改变。
PLAPI.h
#pragma once #include <iostream> #ifndef NULL #define NULL 0 #endif #ifndef WINAPI #define WINAPI __stdcall #endif #define NEW(p, size) { p = (char *)malloc(size); memset( p, 0, size ); } #define DEL(p) { free((void*)p); p = NULL; } #ifndef MAX_PATH #define MAX_PATH 260 #endif #ifndef MAKEWORD #define MAKEWORD(a, b) ((unsigned short)(((unsigned char)(a)) | ((unsigned short)((unsigned char)(b))) << 8)) #endif #define PLAPI extern "C" __declspec(dllexport) #define PLAPI_ServerFunc bool (WINAPI *ServerFunc)(int dwServerID, int dwConnID, int dwAction, int dwFlag, void *lpvBuffer, int ilength) #define PLAPI_GetEnvVar bool(WINAPI *GetEnvVar)(int dwServerID, int dwConnID, const char *lpszVarName, void *lpvBuffer) #define PLAPI_Read bool(WINAPI *Read)(int dwServerID, int dwConnID, void *lpvBuffer, int dwBytesToRead, int *dwBytesRead) #define PLAPI_Write bool(WINAPI *Write)(int dwServerID, int dwConnID, const void *lpvBuffer, int ilength) #define PLUME_EVENT_BEGIN_CONN 1 #define PLUME_EVENT_DONE_CONN 2 #define PLUME_EVENT_BEGIN_REQUEST 3 #define PLUME_EVENT_DONE_REQUEST 4 #define PLUME_EVENT_ONSEND 5 #define PLUME_EVENT_ONBODY 6 #define PLUME_EVENT_RESULT_STOP 0 #define PLUME_EVENT_RESULT_CONTINUE 1 #define PLUME_EVENT_RESULT_DISCONNECT 2 #define PLUME_ACTION_REGISTER_EVENT 0 #define PLUME_ACTION_LOG 1 #define PLUME_ACTION_SEND_CUSTOM_ERROR 2 #define PLUME_ACTION_READ_CONFIG 3 #define PLUME_ACTION_SEND_HEADER 4 #define PLUME_ACTION_DONE_REQUEST 5 #define PLUME_ACTION_GET_CONNECTION_COUNTS 6 #define PLUME_PROC_RESULT_SUCCESS 1 #define PLUME_PROC_RESULT_FAILURE 0 typedef struct plume_server { int dwServerID; int dwConnID; PLAPI_GetEnvVar; PLAPI_Read; PLAPI_Write; PLAPI_ServerFunc; } plume_server; typedef struct plume_path_struct { char* pConnDIR; char* pPathTranslated; char* pPath; } plume_path_struct; typedef struct plume_readconfig_struct { char* pSectionName; char* pKeyName; char* pValue; } plume_readconfig_struct; PLAPI bool WINAPI Plume_InitPlugin(int dwServerVersion, PLAPI_ServerFunc); PLAPI int WINAPI Plume_PluginProc(plume_server * plume_server); PLAPI void WINAPI Plume_GetPluginDesc(char **lpszName, char **lpszVersion, char **lpszAuthor, char **lpszDescription); // Usage : // char **pConnDIR, **pPathTranslated, **pPath, **pPathInfo; // Plume_GetPathStruct(s, &pConnDIR, &pPathTranslated, &pPath, &pPathInfo); // strcpy(*..., "Dest String"); bool Plume_GetPathStruct(plume_server *s, char ***pConnDIR, char ***pPathTranslated, char ***pPath) { int ptr; if (!s->GetEnvVar(s->dwServerID, s->dwConnID, "Plume_PathStruct", &ptr)) return false; *pConnDIR = (char **)ptr; *pPathTranslated = (char **)(ptr + 4); *pPath = (char **)(ptr + 8); return true; }
PLAPI.cpp
#include "PLAPI.h" #define PLUGIN_NAME "SDK Plugin" #define PLUGIN_VER "1.0.0" #define PLUGIN_AUTHOR "iEdon" #define PLUGIN_DESC "Plume PLAPI 插件系统 SDK" // PLAPI SDK // (C) 2012-2017 iEdon Inside // 注意:生成 DLL 请注意设置项目属性:链接器-->输入-->模块定义文件为 PLAPI.def,项目类型为动态链接库 (DLL) int Plugin_Event_Callback(plume_server *s, int dwEventType); PLAPI void WINAPI Plume_GetPluginDesc(char **lpszName, char **lpszVersion, char **lpszAuthor, char **lpszDescription) { *lpszName = PLUGIN_NAME; *lpszVersion = PLUGIN_VER; *lpszAuthor = PLUGIN_AUTHOR; *lpszDescription = PLUGIN_DESC; } PLAPI bool WINAPI Plume_InitPlugin(int dwServerVersion, PLAPI_ServerFunc) { char *log = "\tPlume SDK Plugin v1.0.1\n"; ServerFunc(NULL, NULL, PLUME_ACTION_LOG, NULL, log, strlen(log)); // 向错误日志输出信息 printf(log); // 向调试控制台输入信息 if (MAKEWORD(4, 0) > dwServerVersion) { log = "Not supported version yet.\n"; ServerFunc(NULL, NULL, PLUME_ACTION_LOG, NULL, log, strlen(log)); printf(log); return false; } ServerFunc(NULL, NULL, PLUME_ACTION_REGISTER_EVENT, PLUME_EVENT_BEGIN_REQUEST, Plugin_Event_Callback, NULL); // 注册插件事件为开始请求时调用。 return true; } PLAPI int WINAPI Plume_PluginProc(plume_server * s) // 扩展处理请求 { /* POST 获取数据做法:(注:可通过获取环境变量 REQUEST_METHOD 来判断当前请求类型) // TODO Your Code... char *lpvBuffer = (char *)malloc(4096); memset(lpvBuffer, 0, 4096); s->GetEnvVar(s->dwServerID, s->dwConnID, "CONTENT_LENGTH", lpvBuffer); if(atoi(lpvBuffer) <= 0) { s->ServerFunc(s->dwServerID, s->dwConnID, PLUME_ACTION_SEND_CUSTOM_ERROR, 500, "发生了错误,POST 数据长度错误", strlen("发生了错误,POST 数据长度错误")); free(lpvBuffer); return PLUME_PROC_RESULT_FAILURE; // POST 数据长度不对 } free(lpvBuffer); int dwBytesRead; lpvBuffer = (char *)malloc(40960); while(s->Read(s->dwServerID, s->dwConnID, lpvBuffer, 40960, &dwBytesRead)) { // TODO ... 此处为每块 POST 数据的处理 memset(lpvBuffer, 0, 40960); } free(lpvBuffer); // TODO Your Code... */ /* ServerFunc (PLUME_ACTION_READ_CONFIG) 用法: PLUME_ACTION_READ_CONFIG 用于读取当前网站INI配置文件中的自定义配置信息, 需要构建一个 plume_readconfig_struct,并依次填充INI配置项名、键名,并为接收值分配 MAX_PATH 长度的内存。 // TODO Your Code... plume_readconfig_struct prs; char *lpszValue = (char *)malloc(MAX_PATH); memset(lpszValue, 0, MAX_PATH); prs.pSectionName = "TestConfig"; prs.pKeyName = "keyname"; prs.pValue = lpszValue; s->ServerFunc(s->dwServerID, s->dwConnID, PLUME_ACTION_READ_CONFIG, (int)&prs, NULL, NULL); // 读取配置,获得的返回内容存放于 prs.value。 // TODO Your Code... free(lpszValue); // 这样,就相当于读取了虚拟主机配置文件中 [TestConfig] 里 keyname 的内容。 // ServerFunc (PLUME_ACTION_GET_CONNECTION_COUNTS) 用法: int iConnCounts = 0; s->ServerFunc(s->dwServerID, NULL, PLUME_ACTION_GET_CONNECTION_COUNTS, &iConnCounts, NULL, NULL); */ // 准备正文 char *lpvBuffer = (char *)malloc(4096); memset(lpvBuffer, 0, 4096); s->GetEnvVar(s->dwServerID, s->dwConnID, "SERVER_SOFTWARE", lpvBuffer); // 例:获取环境变量 SERVER_SOFTWARE 的内容 char lpszContext[1024]; sprintf(lpszContext, "<h1>Plume SDK Plugin</h1><br />You are running : %s", lpvBuffer); // 同CGI一样,预处理头部 // 提示:如果输出内容不定长或无法预知长度,可以指定 Transfer-Encoding: chunked 而无需计算 Content-Length。发送头部以后,采用 chunked 编码自由输出不定长内容。 char lpszHeader[128]; sprintf(lpszHeader, "Content-Type: text/html; charset=gb2312\r\nContent-Length: %d", strlen(lpszContext)); s->ServerFunc(s->dwServerID, s->dwConnID, PLUME_ACTION_SEND_HEADER, NULL, lpszHeader, strlen(lpszHeader)); // 同CGI一样,先发送头部 s->Write(s->dwServerID, s->dwConnID, lpszContext, strlen(lpszContext)); // 然后就可以发送正文 s->ServerFunc(s->dwServerID, s->dwConnID, PLUME_ACTION_DONE_REQUEST, NULL, NULL, NULL); // 正常响应后,使用 Done Request 来结束会话并释放连接资源。 // 释放申请的内存 free(lpvBuffer); // 返回成功 return PLUME_PROC_RESULT_SUCCESS; } int Plugin_Event_Callback(plume_server *s, int dwEventType, void *lpvBuffer, int iLength) // 插件事件处理请求 { if (dwEventType == PLUME_EVENT_BEGIN_REQUEST) // 连接开始 { return PLUME_EVENT_RESULT_CONTINUE; // 继续处理 } else { // 发送自定义错误页面后不需要 Done Request. s->ServerFunc(s->dwServerID, s->dwConnID, PLUME_ACTION_SEND_CUSTOM_ERROR, 500, "发生了错误,事件类型不存在。", strlen("发生了错误,事件类型不存在。")); return PLUME_EVENT_RESULT_STOP; // 立即停止处理 } return PLUME_EVENT_RESULT_DISCONNECT; // 立即断开与客户端的连接 }
黑科技 ❓
黑科技
满满的全是一屏的代码,能看懂一点。
感觉c++复杂多了…
是啊,C++可以写死人
我想大喊一句,php是世界上最好的语言 😛
感觉c++复杂多了…
是啊,C++可以写死人
我想大喊一句,php是世界上最好的语言 😛
满满的全是一屏的代码,能看懂一点。
黑科技
黑科技 ❓