mirror of
https://github.com/lxsang/ant-http
synced 2024-12-25 16:28:21 +01:00
new api
This commit is contained in:
parent
1e2e600bfc
commit
8d2449bd69
@ -53,3 +53,9 @@ autoconf
|
|||||||
automake --add-missing
|
automake --add-missing
|
||||||
make distcheck
|
make distcheck
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### To do
|
||||||
|
- variable size dictionary
|
||||||
|
- refactoring libantd API, remove unused functions
|
||||||
|
- remove static strings, replace it by configurations
|
||||||
|
@ -25,7 +25,7 @@ ssl.enable=0
|
|||||||
; the SSL cert and key files
|
; the SSL cert and key files
|
||||||
; ssl.cert=fullchain.pem
|
; ssl.cert=fullchain.pem
|
||||||
; ssl.key=privkey.pem
|
; ssl.key=privkey.pem
|
||||||
|
; ssl.cipher=ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
|
||||||
; This enable some plugins to be initialised at server startup
|
; This enable some plugins to be initialised at server startup
|
||||||
[AUTOSTART]
|
[AUTOSTART]
|
||||||
; to start a plugin at server statup use:
|
; to start a plugin at server statup use:
|
||||||
@ -44,6 +44,33 @@ ssl.enable=0
|
|||||||
; ^([a-zA-Z][a-zA-Z0-9]*)\.[a-zA-Z0-9]+\..*$ = /<1><url>?<query>
|
; ^([a-zA-Z][a-zA-Z0-9]*)\.[a-zA-Z0-9]+\..*$ = /<1><url>?<query>
|
||||||
; Sytax: [regular expression on the original request]=[new request rule]
|
; Sytax: [regular expression on the original request]=[new request rule]
|
||||||
|
|
||||||
|
[MIMES]
|
||||||
|
image/bmp=bmp
|
||||||
|
image/jpeg=jpg,jpeg
|
||||||
|
text/css=css
|
||||||
|
text/markdown=md
|
||||||
|
text/csv=csv
|
||||||
|
application/pdf=pdf
|
||||||
|
image/gif=gif
|
||||||
|
text/html=html,htm,chtml
|
||||||
|
application/json=json
|
||||||
|
application/javascript=js
|
||||||
|
image/png=png
|
||||||
|
image/x-portable-pixmap=ppm
|
||||||
|
application/x-rar-compressed=rar
|
||||||
|
image/tiff=tiff
|
||||||
|
application/x-tar=tar
|
||||||
|
text/plain=txt
|
||||||
|
application/x-font-ttf=ttf
|
||||||
|
application/xhtml+xml=xhtml
|
||||||
|
application/xml=xml
|
||||||
|
application/zip=zip
|
||||||
|
image/svg+xml=svg
|
||||||
|
application/vnd.ms-fontobject=eot
|
||||||
|
application/x-font-woff=woff,woff2
|
||||||
|
application/x-font-otf=otf
|
||||||
|
audio/mpeg=mp3,mpeg
|
||||||
|
|
||||||
[FILEHANDLER]
|
[FILEHANDLER]
|
||||||
; specify a plugin for handling
|
; specify a plugin for handling
|
||||||
; a file type
|
; a file type
|
||||||
|
BIN
dist/antd-1.0.4b.tar.gz
vendored
BIN
dist/antd-1.0.4b.tar.gz
vendored
Binary file not shown.
118
http_server.c
118
http_server.c
@ -1,4 +1,26 @@
|
|||||||
#include "http_server.h"
|
#include "http_server.h"
|
||||||
|
|
||||||
|
//define all basic mime here
|
||||||
|
static mime_t _mimes[] = {
|
||||||
|
{"image/bmp","bmp"},
|
||||||
|
{"image/jpeg","jpg,jpeg"},
|
||||||
|
{"text/css","css"},
|
||||||
|
{"text/markdown","md"},
|
||||||
|
{"text/csv","csv"},
|
||||||
|
{"application/pdf","pdf"},
|
||||||
|
{"image/gif","gif"},
|
||||||
|
{"text/html","html"},
|
||||||
|
{"application/json","json"},
|
||||||
|
{"application/javascript","js"},
|
||||||
|
{"image/png","png"},
|
||||||
|
{"text/plain","txt"},
|
||||||
|
{"application/xhtml+xml","xhtml"},
|
||||||
|
{"application/xml","xml"},
|
||||||
|
{"image/svg+xml","svg"},
|
||||||
|
{NULL,NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static pthread_mutex_t server_mux = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t server_mux = PTHREAD_MUTEX_INITIALIZER;
|
||||||
config_t server_config;
|
config_t server_config;
|
||||||
config_t *config()
|
config_t *config()
|
||||||
@ -64,6 +86,8 @@ void destroy_config()
|
|||||||
free(server_config.htdocs);
|
free(server_config.htdocs);
|
||||||
if (server_config.tmpdir)
|
if (server_config.tmpdir)
|
||||||
free(server_config.tmpdir);
|
free(server_config.tmpdir);
|
||||||
|
if(server_config.ssl_cipher)
|
||||||
|
free(server_config.ssl_cipher);
|
||||||
if(server_config.errorfp)
|
if(server_config.errorfp)
|
||||||
{
|
{
|
||||||
fclose(server_config.errorfp);
|
fclose(server_config.errorfp);
|
||||||
@ -74,6 +98,8 @@ void destroy_config()
|
|||||||
fclose(server_config.logfp);
|
fclose(server_config.logfp);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if(server_config.mimes)
|
||||||
|
freedict(server_config.mimes);
|
||||||
LOG("Unclosed connection: %d", server_config.connection);
|
LOG("Unclosed connection: %d", server_config.connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,6 +167,10 @@ static int config_handler(void *conf, const char *section, const char *name,
|
|||||||
{
|
{
|
||||||
pconfig->sslkey = strdup(value);
|
pconfig->sslkey = strdup(value);
|
||||||
}
|
}
|
||||||
|
else if(MATCH("SERVER","ssl.cipher"))
|
||||||
|
{
|
||||||
|
pconfig->ssl_cipher = strdup(value);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (strcmp(section, "RULES") == 0)
|
else if (strcmp(section, "RULES") == 0)
|
||||||
{
|
{
|
||||||
@ -157,6 +187,10 @@ static int config_handler(void *conf, const char *section, const char *name,
|
|||||||
// auto start plugin
|
// auto start plugin
|
||||||
plugin_load((char *)value);
|
plugin_load((char *)value);
|
||||||
}
|
}
|
||||||
|
else if(strcmp(section, "MIMES") == 0)
|
||||||
|
{
|
||||||
|
dput(pconfig->mimes,name,strdup(value));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return 0; /* unknown section/name, error */
|
return 0; /* unknown section/name, error */
|
||||||
@ -193,11 +227,18 @@ void load_config(const char *file)
|
|||||||
server_config.handlers = dict();
|
server_config.handlers = dict();
|
||||||
server_config.maxcon = 1000;
|
server_config.maxcon = 1000;
|
||||||
server_config.connection = 0;
|
server_config.connection = 0;
|
||||||
#ifdef USE_OPENSSL
|
server_config.errorfp = NULL;
|
||||||
|
server_config.logfp = NULL;
|
||||||
|
server_config.mimes = dict();
|
||||||
server_config.usessl = 0;
|
server_config.usessl = 0;
|
||||||
server_config.sslcert = "cert.pem";
|
server_config.sslcert = "cert.pem";
|
||||||
server_config.sslkey = "key.pem";
|
server_config.sslkey = "key.pem";
|
||||||
#endif
|
server_config.ssl_cipher = NULL;
|
||||||
|
// put it default mimes
|
||||||
|
for(int i = 0; _mimes[i].type != NULL; i++)
|
||||||
|
{
|
||||||
|
dput(server_config.mimes,_mimes[i].type, strdup(_mimes[i].ext));
|
||||||
|
}
|
||||||
if (ini_parse(file, config_handler, &server_config) < 0)
|
if (ini_parse(file, config_handler, &server_config) < 0)
|
||||||
{
|
{
|
||||||
ERROR("Can't load '%s'. Used defaut configuration", file);
|
ERROR("Can't load '%s'. Used defaut configuration", file);
|
||||||
@ -209,9 +250,13 @@ void load_config(const char *file)
|
|||||||
LOG("SSL enable %d", server_config.usessl);
|
LOG("SSL enable %d", server_config.usessl);
|
||||||
LOG("SSL cert %s", server_config.sslcert);
|
LOG("SSL cert %s", server_config.sslcert);
|
||||||
LOG("SSL key %s", server_config.sslkey);
|
LOG("SSL key %s", server_config.sslkey);
|
||||||
|
if(!server_config.ssl_cipher)
|
||||||
|
LOG("SSL Cipher suite: %s", "HIGH");
|
||||||
|
else
|
||||||
|
LOG("SSL Cipher suite: %s", server_config.ssl_cipher);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
init_file_system();
|
LOG("%d mimes entries found", server_config.mimes->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *accept_request(void *data)
|
void *accept_request(void *data)
|
||||||
@ -238,7 +283,7 @@ void *accept_request(void *data)
|
|||||||
int sel = select(client->sock + 1, &read_flags, &write_flags, (fd_set *)0, &timeout);
|
int sel = select(client->sock + 1, &read_flags, &write_flags, (fd_set *)0, &timeout);
|
||||||
if (sel == -1)
|
if (sel == -1)
|
||||||
{
|
{
|
||||||
unknow(rq->client);
|
antd_error(rq->client, 400, "Bad request");
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
if (sel == 0 || (!FD_ISSET(client->sock, &read_flags) && !FD_ISSET(client->sock, &write_flags)))
|
if (sel == 0 || (!FD_ISSET(client->sock, &read_flags) && !FD_ISSET(client->sock, &write_flags)))
|
||||||
@ -285,7 +330,7 @@ void *accept_request(void *data)
|
|||||||
ERROR("Error performing SSL handshake %d %d %lu", stat, ret, ERR_get_error());
|
ERROR("Error performing SSL handshake %d %d %lu", stat, ret, ERR_get_error());
|
||||||
//server_config.connection++;
|
//server_config.connection++;
|
||||||
ERR_print_errors_fp(stderr);
|
ERR_print_errors_fp(stderr);
|
||||||
unknow(rq->client);
|
antd_error(rq->client, 400, "Invalid SSL request");
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -320,7 +365,7 @@ void *accept_request(void *data)
|
|||||||
if (!line)
|
if (!line)
|
||||||
{
|
{
|
||||||
LOG("No method found");
|
LOG("No method found");
|
||||||
unknow(rq->client);
|
antd_error(rq->client, 405, "No method found");
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
trim(token, ' ');
|
trim(token, ' ');
|
||||||
@ -331,7 +376,7 @@ void *accept_request(void *data)
|
|||||||
if (!line)
|
if (!line)
|
||||||
{
|
{
|
||||||
LOG("No request found");
|
LOG("No request found");
|
||||||
unknow(rq->client);
|
antd_error(rq->client, 400, "Bad request");
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
trim(token, ' ');
|
trim(token, ' ');
|
||||||
@ -388,7 +433,7 @@ void *resolve_request(void *data)
|
|||||||
strcat(path, "/index.html");
|
strcat(path, "/index.html");
|
||||||
if (stat(path, &st) == -1)
|
if (stat(path, &st) == -1)
|
||||||
{
|
{
|
||||||
association it;
|
chain_t it;
|
||||||
for_each_assoc(it, server_config.handlers)
|
for_each_assoc(it, server_config.handlers)
|
||||||
{
|
{
|
||||||
newurl = __s("%s/index.%s", url, it->key);
|
newurl = __s("%s/index.%s", url, it->key);
|
||||||
@ -408,7 +453,7 @@ void *resolve_request(void *data)
|
|||||||
}
|
}
|
||||||
if (!newurl)
|
if (!newurl)
|
||||||
{
|
{
|
||||||
notfound(rq->client);
|
antd_error(rq->client, 404, "Resource Not Found");
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
//if(url) free(url); this is freed in the dput function
|
//if(url) free(url); this is freed in the dput function
|
||||||
@ -439,7 +484,7 @@ void *resolve_request(void *data)
|
|||||||
return execute_plugin(rq, h);
|
return execute_plugin(rq, h);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
unknow(rq->client);
|
antd_error(rq->client, 403, "Access forbidden");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -553,15 +598,21 @@ void *serve_file(void *data)
|
|||||||
int s = stat(path, &st);
|
int s = stat(path, &st);
|
||||||
if(s == -1)
|
if(s == -1)
|
||||||
{
|
{
|
||||||
notfound(rq->client);
|
antd_error(rq->client, 404, "File not found");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int size = (int)st.st_size;
|
int size = (int)st.st_size;
|
||||||
set_status(rq->client,200,"OK");
|
char ibuf[20];
|
||||||
__t(rq->client,"Content-Type: %s",mime_type);
|
snprintf (ibuf, sizeof(ibuf), "%d",size);
|
||||||
__t(rq->client,"Content-Length: %d",size);
|
antd_response_header_t rhd;
|
||||||
response(rq->client,"");
|
rhd.cookie = NULL;
|
||||||
|
rhd.status = 200;
|
||||||
|
rhd.header = dict();
|
||||||
|
dput(rhd.header, "Content-Type", strdup(mime_type));
|
||||||
|
dput(rhd.header, "Content-Length", strdup(ibuf));
|
||||||
|
antd_send_header(rq->client, &rhd);
|
||||||
|
|
||||||
__f(rq->client, path);
|
__f(rq->client, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -637,15 +688,15 @@ char *apply_rules(const char *host, char *url)
|
|||||||
void *decode_request_header(void *data)
|
void *decode_request_header(void *data)
|
||||||
{
|
{
|
||||||
antd_request_t *rq = (antd_request_t *)data;
|
antd_request_t *rq = (antd_request_t *)data;
|
||||||
dictionary cookie = NULL;
|
dictionary_t cookie = NULL;
|
||||||
char *line;
|
char *line;
|
||||||
char *token;
|
char *token;
|
||||||
char *query = NULL;
|
char *query = NULL;
|
||||||
char *host = NULL;
|
char *host = NULL;
|
||||||
char buf[2 * BUFFLEN];
|
char buf[2 * BUFFLEN];
|
||||||
char *url = (char *)dvalue(rq->request, "REQUEST_QUERY");
|
char *url = (char *)dvalue(rq->request, "REQUEST_QUERY");
|
||||||
dictionary xheader = dict();
|
dictionary_t xheader = dict();
|
||||||
dictionary request = dict();
|
dictionary_t request = dict();
|
||||||
dput(rq->request, "REQUEST_HEADER", xheader);
|
dput(rq->request, "REQUEST_HEADER", xheader);
|
||||||
dput(rq->request, "REQUEST_DATA", request);
|
dput(rq->request, "REQUEST_DATA", request);
|
||||||
// first real all header
|
// first real all header
|
||||||
@ -700,7 +751,7 @@ void *decode_request_header(void *data)
|
|||||||
void *decode_request(void *data)
|
void *decode_request(void *data)
|
||||||
{
|
{
|
||||||
antd_request_t *rq = (antd_request_t *)data;
|
antd_request_t *rq = (antd_request_t *)data;
|
||||||
dictionary headers = dvalue(rq->request, "REQUEST_HEADER");
|
dictionary_t headers = dvalue(rq->request, "REQUEST_HEADER");
|
||||||
int ws = 0;
|
int ws = 0;
|
||||||
char *ws_key = NULL;
|
char *ws_key = NULL;
|
||||||
char *method = NULL;
|
char *method = NULL;
|
||||||
@ -736,7 +787,7 @@ void *decode_request(void *data)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unimplemented(rq->client);
|
antd_error(rq->client,501, "Request Method Not Implemented");
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -744,8 +795,8 @@ void *decode_request(void *data)
|
|||||||
void *decode_post_request(void *data)
|
void *decode_post_request(void *data)
|
||||||
{
|
{
|
||||||
antd_request_t *rq = (antd_request_t *)data;
|
antd_request_t *rq = (antd_request_t *)data;
|
||||||
dictionary request = dvalue(rq->request, "REQUEST_DATA");
|
dictionary_t request = dvalue(rq->request, "REQUEST_DATA");
|
||||||
dictionary headers = dvalue(rq->request, "REQUEST_HEADER");
|
dictionary_t headers = dvalue(rq->request, "REQUEST_HEADER");
|
||||||
char *ctype = NULL;
|
char *ctype = NULL;
|
||||||
int clen = -1;
|
int clen = -1;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
@ -762,8 +813,7 @@ void *decode_post_request(void *data)
|
|||||||
return task;
|
return task;
|
||||||
if (ctype == NULL || clen == -1)
|
if (ctype == NULL || clen == -1)
|
||||||
{
|
{
|
||||||
LOG("Bad request");
|
antd_error(rq->client, 400, "Bad Request, missing content description");
|
||||||
badrequest(rq->client);
|
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
// decide what to do with the data
|
// decide what to do with the data
|
||||||
@ -787,9 +837,12 @@ void *decode_post_request(void *data)
|
|||||||
key++;
|
key++;
|
||||||
else
|
else
|
||||||
key = ctype;
|
key = ctype;
|
||||||
|
if(pquery)
|
||||||
|
{
|
||||||
dput(request, key, strdup(pquery));
|
dput(request, key, strdup(pquery));
|
||||||
free(pquery);
|
free(pquery);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -837,7 +890,7 @@ void ws_confirm_request(void *client, const char *key)
|
|||||||
* @param client The client socket
|
* @param client The client socket
|
||||||
* @return The Dictionary socket or NULL
|
* @return The Dictionary socket or NULL
|
||||||
*/
|
*/
|
||||||
dictionary decode_cookie(const char *line)
|
dictionary_t decode_cookie(const char *line)
|
||||||
{
|
{
|
||||||
char *token, *token1;
|
char *token, *token1;
|
||||||
char *cpstr = strdup(line);
|
char *cpstr = strdup(line);
|
||||||
@ -846,7 +899,7 @@ dictionary decode_cookie(const char *line)
|
|||||||
trim(cpstr, '\n');
|
trim(cpstr, '\n');
|
||||||
trim(cpstr, '\r');
|
trim(cpstr, '\r');
|
||||||
|
|
||||||
dictionary dic = NULL;
|
dictionary_t dic = NULL;
|
||||||
while ((token = strsep(&cpstr, ";")))
|
while ((token = strsep(&cpstr, ";")))
|
||||||
{
|
{
|
||||||
trim(token, ' ');
|
trim(token, ' ');
|
||||||
@ -915,7 +968,7 @@ void *decode_multi_part_request_data(void *data)
|
|||||||
antd_task_t *task = antd_create_task(NULL, (void *)rq, NULL, rq->client->last_io);
|
antd_task_t *task = antd_create_task(NULL, (void *)rq, NULL, rq->client->last_io);
|
||||||
task->priority++;
|
task->priority++;
|
||||||
char *boundary = (char *)dvalue(rq->request, "MULTI_PART_BOUNDARY");
|
char *boundary = (char *)dvalue(rq->request, "MULTI_PART_BOUNDARY");
|
||||||
dictionary dic = (dictionary)dvalue(rq->request, "REQUEST_DATA");
|
dictionary_t dic = (dictionary_t)dvalue(rq->request, "REQUEST_DATA");
|
||||||
char *boundend = __s("%s--", boundary);
|
char *boundend = __s("%s--", boundary);
|
||||||
// search for content disposition:
|
// search for content disposition:
|
||||||
while ((line = read_line(rq->client)) &&
|
while ((line = read_line(rq->client)) &&
|
||||||
@ -1063,7 +1116,7 @@ void *decode_multi_part_request_data(void *data)
|
|||||||
* @param query : the query string
|
* @param query : the query string
|
||||||
* @return a dictionary of key-value
|
* @return a dictionary of key-value
|
||||||
*/
|
*/
|
||||||
void decode_url_request(const char *query, dictionary dic)
|
void decode_url_request(const char *query, dictionary_t dic)
|
||||||
{
|
{
|
||||||
if (query == NULL)
|
if (query == NULL)
|
||||||
return;
|
return;
|
||||||
@ -1156,7 +1209,7 @@ void *execute_plugin(void *data, const char *pname)
|
|||||||
pthread_mutex_unlock(&server_mux);
|
pthread_mutex_unlock(&server_mux);
|
||||||
if (plugin == NULL)
|
if (plugin == NULL)
|
||||||
{
|
{
|
||||||
unknow(rq->client);
|
antd_error(rq->client, 503, "Requested service not found");
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1171,7 +1224,7 @@ void *execute_plugin(void *data, const char *pname)
|
|||||||
if ((error = dlerror()) != NULL)
|
if ((error = dlerror()) != NULL)
|
||||||
{
|
{
|
||||||
ERROR("Problem when finding %s method from %s : %s", PLUGIN_HANDLER, pname, error);
|
ERROR("Problem when finding %s method from %s : %s", PLUGIN_HANDLER, pname, error);
|
||||||
unknow(rq->client);
|
antd_error(rq->client, 503, "Requested service not found");
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
// check if we need the raw data or not
|
// check if we need the raw data or not
|
||||||
@ -1195,3 +1248,8 @@ int usessl()
|
|||||||
return server_config.usessl;
|
return server_config.usessl;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
dictionary_t mimes_list()
|
||||||
|
{
|
||||||
|
return server_config.mimes;
|
||||||
|
}
|
@ -35,14 +35,14 @@ void badrequest(void*);
|
|||||||
int rule_check(const char*, const char*, const char* , const char* , const char* , char*);
|
int rule_check(const char*, const char*, const char* , const char* , const char* , char*);
|
||||||
void ws_confirm_request(void*, const char*);
|
void ws_confirm_request(void*, const char*);
|
||||||
char* post_url_decode(void* client,int len);
|
char* post_url_decode(void* client,int len);
|
||||||
void decode_url_request(const char* query, dictionary);
|
void decode_url_request(const char* query, dictionary_t);
|
||||||
void* decode_request_header(void* data);
|
void* decode_request_header(void* data);
|
||||||
void* decode_request(void* data);
|
void* decode_request(void* data);
|
||||||
void* decode_post_request(void* data);
|
void* decode_post_request(void* data);
|
||||||
void* resolve_request(void* data);
|
void* resolve_request(void* data);
|
||||||
void* decode_multi_part_request(void*,const char*);
|
void* decode_multi_part_request(void*,const char*);
|
||||||
void* decode_multi_part_request_data(void* data);
|
void* decode_multi_part_request_data(void* data);
|
||||||
dictionary decode_cookie(const char*);
|
dictionary_t decode_cookie(const char*);
|
||||||
char* post_data_decode(void*,int);
|
char* post_data_decode(void*,int);
|
||||||
void set_nonblock(int);
|
void set_nonblock(int);
|
||||||
void* execute_plugin(void* data, const char *path);
|
void* execute_plugin(void* data, const char *path);
|
||||||
|
4
httpd.c
4
httpd.c
@ -10,8 +10,8 @@ static int server_sock = -1;
|
|||||||
|
|
||||||
// define the cipher suit used
|
// define the cipher suit used
|
||||||
// dirty hack, this should be configured by the configuration file
|
// dirty hack, this should be configured by the configuration file
|
||||||
#define CIPHER_SUIT "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"
|
// #define CIPHER_SUIT "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"
|
||||||
|
#define CIPHER_SUIT "HIGH"
|
||||||
|
|
||||||
static int ssl_session_ctx_id = 1;
|
static int ssl_session_ctx_id = 1;
|
||||||
SSL_CTX *ctx;
|
SSL_CTX *ctx;
|
||||||
|
@ -22,19 +22,33 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#include "dictionary.h"
|
#include "dictionary.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
dictionary dict()
|
dictionary_t dict()
|
||||||
{
|
{
|
||||||
dictionary d = (dictionary)malloc(DHASHSIZE*sizeof(association));
|
return dict_n(DHASHSIZE);
|
||||||
for(int i=0; i< DHASHSIZE;i++)
|
}
|
||||||
d[i] = NULL;
|
dictionary_t dict_n(unsigned int size)
|
||||||
|
{
|
||||||
|
dictionary_t d = (dictionary_t) malloc(sizeof(struct __dict));
|
||||||
|
if(!d) return NULL;
|
||||||
|
d->map= (map_t)malloc(size*sizeof(chain_t));
|
||||||
|
if(!d->map)
|
||||||
|
{
|
||||||
|
free(d);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
d->cap = size;
|
||||||
|
d->size = 0;
|
||||||
|
for(unsigned int i=0; i< size;i++)
|
||||||
|
d->map[i] = NULL;
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
association dlookup(dictionary dic,const char* key)
|
chain_t dlookup(dictionary_t dic,const char* key)
|
||||||
{
|
{
|
||||||
association np;
|
chain_t np;
|
||||||
if(dic == NULL) return NULL;
|
if(dic->map == NULL) return NULL;
|
||||||
for (np = dic[hash(key,DHASHSIZE)]; np != NULL; np = np->next)
|
for (np = dic->map[hash(key,dic->cap)]; np != NULL; np = np->next)
|
||||||
{
|
{
|
||||||
if(!np || !np->key)
|
if(!np || !np->key)
|
||||||
{
|
{
|
||||||
@ -45,26 +59,27 @@ association dlookup(dictionary dic,const char* key)
|
|||||||
}
|
}
|
||||||
return NULL; /* not found */
|
return NULL; /* not found */
|
||||||
}
|
}
|
||||||
association __put_el_with_key(dictionary dic, const char* key)
|
chain_t __put_el_with_key(dictionary_t dic, const char* key)
|
||||||
{
|
{
|
||||||
association np;
|
chain_t np;
|
||||||
unsigned hashval;
|
unsigned hashval;
|
||||||
if(dic == NULL) return NULL;
|
if(dic->map == NULL) return NULL;
|
||||||
if ((np = dlookup(dic,key)) == NULL) { /* not found */
|
if ((np = dlookup(dic,key)) == NULL) { /* not found */
|
||||||
np = (association) malloc(sizeof(*np));
|
np = (chain_t) malloc(sizeof(*np));
|
||||||
np->value = NULL;
|
|
||||||
if (np == NULL || (np->key = strdup(key)) == NULL)
|
if (np == NULL || (np->key = strdup(key)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
hashval = hash(key, DHASHSIZE);
|
np->value = NULL;
|
||||||
np->next = dic[hashval];
|
hashval = hash(key, dic->cap);
|
||||||
dic[hashval] = np;
|
np->next = dic->map[hashval];
|
||||||
|
dic->map[hashval] = np;
|
||||||
|
dic->size++;
|
||||||
}
|
}
|
||||||
// found
|
// found
|
||||||
return np;
|
return np;
|
||||||
}
|
}
|
||||||
association dput(dictionary dic,const char* key, void* value)
|
chain_t dput(dictionary_t dic,const char* key, void* value)
|
||||||
{
|
{
|
||||||
association np = __put_el_with_key(dic,key);
|
chain_t np = __put_el_with_key(dic,key);
|
||||||
if(np == NULL)
|
if(np == NULL)
|
||||||
{
|
{
|
||||||
if(value) free(value);
|
if(value) free(value);
|
||||||
@ -74,38 +89,43 @@ association dput(dictionary dic,const char* key, void* value)
|
|||||||
np->value = value;
|
np->value = value;
|
||||||
return np;
|
return np;
|
||||||
}
|
}
|
||||||
int dremove(dictionary dic, const char* key)
|
chain_t dremove(dictionary_t dic, const char* key)
|
||||||
{
|
{
|
||||||
if(dic == NULL) return 0;
|
if(dic->map == NULL) return 0;
|
||||||
int hashval = hash(key, DHASHSIZE);
|
int hashval = hash(key, dic->cap);
|
||||||
association np = dic[hashval];
|
chain_t np = dic->map[hashval];
|
||||||
if(np!=NULL && strcmp(key,np->key)==0)
|
if(np!=NULL && strcmp(key,np->key)==0)
|
||||||
{
|
{
|
||||||
dic[hashval] = np->next;
|
dic->size--;
|
||||||
return 1;
|
dic->map[hashval] = np->next;
|
||||||
|
np->next = NULL;
|
||||||
|
return np;
|
||||||
}
|
}
|
||||||
for (np= dic[hashval]; np != NULL; np = np->next)
|
for (np= dic->map[hashval]; np != NULL; np = np->next)
|
||||||
if (np->next!=NULL&&strcmp(key, np->next->key) == 0)
|
if (np->next!=NULL&&strcmp(key, np->next->key) == 0)
|
||||||
{
|
{
|
||||||
|
chain_t ret = np->next;
|
||||||
np->next = np->next->next; /* found */
|
np->next = np->next->next; /* found */
|
||||||
return 1;
|
dic->size--;
|
||||||
|
ret->next = NULL;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
return 0; /* not found */
|
return NULL; /* not found */
|
||||||
|
|
||||||
}
|
}
|
||||||
void* dvalue(dictionary dic, const char* key)
|
void* dvalue(dictionary_t dic, const char* key)
|
||||||
{
|
{
|
||||||
association as = dlookup(dic,key);
|
chain_t as = dlookup(dic,key);
|
||||||
if(as == NULL) return NULL;
|
if(as == NULL) return NULL;
|
||||||
return as->value;
|
return as->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_association(association * asoc)
|
void free_association(chain_t * asoc)
|
||||||
{
|
{
|
||||||
|
|
||||||
while( (*asoc) != NULL )
|
while( (*asoc) != NULL )
|
||||||
{
|
{
|
||||||
association a = *asoc;
|
chain_t a = *asoc;
|
||||||
(* asoc) = (*asoc) ->next;
|
(* asoc) = (*asoc) ->next;
|
||||||
|
|
||||||
if(a->key)
|
if(a->key)
|
||||||
@ -118,11 +138,11 @@ void free_association(association * asoc)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void freedict(dictionary dic){
|
void freedict(dictionary_t dic){
|
||||||
for(int i = 0; i < DHASHSIZE; i++)
|
for(unsigned int i = 0; i < dic->cap; i++)
|
||||||
free_association(&(dic[i]));
|
free_association(&(dic->map[i]));
|
||||||
|
free(dic->map);
|
||||||
free(dic);
|
free(dic);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,10 +24,10 @@ THE SOFTWARE.
|
|||||||
#ifndef DICTIONARY_H
|
#ifndef DICTIONARY_H
|
||||||
#define DICTIONARY_H
|
#define DICTIONARY_H
|
||||||
|
|
||||||
#include "utils.h"
|
#define DHASHSIZE 16
|
||||||
#define for_each_assoc(assoc, dic) \
|
#define for_each_assoc(assoc, dic) \
|
||||||
for(int i = 0; i < DHASHSIZE; i++) \
|
for(unsigned int i = 0; i < dic->cap; i++) \
|
||||||
for(assoc = dic[i];assoc!= NULL; assoc = assoc->next)
|
for(assoc = dic->map[i];assoc!= NULL; assoc = assoc->next)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dictionary for header
|
* Dictionary for header
|
||||||
@ -37,14 +37,22 @@ typedef struct __assoc{
|
|||||||
char *key;
|
char *key;
|
||||||
void* value;
|
void* value;
|
||||||
//char *value;
|
//char *value;
|
||||||
} * association;
|
} * chain_t;
|
||||||
|
|
||||||
typedef association* dictionary;
|
typedef chain_t* map_t;
|
||||||
dictionary dict();
|
|
||||||
association dlookup(dictionary,const char*);
|
typedef struct __dict{
|
||||||
void* dvalue(dictionary, const char*);
|
unsigned int cap;
|
||||||
association dput(dictionary,const char*, void*);
|
map_t map;
|
||||||
int dremove(dictionary, const char*);
|
unsigned int size;
|
||||||
void freedict(dictionary);
|
}* dictionary_t;
|
||||||
|
|
||||||
|
dictionary_t dict();
|
||||||
|
dictionary_t dict_n(unsigned int n);
|
||||||
|
chain_t dlookup(dictionary_t,const char*);
|
||||||
|
void* dvalue(dictionary_t, const char*);
|
||||||
|
chain_t dput(dictionary_t,const char*, void*);
|
||||||
|
chain_t dremove(dictionary_t, const char*);
|
||||||
|
void freedict(dictionary_t);
|
||||||
|
|
||||||
#endif
|
#endif
|
328
lib/handle.c
328
lib/handle.c
@ -1,4 +1,5 @@
|
|||||||
#include "handle.h"
|
#include "handle.h"
|
||||||
|
#define HTML_TPL "<HTML><HEAD><TITLE>%s</TITLE></HEAD><BODY><h2>%s</h2></BODY></HTML>"
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
int usessl()
|
int usessl()
|
||||||
{
|
{
|
||||||
@ -18,36 +19,110 @@ void server_log(const char* fmt, ...)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void set_status(void* client,int code,const char* msg)
|
|
||||||
|
const char* get_status_str(int stat)
|
||||||
{
|
{
|
||||||
char *s = __s("HTTP/1.1 %d %s", code, msg);
|
switch(stat)
|
||||||
response(client, s);
|
{
|
||||||
free(s);
|
case 100: return "Continue";
|
||||||
s = __s("Server: %s ", SERVER_NAME);
|
case 101: return "Switching Protocols";
|
||||||
response(client, s);
|
case 102: return "Processing";
|
||||||
free(s);
|
case 103: return "Early Hints";
|
||||||
}
|
|
||||||
void redirect(void* client,const char*path)
|
case 200: return "OK";
|
||||||
{
|
case 201: return "Created";
|
||||||
__t(client,"<html><head><meta http-equiv=\"refresh\" content=\"0; url=%s\"></head><body></body></html>",path);
|
case 202: return "Accepted";
|
||||||
|
case 203: return "Non-Authoritative Information";
|
||||||
|
case 204: return "No Content";
|
||||||
|
case 205: return "Reset Content";
|
||||||
|
case 206: return "Partial Content";
|
||||||
|
case 207: return "Multi-Status";
|
||||||
|
case 208: return "Already Reported";
|
||||||
|
case 226: return "IM Used";
|
||||||
|
|
||||||
|
case 300: return "Multiple Choices";
|
||||||
|
case 301: return "Moved Permanently";
|
||||||
|
case 302: return "Found";
|
||||||
|
case 303: return "See Other";
|
||||||
|
case 304: return "Not Modified";
|
||||||
|
case 305: return "Use Proxy";
|
||||||
|
case 306: return "Switch Proxy";
|
||||||
|
case 307: return "Temporary Redirect";
|
||||||
|
case 308: return "Permanent Redirect";
|
||||||
|
|
||||||
|
case 400: return "Bad Request";
|
||||||
|
case 401: return "Unauthorized";
|
||||||
|
case 402: return "Payment Required";
|
||||||
|
case 403: return "Forbidden";
|
||||||
|
case 404: return "Not Found";
|
||||||
|
case 405: return "Method Not Allowed";
|
||||||
|
case 406: return "Not Acceptable";
|
||||||
|
case 407: return "Proxy Authentication Required";
|
||||||
|
case 408: return "Request Timeout";
|
||||||
|
case 409: return "Conflict";
|
||||||
|
case 410: return "Gone";
|
||||||
|
case 411: return "Length Required";
|
||||||
|
case 412: return "Precondition Failed";
|
||||||
|
case 413: return "Payload Too Large";
|
||||||
|
case 414: return "URI Too Long";
|
||||||
|
case 415: return "Unsupported Media Type";
|
||||||
|
case 416: return "Range Not Satisfiable";
|
||||||
|
case 417: return "Expectation Failed";
|
||||||
|
case 421: return "Misdirected Request";
|
||||||
|
case 422: return "Unprocessable Entity";
|
||||||
|
case 423: return "Locked";
|
||||||
|
case 424: return "Failed Dependency";
|
||||||
|
case 425: return "Too Early";
|
||||||
|
case 426: return "Upgrade Required";
|
||||||
|
case 428: return "Precondition Required";
|
||||||
|
case 429: return "Too Many Requests";
|
||||||
|
case 431: return "Request Header Fields Too Large";
|
||||||
|
case 451: return "Unavailable For Legal Reasons";
|
||||||
|
|
||||||
|
case 500: return "Internal Server Error";
|
||||||
|
case 501: return "Not Implemented";
|
||||||
|
case 502: return "Bad Gateway";
|
||||||
|
case 503: return "Service Unavailable";
|
||||||
|
case 504: return "Gateway Timeout";
|
||||||
|
case 505: return "HTTP Version Not Supported";
|
||||||
|
case 506: return "Variant Also Negotiates";
|
||||||
|
case 507: return "Insufficient Storage";
|
||||||
|
case 508: return "Loop Detected";
|
||||||
|
case 510: return "Not Extended";
|
||||||
|
case 511: return "Network Authentication Required";
|
||||||
|
default: return "Unofficial Status";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void html(void* client)
|
void antd_send_header(void* client, antd_response_header_t* res)
|
||||||
{
|
{
|
||||||
ctype(client,"text/html; charset=utf-8");
|
if(!res->header)
|
||||||
}
|
res->header = dict();
|
||||||
void text(void* client)
|
dput(res->header,"Server", strdup(SERVER_NAME));
|
||||||
{
|
const char* stat_str = get_status_str(res->status);
|
||||||
ctype(client,"text/plain; charset=utf-8");
|
__t(client, "HTTP/1.1 %d %s", res->status, stat_str);
|
||||||
}
|
chain_t it;
|
||||||
void json(void* client)
|
for_each_assoc(it, res->header)
|
||||||
{
|
{
|
||||||
ctype(client,"application/json");
|
__t(client,"%s: %s", it->key, (const char*)it->value);
|
||||||
}
|
}
|
||||||
void textstream(void* client)
|
// send out cookie
|
||||||
{
|
if(res->cookie)
|
||||||
ctype(client, "text/event-stream");
|
{
|
||||||
|
int size = list_size(res->cookie);
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
__t(client,"Set-Cookie: %s", list_at(res->cookie, i)->value.s);
|
||||||
|
}
|
||||||
|
list_free(&res->cookie);
|
||||||
|
res->cookie = NULL;
|
||||||
|
}
|
||||||
|
__b(client, (unsigned char*)"\r\n", 2);
|
||||||
|
freedict(res->header);
|
||||||
|
res->header = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void octstream(void* client, char* name)
|
void octstream(void* client, char* name)
|
||||||
{
|
{
|
||||||
set_status(client,200,"OK");
|
set_status(client,200,"OK");
|
||||||
@ -55,38 +130,15 @@ void octstream(void* client, char* name)
|
|||||||
__t(client,"Content-Disposition: attachment; filename=\"%s\"", name);
|
__t(client,"Content-Disposition: attachment; filename=\"%s\"", name);
|
||||||
response(client,"");
|
response(client,"");
|
||||||
//Content-Disposition: attachment; filename="fname.ext"
|
//Content-Disposition: attachment; filename="fname.ext"
|
||||||
}
|
}*/
|
||||||
void jpeg(void* client)
|
|
||||||
{
|
|
||||||
ctype(client,"image/jpeg");
|
|
||||||
}
|
|
||||||
void ctype(void* client, const char* type)
|
|
||||||
{
|
|
||||||
set_status(client,200,"OK");
|
|
||||||
__t(client,"Content-Type: %s",type);
|
|
||||||
response(client,"");
|
|
||||||
}
|
|
||||||
|
|
||||||
int response(void* client, const char* data)
|
|
||||||
{
|
|
||||||
char buf[BUFFLEN+3];
|
|
||||||
strcpy(buf, data);
|
|
||||||
int nbytes;
|
|
||||||
int size = strlen(data);
|
|
||||||
buf[size] = '\r';
|
|
||||||
buf[size+1] = '\n';
|
|
||||||
buf[size+2] = '\0';
|
|
||||||
|
|
||||||
nbytes = antd_send(client, buf, strlen(buf));
|
|
||||||
return (nbytes ==-1?0:1);
|
|
||||||
}
|
|
||||||
int antd_send(void *src, const void* data, int len)
|
int antd_send(void *src, const void* data, int len)
|
||||||
{
|
{
|
||||||
if(!src || !data) return -1;
|
if(!src || !data) return -1;
|
||||||
int written;
|
int written;
|
||||||
antd_client_t * source = (antd_client_t *) src;
|
antd_client_t * source = (antd_client_t *) src;
|
||||||
char* ptr;
|
char* ptr;
|
||||||
int writelen;
|
int writelen = 0;
|
||||||
int count;
|
int count;
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
if(usessl())
|
if(usessl())
|
||||||
@ -200,7 +252,9 @@ int antd_send(void *src, const void* data, int len)
|
|||||||
}
|
}
|
||||||
else if(count == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
|
else if(count == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
|
||||||
{
|
{
|
||||||
return written;
|
ERROR("Error while writing: %s", strerror(errno));
|
||||||
|
break;
|
||||||
|
//return written;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
@ -351,6 +405,7 @@ int antd_recv(void *src, void* data, int len)
|
|||||||
}
|
}
|
||||||
else if(errno != EAGAIN && errno != EWOULDBLOCK)
|
else if(errno != EAGAIN && errno != EWOULDBLOCK)
|
||||||
{
|
{
|
||||||
|
ERROR("Error while writing: %s", strerror(errno));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -408,66 +463,27 @@ int antd_close(void* src)
|
|||||||
src = NULL;
|
src = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
int __ti(void* client,int data)
|
|
||||||
{
|
|
||||||
char str[15];
|
|
||||||
sprintf(str, "%d", data);
|
|
||||||
return response(client,str);
|
|
||||||
}
|
|
||||||
|
|
||||||
int __t(void* client, const char* fstring,...)
|
int __t(void* client, const char* fstring,...)
|
||||||
{
|
{
|
||||||
int nbytes;
|
|
||||||
int dlen;
|
int dlen;
|
||||||
int sent = 0;
|
int st;
|
||||||
int buflen = 0;
|
|
||||||
va_list arguments;
|
va_list arguments;
|
||||||
char * data;
|
char * data;
|
||||||
char* chunk;
|
|
||||||
va_start( arguments, fstring);
|
va_start( arguments, fstring);
|
||||||
dlen = vsnprintf(0,0,fstring,arguments) + 1;
|
dlen = vsnprintf(0,0,fstring,arguments)+1;
|
||||||
va_end(arguments);
|
va_end(arguments);
|
||||||
if ((data = (char*)malloc(dlen*sizeof(char))) != 0)
|
if ((data = (char*)malloc(dlen*sizeof(char))) != 0)
|
||||||
{
|
{
|
||||||
va_start(arguments, fstring);
|
va_start(arguments, fstring);
|
||||||
vsnprintf(data, dlen, fstring, arguments);
|
vsnprintf(data, dlen, fstring, arguments);
|
||||||
va_end(arguments);
|
va_end(arguments);
|
||||||
|
st = __b(client, (const unsigned char*)data, strlen(data));
|
||||||
if(dlen < BUFFLEN)
|
__b(client, (unsigned char*)"\r\n", 2);
|
||||||
{
|
|
||||||
int ret = response(client,data);
|
|
||||||
free(data);
|
free(data);
|
||||||
return ret;
|
return st;
|
||||||
}
|
}
|
||||||
else
|
return 0;
|
||||||
{
|
|
||||||
while(sent < dlen - 1)
|
|
||||||
{
|
|
||||||
if(dlen - sent > BUFFLEN)
|
|
||||||
buflen = BUFFLEN;
|
|
||||||
else
|
|
||||||
buflen = dlen - sent - 1;
|
|
||||||
//LOG("BUFFLEN %d\n",buflen);
|
|
||||||
chunk = (char*) malloc((buflen)*sizeof(char));
|
|
||||||
memcpy(chunk,data+sent,buflen);
|
|
||||||
//chunk[buflen-1] = '\0';
|
|
||||||
//response(client,chunk);
|
|
||||||
sent += buflen;
|
|
||||||
nbytes = antd_send(client, chunk, buflen);
|
|
||||||
free(chunk);
|
|
||||||
if(nbytes == -1)
|
|
||||||
{
|
|
||||||
//free(data);
|
|
||||||
//return 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
chunk = "\r\n";
|
|
||||||
antd_send(client, chunk, strlen(chunk));
|
|
||||||
}
|
|
||||||
free(data);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
int __b(void* client, const unsigned char* data, int size)
|
int __b(void* client, const unsigned char* data, int size)
|
||||||
@ -475,15 +491,15 @@ int __b(void* client, const unsigned char* data, int size)
|
|||||||
char buf[BUFFLEN];
|
char buf[BUFFLEN];
|
||||||
int sent = 0;
|
int sent = 0;
|
||||||
int buflen = 0;
|
int buflen = 0;
|
||||||
int nbytes;
|
int nbytes = 0;
|
||||||
|
|
||||||
if(size <= BUFFLEN)
|
/*if(size <= BUFFLEN)
|
||||||
{
|
{
|
||||||
nbytes = antd_send(client,data,size);
|
nbytes = antd_send(client,data,size);
|
||||||
return (nbytes==-1?0:1);
|
return (nbytes==-1?0:1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{*/
|
||||||
while(sent < size)
|
while(sent < size)
|
||||||
{
|
{
|
||||||
if(size - sent > BUFFLEN)
|
if(size - sent > BUFFLEN)
|
||||||
@ -492,10 +508,13 @@ int __b(void* client, const unsigned char* data, int size)
|
|||||||
buflen = size - sent;
|
buflen = size - sent;
|
||||||
memcpy(buf,data+sent,buflen);
|
memcpy(buf,data+sent,buflen);
|
||||||
nbytes = antd_send(client,buf,buflen);
|
nbytes = antd_send(client,buf,buflen);
|
||||||
sent += buflen;
|
if(nbytes == -1)
|
||||||
if(nbytes == -1) return 0;
|
{
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
sent += nbytes;
|
||||||
}
|
}
|
||||||
|
//}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int __f(void* client, const char* file)
|
int __f(void* client, const char* file)
|
||||||
@ -517,95 +536,64 @@ int __f(void* client, const char* file)
|
|||||||
fclose(ptr);
|
fclose(ptr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
int __f(void* client, const char* file)
|
|
||||||
{
|
|
||||||
char buf[BUFFLEN];
|
|
||||||
FILE *ptr;
|
|
||||||
int nbytes;
|
|
||||||
ptr = fopen(file,"r");
|
|
||||||
if(!ptr)
|
|
||||||
{
|
|
||||||
LOG("Cannot read : %s\n", file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
memset(buf,0, sizeof(buf));
|
|
||||||
while(fgets(buf, sizeof(buf) - 1, ptr) != NULL)
|
|
||||||
{
|
|
||||||
nbytes = antd_send(client, buf, strlen(buf));
|
|
||||||
if(nbytes == -1) return 0;
|
|
||||||
memset(buf,0, sizeof(buf));
|
|
||||||
//LOG("READ : %s\n", buf);
|
|
||||||
//fgets(buf, sizeof(buf), ptr);
|
|
||||||
}
|
|
||||||
fclose(ptr);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
int upload(const char* tmp, const char* path)
|
int upload(const char* tmp, const char* path)
|
||||||
{
|
{
|
||||||
return !rename(tmp, path);
|
return !rename(tmp, path);
|
||||||
}
|
}
|
||||||
// __plugin__.name
|
|
||||||
void set_cookie(void* client,const char* type, dictionary dic, const char* name)
|
/*
|
||||||
|
void set_cookie(void* client,const char* type, dictionary_t dic, const char* name)
|
||||||
{
|
{
|
||||||
set_status(client,200,"OK");
|
set_status(client,200,"OK");
|
||||||
__t(client,"Content-Type: %s",type);
|
__t(client,"Content-Type: %s",type);
|
||||||
association assoc;
|
chain_t assoc;
|
||||||
for_each_assoc(assoc,dic){
|
for_each_assoc(assoc,dic){
|
||||||
__t(client,"Set-Cookie: %s=%s; Path=/%s",assoc->key, (char*)assoc->value, name);
|
__t(client,"Set-Cookie: %s=%s; Path=/%s",assoc->key, (char*)assoc->value, name);
|
||||||
}
|
}
|
||||||
response(client,"");
|
response(client,"");
|
||||||
}
|
}
|
||||||
void clear_cookie(void* client, dictionary dic)
|
void clear_cookie(void* client, dictionary_t dic)
|
||||||
{
|
{
|
||||||
set_status(client,200,"OK");
|
set_status(client,200,"OK");
|
||||||
__t(client,"Content-Type: text/html; charset=utf-8");
|
__t(client,"Content-Type: text/html; charset=utf-8");
|
||||||
association assoc;
|
chain_t assoc;
|
||||||
for_each_assoc(assoc,dic){
|
for_each_assoc(assoc,dic){
|
||||||
__t(client,"Set-Cookie: %s=%s;expires=",assoc->key, (char*)assoc->value, server_time());
|
__t(client,"Set-Cookie: %s=%s;expires=%s",assoc->key, (char*)assoc->value, server_time());
|
||||||
}
|
}
|
||||||
response(client,"");
|
response(client,"");
|
||||||
}
|
}
|
||||||
void unknow(void* client)
|
*/
|
||||||
|
|
||||||
|
void antd_error(void* client, int status, const char* msg)
|
||||||
{
|
{
|
||||||
set_status(client,520,"Unknown Error");
|
antd_response_header_t rsh;
|
||||||
__t(client,"Content-Type: text/html; charset=utf-8");
|
rsh.header = dict();
|
||||||
response(client,"");
|
rsh.cookie = NULL;
|
||||||
__t(client,"520 Unknow request");
|
const char* stat_str = get_status_str(status);
|
||||||
|
rsh.status = status;
|
||||||
|
dput(rsh.header, "Content-Type", strdup("text/html; charset=utf-8"));
|
||||||
|
char * res_str = __s(HTML_TPL, stat_str, msg);
|
||||||
|
int clen = 0;
|
||||||
|
if(res_str)
|
||||||
|
{
|
||||||
|
clen = strlen(res_str);
|
||||||
|
}
|
||||||
|
char ibuf[20];
|
||||||
|
snprintf (ibuf, sizeof(ibuf), "%d",clen);
|
||||||
|
dput(rsh.header, "Content-Length", strdup(ibuf));
|
||||||
|
antd_send_header(client, &rsh);
|
||||||
|
if(res_str)
|
||||||
|
{
|
||||||
|
//printf("%s\n", res_str);
|
||||||
|
__b(client, (unsigned char*)res_str, clen);
|
||||||
|
//__t(client, HTML_TPL, stat_str, msg);
|
||||||
|
free(res_str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void notfound(void* client)
|
|
||||||
{
|
|
||||||
set_status(client,404,"Not found");
|
int ws_enable(dictionary_t dic)
|
||||||
__t(client,"Content-Type: text/html; charset=utf-8");
|
|
||||||
response(client,"");
|
|
||||||
__t(client,"Resource not found");
|
|
||||||
}
|
|
||||||
void badrequest(void* client)
|
|
||||||
{
|
|
||||||
set_status(client,400,"Bad request");
|
|
||||||
__t(client,"Content-Type: text/html; charset=utf-8");
|
|
||||||
response(client,"");
|
|
||||||
__t(client,"400 Bad request");
|
|
||||||
}
|
|
||||||
void unimplemented(void* client)
|
|
||||||
{
|
|
||||||
set_status(client,501,"Method Not Implemented");
|
|
||||||
__t(client,"Content-Type: text/html");
|
|
||||||
response(client,"");
|
|
||||||
__t(client, "<HTML><HEAD><TITLE>Method Not Implemented");
|
|
||||||
__t(client, "</TITLE></HEAD>");
|
|
||||||
__t(client, "<BODY><P>HTTP request method not supported.");
|
|
||||||
__t(client, "</BODY></HTML>");
|
|
||||||
}
|
|
||||||
void cannot_execute(void* client)
|
|
||||||
{
|
|
||||||
set_status(client,500,"Internal Server Error");
|
|
||||||
__t(client,"Content-Type: text/html");
|
|
||||||
response(client,"");
|
|
||||||
__t(client, "<P>Error prohibited CGI execution.");
|
|
||||||
}
|
|
||||||
int ws_enable(dictionary dic)
|
|
||||||
{
|
{
|
||||||
if(!dic) return 0;
|
if(!dic) return 0;
|
||||||
char*v = (char*)dvalue(dic, "__web_socket__");
|
char*v = (char*)dvalue(dic, "__web_socket__");
|
||||||
@ -667,7 +655,7 @@ void destroy_request(void *data)
|
|||||||
// free all other thing
|
// free all other thing
|
||||||
if (rq->request)
|
if (rq->request)
|
||||||
{
|
{
|
||||||
dictionary tmp = dvalue(rq->request, "COOKIE");
|
dictionary_t tmp = dvalue(rq->request, "COOKIE");
|
||||||
if (tmp)
|
if (tmp)
|
||||||
freedict(tmp);
|
freedict(tmp);
|
||||||
tmp = dvalue(rq->request, "REQUEST_HEADER");
|
tmp = dvalue(rq->request, "REQUEST_HEADER");
|
||||||
|
43
lib/handle.h
43
lib/handle.h
@ -13,6 +13,7 @@
|
|||||||
#include "dbhelper.h"
|
#include "dbhelper.h"
|
||||||
#endif
|
#endif
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include "dictionary.h"
|
#include "dictionary.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "ini.h"
|
#include "ini.h"
|
||||||
@ -48,9 +49,17 @@ typedef struct{
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
antd_client_t* client;
|
antd_client_t* client;
|
||||||
dictionary request;
|
dictionary_t request;
|
||||||
} antd_request_t;
|
} antd_request_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
dictionary_t header;
|
||||||
|
list_t cookie;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
} antd_response_header_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int port;
|
int port;
|
||||||
@ -59,8 +68,8 @@ typedef struct {
|
|||||||
char *db_path;
|
char *db_path;
|
||||||
char* htdocs;
|
char* htdocs;
|
||||||
char* tmpdir;
|
char* tmpdir;
|
||||||
list rules;
|
list_t rules;
|
||||||
dictionary handlers;
|
dictionary_t handlers;
|
||||||
int backlog;
|
int backlog;
|
||||||
int maxcon;
|
int maxcon;
|
||||||
int connection;
|
int connection;
|
||||||
@ -73,6 +82,8 @@ typedef struct {
|
|||||||
int usessl;
|
int usessl;
|
||||||
char* sslcert;
|
char* sslcert;
|
||||||
char* sslkey;
|
char* sslkey;
|
||||||
|
char* ssl_cipher;
|
||||||
|
dictionary_t mimes;
|
||||||
// #endif
|
// #endif
|
||||||
}config_t;
|
}config_t;
|
||||||
|
|
||||||
@ -90,31 +101,19 @@ typedef struct {
|
|||||||
|
|
||||||
void set_nonblock(int socket);
|
void set_nonblock(int socket);
|
||||||
//void set_block(int socket);
|
//void set_block(int socket);
|
||||||
int response(void*, const char*);
|
|
||||||
void ctype(void*,const char*);
|
void antd_send_header(void*,antd_response_header_t*);
|
||||||
void redirect(void*,const char*);
|
const char* get_status_str(int stat);
|
||||||
void html(void*);
|
|
||||||
void text(void*);
|
|
||||||
void json(void*);
|
|
||||||
void jpeg(void*);
|
|
||||||
void octstream(void*, char*);
|
|
||||||
void textstream(void*);
|
|
||||||
int __ti(void*,int);
|
|
||||||
int __t(void*, const char*,...);
|
int __t(void*, const char*,...);
|
||||||
int __b(void*, const unsigned char*, int);
|
int __b(void*, const unsigned char*, int);
|
||||||
int __f(void*, const char*);
|
int __f(void*, const char*);
|
||||||
//int __fb(void*, const char*);
|
|
||||||
int upload(const char*, const char*);
|
int upload(const char*, const char*);
|
||||||
|
|
||||||
void set_cookie(void*, const char*,dictionary,const char*);
|
|
||||||
void set_status(void*,int,const char*);
|
|
||||||
void clear_cookie(void*, dictionary);
|
|
||||||
/*Default function for plugin*/
|
/*Default function for plugin*/
|
||||||
void unknow(void*);
|
void antd_error(void* client, int status, const char* msg);
|
||||||
void badrequest(void* client);
|
|
||||||
void unimplemented(void* client);
|
int ws_enable(dictionary_t);
|
||||||
void notfound(void* client);
|
|
||||||
int ws_enable(dictionary);
|
|
||||||
char* read_line(void* sock);
|
char* read_line(void* sock);
|
||||||
int read_buf(void* sock,char* buf,int i);
|
int read_buf(void* sock,char* buf,int i);
|
||||||
int antd_send( void *source, const void* data, int len);
|
int antd_send( void *source, const void* data, int len);
|
||||||
|
119
lib/list.c
119
lib/list.c
@ -23,52 +23,52 @@ THE SOFTWARE.
|
|||||||
*/
|
*/
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
list list_init()
|
list_t list_init()
|
||||||
{
|
{
|
||||||
list ret = (list)malloc(sizeof *ret);
|
list_t ret = (list_t)malloc(sizeof *ret);
|
||||||
ret->type = RPC_TYPE_NIL;
|
ret->type = LIST_TYPE_NIL;
|
||||||
ret->next = NULL;
|
ret->next = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
void list_put(list* l, item it)
|
void list_put(list_t* l, item_t it)
|
||||||
{
|
{
|
||||||
if(*l == NULL || (*l)->type == RPC_TYPE_NIL)
|
if(*l == NULL || (*l)->type == LIST_TYPE_NIL)
|
||||||
{
|
{
|
||||||
free(*l);
|
free(*l);
|
||||||
*l = it;
|
*l = it;
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
item np = list_last(*l);
|
item_t np = list_last(*l);
|
||||||
np->next = it;
|
np->next = it;
|
||||||
}
|
}
|
||||||
void list_put_special(list* l, const char* str)
|
void list_put_special(list_t* l, const char* str)
|
||||||
{
|
{
|
||||||
item v;
|
item_t v;
|
||||||
if(IS_INT(str))
|
if(IS_INT(str))
|
||||||
{
|
{
|
||||||
v = list_item(RPC_TYPE_INT);
|
v = list_item(LIST_TYPE_INT);
|
||||||
v->value.i = atoi(str);
|
v->value.i = atoi(str);
|
||||||
}
|
}
|
||||||
else if(IS_FLOAT(str))
|
else if(IS_FLOAT(str))
|
||||||
{
|
{
|
||||||
v = list_item(RPC_TYPE_DOUBLE);
|
v = list_item(LIST_TYPE_DOUBLE);
|
||||||
v->value.d = (double)atof(str);
|
v->value.d = (double)atof(str);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
v = list_item(RPC_TYPE_STRING);
|
v = list_item(LIST_TYPE_STRING);
|
||||||
v->value.s = strdup(str);
|
v->value.s = strdup(str);
|
||||||
}
|
}
|
||||||
list_put(l,v);
|
list_put(l,v);
|
||||||
}
|
}
|
||||||
item list_last(list l)
|
item_t list_last(list_t l)
|
||||||
{
|
{
|
||||||
item p = l;
|
item_t p = l;
|
||||||
while(p && p->next != NULL)
|
while(p && p->next != NULL)
|
||||||
p = p->next;
|
p = p->next;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
int list_remove(list l,int idx)
|
int list_remove(list_t l,int idx)
|
||||||
{
|
{
|
||||||
if(l==NULL) return 0;
|
if(l==NULL) return 0;
|
||||||
if(idx <0 || idx >= list_size(l)) return 0;
|
if(idx <0 || idx >= list_size(l)) return 0;
|
||||||
@ -77,17 +77,17 @@ int list_remove(list l,int idx)
|
|||||||
l=l->next;
|
l=l->next;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
item np = list_at(l,idx-1);
|
item_t np = list_at(l,idx-1);
|
||||||
if(np == NULL) return 0;
|
if(np == NULL) return 0;
|
||||||
if(np->next == NULL) return 1;
|
if(np->next == NULL) return 1;
|
||||||
np->next = np->next->next;
|
np->next = np->next->next;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int list_size(list l)
|
int list_size(list_t l)
|
||||||
{
|
{
|
||||||
if(l == NULL || l->type == RPC_TYPE_NIL) return 0;
|
if(l == NULL || l->type == LIST_TYPE_NIL) return 0;
|
||||||
int i=0;
|
int i=0;
|
||||||
item np = l;
|
item_t np = l;
|
||||||
while(np)
|
while(np)
|
||||||
{
|
{
|
||||||
np = np->next;
|
np = np->next;
|
||||||
@ -95,46 +95,46 @@ int list_size(list l)
|
|||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
char* as_string(list l)
|
char* as_string(list_t l)
|
||||||
{
|
{
|
||||||
char* str = "";
|
char* str = "";
|
||||||
if(l != NULL && l->type != RPC_TYPE_NIL)
|
if(l != NULL && l->type != LIST_TYPE_NIL)
|
||||||
{
|
{
|
||||||
switch(l->type)
|
switch(l->type)
|
||||||
{
|
{
|
||||||
case RPC_TYPE_BASE64:
|
case LIST_TYPE_BASE64:
|
||||||
str = __s("b64:%s", l->value.b64);
|
str = __s("b64:%s", l->value.b64);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RPC_TYPE_BOOL:
|
case LIST_TYPE_BOOL:
|
||||||
str = __s("bool:%d", l->value.b);
|
str = __s("bool:%d", l->value.b);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RPC_TYPE_DOUBLE:
|
case LIST_TYPE_DOUBLE:
|
||||||
str = __s("double:%lf", l->value.d);
|
str = __s("double:%lf", l->value.d);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RPC_TYPE_DATE:
|
case LIST_TYPE_DATE:
|
||||||
str = __s("date:%s", l->value.date);
|
str = __s("date:%s", l->value.date);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RPC_TYPE_INT:
|
case LIST_TYPE_INT:
|
||||||
case RPC_TYPE_I4:
|
case LIST_TYPE_I4:
|
||||||
str = __s("int:%d", l->value.i);
|
str = __s("int:%d", l->value.i);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RPC_TYPE_STRING:
|
case LIST_TYPE_STRING:
|
||||||
str = __s("string:%s", l->value.s);
|
str = __s("string:%s", l->value.s);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RPC_TYPE_ARRAY:
|
case LIST_TYPE_ARRAY:
|
||||||
str = __s("[%s]", as_string(l->value.array));
|
str = __s("[%s]", as_string(l->value.array));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
str = "<Unknown>";
|
str = "<Unknown>";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
item np = l->next;
|
item_t np = l->next;
|
||||||
if(np)
|
if(np)
|
||||||
{
|
{
|
||||||
str = __s("%s,\n%s", str, as_string(np));
|
str = __s("%s,\n%s", str, as_string(np));
|
||||||
@ -143,12 +143,12 @@ char* as_string(list l)
|
|||||||
}
|
}
|
||||||
return "[empty]";
|
return "[empty]";
|
||||||
}
|
}
|
||||||
item list_at(list l,int idx)
|
item_t list_at(list_t l,int idx)
|
||||||
{
|
{
|
||||||
if(l == NULL || idx<0 || idx>= list_size(l))
|
if(l == NULL || idx<0 || idx>= list_size(l))
|
||||||
return NULL;
|
return NULL;
|
||||||
int i=0;
|
int i=0;
|
||||||
item np = l;
|
item_t np = l;
|
||||||
while(np)
|
while(np)
|
||||||
{
|
{
|
||||||
if(i==idx)
|
if(i==idx)
|
||||||
@ -158,20 +158,20 @@ item list_at(list l,int idx)
|
|||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
item list_item(int type)
|
item_t list_item(int type)
|
||||||
{
|
{
|
||||||
item ret = (item)malloc(sizeof *ret);
|
item_t ret = (item_t)malloc(sizeof *ret);
|
||||||
ret->type = type;
|
ret->type = type;
|
||||||
ret->next = NULL;
|
ret->next = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
list split(const char* str, const char* delim)
|
list_t split(const char* str, const char* delim)
|
||||||
{
|
{
|
||||||
if(str == NULL || delim == NULL) return NULL;
|
if(str == NULL || delim == NULL) return NULL;
|
||||||
char* str_cpy = strdup(str);
|
char* str_cpy = strdup(str);
|
||||||
char* org_str = str_cpy;
|
char* org_str = str_cpy;
|
||||||
char* token;
|
char* token;
|
||||||
list l = list_init();
|
list_t l = list_init();
|
||||||
while((token = strsep(&str_cpy,delim)))
|
while((token = strsep(&str_cpy,delim)))
|
||||||
{
|
{
|
||||||
if(strlen(token) > 0)
|
if(strlen(token) > 0)
|
||||||
@ -180,69 +180,72 @@ list split(const char* str, const char* delim)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(org_str);
|
free(org_str);
|
||||||
if(l->type== RPC_TYPE_NIL)
|
if(l->type== LIST_TYPE_NIL)
|
||||||
|
{
|
||||||
|
free(l);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
void list_put_i(list* l,int v)
|
void list_put_i(list_t* l,int v)
|
||||||
{
|
{
|
||||||
item it = list_item(RPC_TYPE_INT);
|
item_t it = list_item(LIST_TYPE_INT);
|
||||||
it->value.i = v;
|
it->value.i = v;
|
||||||
list_put(l,it);
|
list_put(l,it);
|
||||||
}
|
}
|
||||||
void list_put_d(list* l,double v)
|
void list_put_d(list_t* l,double v)
|
||||||
{
|
{
|
||||||
item it = list_item(RPC_TYPE_DOUBLE);
|
item_t it = list_item(LIST_TYPE_DOUBLE);
|
||||||
it->value.d = v;
|
it->value.d = v;
|
||||||
list_put(l,it);
|
list_put(l,it);
|
||||||
}
|
}
|
||||||
void list_put_b(list* l,int v)
|
void list_put_b(list_t* l,int v)
|
||||||
{
|
{
|
||||||
item it = list_item(RPC_TYPE_BOOL);
|
item_t it = list_item(LIST_TYPE_BOOL);
|
||||||
it->value.b = v;
|
it->value.b = v;
|
||||||
list_put(l,it);
|
list_put(l,it);
|
||||||
}
|
}
|
||||||
void list_put_b64(list* l,const char* v)
|
void list_put_b64(list_t* l,const char* v)
|
||||||
{
|
{
|
||||||
item it = list_item(RPC_TYPE_BASE64);
|
item_t it = list_item(LIST_TYPE_BASE64);
|
||||||
it->value.b64 = strdup(v);
|
it->value.b64 = strdup(v);
|
||||||
list_put(l,it);
|
list_put(l,it);
|
||||||
}
|
}
|
||||||
void list_put_date(list* l,const char* v)
|
void list_put_date(list_t* l,const char* v)
|
||||||
{
|
{
|
||||||
item it = list_item(RPC_TYPE_DATE);
|
item_t it = list_item(LIST_TYPE_DATE);
|
||||||
it->value.date = strdup(v);
|
it->value.date = strdup(v);
|
||||||
list_put(l,it);
|
list_put(l,it);
|
||||||
}
|
}
|
||||||
void list_put_s(list* l,const char* v)
|
void list_put_s(list_t* l,const char* v)
|
||||||
{
|
{
|
||||||
item it = list_item(RPC_TYPE_STRING);
|
item_t it = list_item(LIST_TYPE_STRING);
|
||||||
it->value.s = strdup(v);
|
it->value.s = strdup(v);
|
||||||
list_put(l,it);
|
list_put(l,it);
|
||||||
}
|
}
|
||||||
void list_put_array(list* l,list v)
|
void list_put_array(list_t* l,list_t v)
|
||||||
{
|
{
|
||||||
item it = list_item(RPC_TYPE_ARRAY);
|
item_t it = list_item(LIST_TYPE_ARRAY);
|
||||||
it->value.array = v;
|
it->value.array = v;
|
||||||
list_put(l,it);
|
list_put(l,it);
|
||||||
}
|
}
|
||||||
void list_free(list *l)
|
void list_free(list_t *l)
|
||||||
{
|
{
|
||||||
item curr;
|
item_t curr;
|
||||||
while ((curr = (*l)) != NULL) {
|
while ((curr = (*l)) != NULL) {
|
||||||
(*l) = (*l)->next;
|
(*l) = (*l)->next;
|
||||||
if(curr->type == RPC_TYPE_ARRAY)
|
if(curr->type == LIST_TYPE_ARRAY)
|
||||||
list_free(&curr->value.array);
|
list_free(&curr->value.array);
|
||||||
else if(curr->type == RPC_TYPE_STRING)
|
else if(curr->type == LIST_TYPE_STRING)
|
||||||
free(curr->value.s);
|
free(curr->value.s);
|
||||||
else if(curr->type == RPC_TYPE_DATE)
|
else if(curr->type == LIST_TYPE_DATE)
|
||||||
free(curr->value.date);
|
free(curr->value.date);
|
||||||
else if(curr->type == RPC_TYPE_BASE64)
|
else if(curr->type == LIST_TYPE_BASE64)
|
||||||
free(curr->value.b64);
|
free(curr->value.b64);
|
||||||
free (curr);
|
free (curr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int list_empty(list l)
|
int list_empty(list_t l)
|
||||||
{
|
{
|
||||||
return l== NULL || l->type == RPC_TYPE_NIL;
|
return l== NULL || l->type == LIST_TYPE_NIL;
|
||||||
}
|
}
|
54
lib/list.h
54
lib/list.h
@ -24,7 +24,17 @@ THE SOFTWARE.
|
|||||||
#ifndef LIST_H
|
#ifndef LIST_H
|
||||||
#define LIST_H
|
#define LIST_H
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#define list item
|
|
||||||
|
#define LIST_TYPE_ARRAY 601//hash("array")
|
||||||
|
#define LIST_TYPE_BASE64 335//hash("base64")
|
||||||
|
#define LIST_TYPE_BOOL 40//hash("boolean")
|
||||||
|
#define LIST_TYPE_DOUBLE 977//hash("double")
|
||||||
|
#define LIST_TYPE_DATE 49//hash("dateTime.iso8601")
|
||||||
|
#define LIST_TYPE_INT 1007//hash("int")
|
||||||
|
#define LIST_TYPE_I4 235//hash("i4")
|
||||||
|
#define LIST_TYPE_STRING 17//hash("string")
|
||||||
|
#define LIST_TYPE_NIL 529//hash("nil")
|
||||||
|
|
||||||
typedef struct __item{
|
typedef struct __item{
|
||||||
int type;
|
int type;
|
||||||
union{
|
union{
|
||||||
@ -37,25 +47,25 @@ typedef struct __item{
|
|||||||
struct __item* array;
|
struct __item* array;
|
||||||
} value;
|
} value;
|
||||||
struct __item* next;
|
struct __item* next;
|
||||||
}*item;
|
}*item_t;
|
||||||
|
typedef item_t list_t;
|
||||||
list list_init();
|
list_t list_init();
|
||||||
void list_put(list*,item);
|
void list_put(list_t*,item_t);
|
||||||
void list_put_i(list*,int);
|
void list_put_i(list_t*,int);
|
||||||
void list_put_d(list*,double);
|
void list_put_d(list_t*,double);
|
||||||
void list_put_b(list*,int);
|
void list_put_b(list_t*,int);
|
||||||
void list_put_b64(list*,const char*);
|
void list_put_b64(list_t*,const char*);
|
||||||
void list_put_date(list*,const char*);
|
void list_put_date(list_t*,const char*);
|
||||||
void list_put_s(list*,const char*);
|
void list_put_s(list_t*,const char*);
|
||||||
void list_put_array(list*,list);
|
void list_put_array(list_t*,list_t);
|
||||||
item list_last(list);
|
item_t list_last(list_t);
|
||||||
int list_remove(list,int);
|
int list_remove(list_t,int);
|
||||||
int list_size(list);
|
int list_size(list_t);
|
||||||
item list_at(list,int);
|
item_t list_at(list_t,int);
|
||||||
int list_empty(list);
|
int list_empty(list_t);
|
||||||
item list_item(int type);
|
item_t list_item(int type);
|
||||||
list split(const char*, const char*);
|
list_t split(const char*, const char*);
|
||||||
char* as_string(list);
|
char* as_string(list_t);
|
||||||
void list_put_special(list*, const char*);
|
void list_put_special(list_t*, const char*);
|
||||||
void list_free(list *);
|
void list_free(list_t *);
|
||||||
#endif
|
#endif
|
127
lib/utils.c
127
lib/utils.c
@ -23,58 +23,6 @@ THE SOFTWARE.
|
|||||||
*/
|
*/
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
//define all basic mime here
|
|
||||||
|
|
||||||
static mime_t _mimes[] = {
|
|
||||||
{"image/bmp",(const char *[]){"bmp",NULL},1},
|
|
||||||
{"image/jpeg",(const char *[]){"jpg","jpeg",NULL},1},
|
|
||||||
{"text/css",(const char *[]){"css",NULL},0},
|
|
||||||
{"text/markdown",(const char *[]){"md",NULL},0},
|
|
||||||
{"text/csv",(const char *[]){"csv",NULL},0},
|
|
||||||
{"application/pdf",(const char *[]){"pdf",NULL},1},
|
|
||||||
{"image/gif",(const char *[]){"gif",NULL},1},
|
|
||||||
{"text/html",(const char *[]){"html","htm",NULL},0},
|
|
||||||
{"application/json",(const char *[]){"json",NULL},0},
|
|
||||||
{"application/javascript",(const char *[]){"js",NULL},0},
|
|
||||||
{"image/png",(const char *[]){"png",NULL},1},
|
|
||||||
{"image/x-portable-pixmap",(const char *[]){"ppm",NULL},1},
|
|
||||||
{"application/x-rar-compressed",(const char *[]){"rar",NULL},1},
|
|
||||||
{"image/tiff",(const char *[]){"tiff",NULL},1},
|
|
||||||
{"application/x-tar",(const char *[]){"tar",NULL},1},
|
|
||||||
{"text/plain",(const char *[]){"txt",NULL},0},
|
|
||||||
{"application/x-font-ttf",(const char *[]){"ttf",NULL},1},
|
|
||||||
{"application/xhtml+xml",(const char *[]){"xhtml",NULL},0},
|
|
||||||
{"application/xml",(const char *[]){"xml",NULL},0},
|
|
||||||
{"application/zip",(const char *[]){"zip",NULL},1},
|
|
||||||
{"image/svg+xml",(const char *[]){"svg",NULL},0},
|
|
||||||
{"application/vnd.ms-fontobject",(const char *[]){"eot",NULL},1},
|
|
||||||
{"application/x-font-woff",(const char *[]){"woff","woff2",NULL},1},
|
|
||||||
{"application/x-font-otf",(const char *[]){"otf",NULL},1},
|
|
||||||
{"audio/mpeg",(const char *[]){"mp3","mpeg",NULL},1},
|
|
||||||
{NULL,NULL,0}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
char* __s(const char* fstring,...)
|
|
||||||
{
|
|
||||||
char* data;
|
|
||||||
va_list arguments;
|
|
||||||
int dlen;
|
|
||||||
va_start( arguments, fstring);
|
|
||||||
dlen = vsnprintf(0,0,fstring,arguments) + 1;
|
|
||||||
va_end(arguments);
|
|
||||||
va_end(arguments);
|
|
||||||
if ((data = (char*)malloc(dlen*sizeof(char))) != 0)
|
|
||||||
{
|
|
||||||
va_start(arguments, fstring);
|
|
||||||
vsnprintf(data, dlen, fstring, arguments);
|
|
||||||
va_end(arguments);
|
|
||||||
return data;
|
|
||||||
} else
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trim a string by a character on both ends
|
* Trim a string by a character on both ends
|
||||||
* @param str The target string
|
* @param str The target string
|
||||||
@ -162,21 +110,47 @@ char* ext(const char* file)
|
|||||||
/*get mime file info from extension*/
|
/*get mime file info from extension*/
|
||||||
mime_t mime_from_ext(const char* ex)
|
mime_t mime_from_ext(const char* ex)
|
||||||
{
|
{
|
||||||
for(int i = 0; _mimes[i].type != NULL; i++)
|
dictionary_t mime_list = mimes_list();
|
||||||
for(int j = 0; _mimes[i].ext[j] != NULL; j++)
|
mime_t ret = (mime_t){"application/octet-stream",NULL};
|
||||||
|
if(!mime_list)
|
||||||
|
return ret;
|
||||||
|
chain_t it;
|
||||||
|
char * pattern = __s("(^\\s*%s\\s*,)|(\\s*,\\s*%s\\s*,\\s*)|(^\\s*%s\\s*$)|(,\\s*%s\\s*$)", ex, ex, ex, ex);
|
||||||
|
if(pattern)
|
||||||
|
{
|
||||||
|
for_each_assoc(it,mime_list)
|
||||||
{
|
{
|
||||||
if(IEQU(ex,_mimes[i].ext[j])) return _mimes[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return (mime_t){"application/octet-stream",(const char *[]){(char*)ext,NULL},1};
|
if(regex_match(pattern,it->value,0, NULL))
|
||||||
|
{
|
||||||
|
ret.type = it->key;
|
||||||
|
ret.ext = it->value;
|
||||||
|
free(pattern);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(pattern);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
dictionary_t mimes_list()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
/*get mime file info from type*/
|
/*get mime file info from type*/
|
||||||
mime_t mime_from_type(const char* type)
|
mime_t mime_from_type(const char* type)
|
||||||
{
|
{
|
||||||
for(int i = 0; _mimes[i].type != NULL; i++)
|
dictionary_t mime_list = mimes_list();
|
||||||
if(strstr(type, _mimes[i].type) != NULL)
|
mime_t ret = (mime_t){NULL,NULL};
|
||||||
return _mimes[i];
|
if(!mime_list)
|
||||||
return (mime_t){NULL,NULL,0};
|
return ret;
|
||||||
|
chain_t it = dlookup(mime_list, type);
|
||||||
|
if(it)
|
||||||
|
{
|
||||||
|
ret.type = it->key;
|
||||||
|
ret.ext = it->value;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Get correct HTTP mime type of a file
|
* Get correct HTTP mime type of a file
|
||||||
@ -197,17 +171,6 @@ char* mime(const char* file)
|
|||||||
return (char*)m.type;
|
return (char*)m.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_bin(const char* file)
|
|
||||||
{
|
|
||||||
char * ex = ext(file);
|
|
||||||
mime_t m = mime_from_ext(ex);
|
|
||||||
if(ex)
|
|
||||||
{
|
|
||||||
free(ex);
|
|
||||||
}
|
|
||||||
return m.bin;
|
|
||||||
}
|
|
||||||
|
|
||||||
int match_int(const char* search)
|
int match_int(const char* search)
|
||||||
{
|
{
|
||||||
return regex_match("^[-+]?[0-9]+$",search,0, NULL);
|
return regex_match("^[-+]?[0-9]+$",search,0, NULL);
|
||||||
@ -475,3 +438,23 @@ void sha1(const char* text, char* out)
|
|||||||
SHA1_Final(d, &context);
|
SHA1_Final(d, &context);
|
||||||
digest_to_hex(d,out);
|
digest_to_hex(d,out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* __s(const char* fstring,...)
|
||||||
|
{
|
||||||
|
char* data;
|
||||||
|
va_list arguments;
|
||||||
|
int dlen;
|
||||||
|
va_start( arguments, fstring);
|
||||||
|
dlen = vsnprintf(0,0,fstring,arguments) + 1;
|
||||||
|
va_end(arguments);
|
||||||
|
va_end(arguments);
|
||||||
|
if ((data = (char*)malloc(dlen*sizeof(char))) != 0)
|
||||||
|
{
|
||||||
|
va_start(arguments, fstring);
|
||||||
|
vsnprintf(data, dlen, fstring, arguments);
|
||||||
|
va_end(arguments);
|
||||||
|
return data;
|
||||||
|
} else
|
||||||
|
return "";
|
||||||
|
}
|
21
lib/utils.h
21
lib/utils.h
@ -43,6 +43,7 @@ THE SOFTWARE.
|
|||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
#endif
|
#endif
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
|
#include "dictionary.h"
|
||||||
|
|
||||||
#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
|
#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
|
||||||
#define EQU(a,b) (strcmp(a,b) == 0)
|
#define EQU(a,b) (strcmp(a,b) == 0)
|
||||||
@ -54,36 +55,25 @@ THE SOFTWARE.
|
|||||||
#define true 1
|
#define true 1
|
||||||
#define false 0
|
#define false 0
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define LOG(a,...) server_log("%s:%d: " a "\n", __FILE__, \
|
#define LOG(a,...) server_log("[%s: %d]: " a "\n", __FILE__, \
|
||||||
__LINE__, ##__VA_ARGS__)
|
__LINE__, ##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define LOG(a,...) do{}while(0)
|
#define LOG(a,...) do{}while(0)
|
||||||
#endif
|
#endif
|
||||||
#define ERROR(a,...) error_log("%s:%d: " a "\n", __FILE__, \
|
#define ERROR(a,...) error_log("[%s: %d]: " a "\n", __FILE__, \
|
||||||
__LINE__, ##__VA_ARGS__)
|
__LINE__, ##__VA_ARGS__)
|
||||||
// add this to the utils
|
// add this to the utils
|
||||||
#define UNUSED(x) (void)(x)
|
#define UNUSED(x) (void)(x)
|
||||||
|
|
||||||
#define BUFFLEN 1024
|
#define BUFFLEN 1024
|
||||||
#define HASHSIZE 1024
|
#define HASHSIZE 1024
|
||||||
#define DHASHSIZE 50
|
|
||||||
|
|
||||||
#define RPC_TYPE_ARRAY 601//hash("array")
|
|
||||||
#define RPC_TYPE_BASE64 335//hash("base64")
|
|
||||||
#define RPC_TYPE_BOOL 40//hash("boolean")
|
|
||||||
#define RPC_TYPE_DOUBLE 977//hash("double")
|
|
||||||
#define RPC_TYPE_DATE 49//hash("dateTime.iso8601")
|
|
||||||
#define RPC_TYPE_INT 1007//hash("int")
|
|
||||||
#define RPC_TYPE_I4 235//hash("i4")
|
|
||||||
#define RPC_TYPE_STRING 17//hash("string")
|
|
||||||
#define RPC_TYPE_NIL 529//hash("nil")
|
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
const char* type;
|
const char* type;
|
||||||
const char** ext;
|
const char* ext;
|
||||||
int bin;
|
|
||||||
} mime_t;
|
} mime_t;
|
||||||
|
|
||||||
|
dictionary_t __attribute__((weak)) mimes_list();
|
||||||
char* __s(const char*,...);
|
char* __s(const char*,...);
|
||||||
void trim(char*,const char);
|
void trim(char*,const char);
|
||||||
void removeAll(const char* path,int mode);
|
void removeAll(const char* path,int mode);
|
||||||
@ -91,7 +81,6 @@ char* __time(time_t time);
|
|||||||
char* server_time();
|
char* server_time();
|
||||||
char* ext(const char*);
|
char* ext(const char*);
|
||||||
char* mime(const char*);
|
char* mime(const char*);
|
||||||
int is_bin(const char*);
|
|
||||||
int match_int(const char*);
|
int match_int(const char*);
|
||||||
int match_float(const char*);
|
int match_float(const char*);
|
||||||
int regex_match(const char*,const char*, int, regmatch_t*);
|
int regex_match(const char*,const char*, int, regmatch_t*);
|
||||||
|
Loading…
Reference in New Issue
Block a user