acl/app/jaws/plugin/cgi/http_cgi.c

221 lines
4.9 KiB
C
Raw Blame History

#include "lib_acl.h"
#include "http_plugin.h"
typedef struct {
ACL_VSTRING *alias;
ACL_VSTRING *cgi;
} CGI_MAP;
static ACL_HTABLE *__table = NULL;
static CGI_MAP *cgi_map_new(const char *alias, const char *cgi)
{
CGI_MAP *map = (CGI_MAP*) acl_mycalloc(1, sizeof(CGI_MAP));
map->alias = acl_vstring_alloc(256);
map->cgi = acl_vstring_alloc(256);
acl_vstring_strcpy(map->alias, alias);
acl_vstring_strcpy(map->cgi, var_cfg_cgi_bin);
acl_vstring_strcpy(map->cgi, cgi);
return (map);
}
static void cgi_map_free(CGI_MAP *map)
{
acl_vstring_free(map->alias);
acl_vstring_free(map->cgi);
acl_myfree(map);
}
void http_cgi_init()
{
__table = acl_htable_create(10, 0);
}
void http_cgi_end()
{
acl_htable_free(__table, (void (*)(void*)) cgi_map_free);
}
void http_cgi_add2(const char *alias, const char *cgi)
{
CGI_MAP *map;
map = (CGI_MAP*) acl_htable_find(__table, alias);
if (map != NULL) {
acl_msg_warn("%s(%d): alias(%s) already exist",
__FUNCTION__, __LINE__, alias);
return;
}
map = cgi_map_new(alias, cgi);
acl_htable_enter(__table, alias, map);
}
void http_cgi_add1(const ACL_ARGV *args)
{
if (args->argc < 2) {
acl_msg_error("%s(%d): argc(%d) < 2",
__FUNCTION__, __LINE__, args->argc);
return;
}
http_cgi_add2(args->argv[0], args->argv[1]);
}
CGI *http_cgi_path(const char *alias)
{
CGI *cgi;
CGI_MAP *map = (CGI_MAP*) acl_htable_find(__table, alias);
if (map == NULL)
return (NULL);
cgi = (CGI*) acl_mycalloc(1, sizeof(CGI));
cgi->alias = acl_mystrdup(alias);
cgi->cgi = acl_mystrdup(STR(map->cgi));
return (cgi);
}
static void cgi_free(CGI *cgi)
{
if (cgi == NULL)
return;
if (cgi->client)
acl_vstream_close(cgi->client);
if (cgi->hdr_req)
http_hdr_req_free(cgi->hdr_req);
if (cgi->req) {
cgi->req->hdr_req = NULL;
http_req_free(cgi->req);
}
if (cgi->hdr_res)
http_hdr_res_free(cgi->hdr_res);
if (cgi->cgi)
acl_myfree(cgi->cgi);
if (cgi->alias)
acl_myfree(cgi->alias);
acl_myfree(cgi);
}
static void run_cgi(CGI *cgi, ACL_ARGV *env)
{
char *command = cgi->cgi;
ACL_VSTREAM *stream;
ACL_VSTRING *vbuf;
ACL_ARGV *cgi_hdrs;
char buf[4096];
int ret, errnum = 200;
char **cpp;
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>CGI<47><49><EFBFBD><EFBFBD><EFBFBD>Ĺܵ<C4B9><DCB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
stream = acl_vstream_popen(O_RDWR,
ACL_VSTREAM_POPEN_COMMAND, command,
ACL_VSTREAM_POPEN_ENV, env->argv,
ACL_VSTREAM_POPEN_END);
if (stream == NULL) {
acl_msg_error("%s(%d): open command(%s) error(%s)",
__FUNCTION__, __LINE__, command, acl_last_serror());
return;
}
cgi->req = http_req_new(cgi->hdr_req);
if (cgi->hdr_req->hdr.content_length > 0) {
while (1) {
ret = (int) http_req_body_get_sync(cgi->req, cgi->client,
buf, sizeof(buf) - 1);
if (ret <= 0)
break;
if (acl_vstream_writen(stream, buf, ret) == ACL_VSTREAM_EOF) {
acl_vstream_close(stream);
return;
}
}
}
/*
* http_hdr_set_keepalive(cgi->hdr_req, cgi->hdr_res);
*/
cgi_hdrs = acl_argv_alloc(10);
/* <20><>CGI<47><49><EFBFBD>͵<EFBFBD><CDB5><EFBFBD>Ӧͷ */
while (1) {
char *pname, *ptr;
ret = acl_vstream_gets_nonl(stream, buf, sizeof(buf));
if (ret == ACL_VSTREAM_EOF) {
acl_msg_error("%s(%d): cgi exit exception",
__FUNCTION__, __LINE__);
errnum = 500;
break;
}
if (ret == 0) {
break;
}
ptr = buf;
pname = acl_mystrtok(&ptr, ":\t ");
if (ptr == NULL) {
acl_msg_warn("%s(%d): cgi reply hdr(%s) invalid",
__FUNCTION__, __LINE__, buf);
continue;
}
acl_argv_add(cgi_hdrs, pname, ptr, NULL);
}
vbuf = acl_vstring_alloc(256);
cgi->hdr_res = http_hdr_res_static(errnum);
for (cpp = cgi_hdrs->argv; *cpp; cpp += 2) {
http_hdr_put_str(&cgi->hdr_res->hdr, cpp[0], cpp[1]);
}
http_hdr_entry_replace(&cgi->hdr_res->hdr, "Connection", "close", 1);
http_hdr_build(&cgi->hdr_res->hdr, vbuf);
ret = acl_vstream_writen(cgi->client, STR(vbuf), LEN(vbuf));
if (ret > 0) {
/* <20><>CGI<47><49><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E5B2A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
while (1) {
ret = acl_vstream_read(stream, buf, sizeof(buf));
if (ret == ACL_VSTREAM_EOF)
break;
if (acl_vstream_writen(cgi->client, buf, ret) == ACL_VSTREAM_EOF)
break;
}
}
acl_vstring_free(vbuf);
acl_vstream_pclose(stream);
}
void http_cgi_thread(void *ctx)
{
CGI *cgi = (CGI*) ctx;
HTTP_HDR_REQ *hdr_req = cgi->hdr_req;
ACL_ARGV *env = acl_argv_alloc(10);
ACL_ITER iter;
const char *reply = "HTTP/1.1 200 OK\r\n"
"Date: Sun, 15 Nov 2009 07:06:22 GMT\r\n"
"Server: Apache/2.2.9 (Unix)\r\n"
"Connection: close\r\n"
"Content-Type: text/html\r\n\r\n";
acl_foreach(iter, hdr_req->hdr.entry_lnk) {
HTTP_HDR_ENTRY *entry = (HTTP_HDR_ENTRY*) iter.data;
if (entry->off)
continue;
acl_argv_add(env, entry->name, entry->value, NULL);
}
if (1)
run_cgi(cgi, env);
else {
acl_vstream_writen(cgi->client, reply, sizeof(reply));
}
acl_argv_free(env);
cgi_free(cgi);
}