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; // 立即断开与客户端的连接
}
Leave a Reply