1
0
mirror of https://github.com/lxsang/ant-http synced 2024-07-01 12:59:47 +02:00
This commit is contained in:
lxsang 2019-12-15 12:10:06 +01:00
parent 1e2e600bfc
commit 8d2449bd69
14 changed files with 538 additions and 447 deletions

View File

@ -53,3 +53,9 @@ autoconf
automake --add-missing
make distcheck
```
### To do
- variable size dictionary
- refactoring libantd API, remove unused functions
- remove static strings, replace it by configurations

View File

@ -25,7 +25,7 @@ ssl.enable=0
; the SSL cert and key files
; ssl.cert=fullchain.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
[AUTOSTART]
; 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>
; 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]
; specify a plugin for handling
; a file type

Binary file not shown.

View File

@ -1,4 +1,26 @@
#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;
config_t server_config;
config_t *config()
@ -64,6 +86,8 @@ void destroy_config()
free(server_config.htdocs);
if (server_config.tmpdir)
free(server_config.tmpdir);
if(server_config.ssl_cipher)
free(server_config.ssl_cipher);
if(server_config.errorfp)
{
fclose(server_config.errorfp);
@ -74,6 +98,8 @@ void destroy_config()
fclose(server_config.logfp);
}
#endif
if(server_config.mimes)
freedict(server_config.mimes);
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);
}
else if(MATCH("SERVER","ssl.cipher"))
{
pconfig->ssl_cipher = strdup(value);
}
#endif
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
plugin_load((char *)value);
}
else if(strcmp(section, "MIMES") == 0)
{
dput(pconfig->mimes,name,strdup(value));
}
else
{
return 0; /* unknown section/name, error */
@ -193,11 +227,18 @@ void load_config(const char *file)
server_config.handlers = dict();
server_config.maxcon = 1000;
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.sslcert = "cert.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)
{
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 cert %s", server_config.sslcert);
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
}
init_file_system();
LOG("%d mimes entries found", server_config.mimes->size);
}
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);
if (sel == -1)
{
unknow(rq->client);
antd_error(rq->client, 400, "Bad request");
return task;
}
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());
//server_config.connection++;
ERR_print_errors_fp(stderr);
unknow(rq->client);
antd_error(rq->client, 400, "Invalid SSL request");
return task;
}
}
@ -320,7 +365,7 @@ void *accept_request(void *data)
if (!line)
{
LOG("No method found");
unknow(rq->client);
antd_error(rq->client, 405, "No method found");
return task;
}
trim(token, ' ');
@ -331,7 +376,7 @@ void *accept_request(void *data)
if (!line)
{
LOG("No request found");
unknow(rq->client);
antd_error(rq->client, 400, "Bad request");
return task;
}
trim(token, ' ');
@ -388,7 +433,7 @@ void *resolve_request(void *data)
strcat(path, "/index.html");
if (stat(path, &st) == -1)
{
association it;
chain_t it;
for_each_assoc(it, server_config.handlers)
{
newurl = __s("%s/index.%s", url, it->key);
@ -408,7 +453,7 @@ void *resolve_request(void *data)
}
if (!newurl)
{
notfound(rq->client);
antd_error(rq->client, 404, "Resource Not Found");
return task;
}
//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);
}
else
unknow(rq->client);
antd_error(rq->client, 403, "Access forbidden");
}
else
{
@ -553,15 +598,21 @@ void *serve_file(void *data)
int s = stat(path, &st);
if(s == -1)
{
notfound(rq->client);
antd_error(rq->client, 404, "File not found");
}
else
{
int size = (int)st.st_size;
set_status(rq->client,200,"OK");
__t(rq->client,"Content-Type: %s",mime_type);
__t(rq->client,"Content-Length: %d",size);
response(rq->client,"");
char ibuf[20];
snprintf (ibuf, sizeof(ibuf), "%d",size);
antd_response_header_t rhd;
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);
}
@ -637,15 +688,15 @@ char *apply_rules(const char *host, char *url)
void *decode_request_header(void *data)
{
antd_request_t *rq = (antd_request_t *)data;
dictionary cookie = NULL;
dictionary_t cookie = NULL;
char *line;
char *token;
char *query = NULL;
char *host = NULL;
char buf[2 * BUFFLEN];
char *url = (char *)dvalue(rq->request, "REQUEST_QUERY");
dictionary xheader = dict();
dictionary request = dict();
dictionary_t xheader = dict();
dictionary_t request = dict();
dput(rq->request, "REQUEST_HEADER", xheader);
dput(rq->request, "REQUEST_DATA", request);
// first real all header
@ -700,7 +751,7 @@ void *decode_request_header(void *data)
void *decode_request(void *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;
char *ws_key = NULL;
char *method = NULL;
@ -736,7 +787,7 @@ void *decode_request(void *data)
}
else
{
unimplemented(rq->client);
antd_error(rq->client,501, "Request Method Not Implemented");
return task;
}
}
@ -744,8 +795,8 @@ void *decode_request(void *data)
void *decode_post_request(void *data)
{
antd_request_t *rq = (antd_request_t *)data;
dictionary request = dvalue(rq->request, "REQUEST_DATA");
dictionary headers = dvalue(rq->request, "REQUEST_HEADER");
dictionary_t request = dvalue(rq->request, "REQUEST_DATA");
dictionary_t headers = dvalue(rq->request, "REQUEST_HEADER");
char *ctype = NULL;
int clen = -1;
char *tmp;
@ -762,8 +813,7 @@ void *decode_post_request(void *data)
return task;
if (ctype == NULL || clen == -1)
{
LOG("Bad request");
badrequest(rq->client);
antd_error(rq->client, 400, "Bad Request, missing content description");
return task;
}
// decide what to do with the data
@ -787,8 +837,11 @@ void *decode_post_request(void *data)
key++;
else
key = ctype;
dput(request, key, strdup(pquery));
free(pquery);
if(pquery)
{
dput(request, key, strdup(pquery));
free(pquery);
}
}
return task;
}
@ -837,7 +890,7 @@ void ws_confirm_request(void *client, const char *key)
* @param client The client socket
* @return The Dictionary socket or NULL
*/
dictionary decode_cookie(const char *line)
dictionary_t decode_cookie(const char *line)
{
char *token, *token1;
char *cpstr = strdup(line);
@ -846,7 +899,7 @@ dictionary decode_cookie(const char *line)
trim(cpstr, '\n');
trim(cpstr, '\r');
dictionary dic = NULL;
dictionary_t dic = NULL;
while ((token = strsep(&cpstr, ";")))
{
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);
task->priority++;
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);
// search for content disposition:
while ((line = read_line(rq->client)) &&
@ -1063,7 +1116,7 @@ void *decode_multi_part_request_data(void *data)
* @param query : the query string
* @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)
return;
@ -1156,7 +1209,7 @@ void *execute_plugin(void *data, const char *pname)
pthread_mutex_unlock(&server_mux);
if (plugin == NULL)
{
unknow(rq->client);
antd_error(rq->client, 503, "Requested service not found");
return task;
}
}
@ -1171,7 +1224,7 @@ void *execute_plugin(void *data, const char *pname)
if ((error = dlerror()) != NULL)
{
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;
}
// check if we need the raw data or not
@ -1195,3 +1248,8 @@ int usessl()
return server_config.usessl;
}
#endif
dictionary_t mimes_list()
{
return server_config.mimes;
}

View File

@ -35,14 +35,14 @@ void badrequest(void*);
int rule_check(const char*, const char*, const char* , const char* , const char* , char*);
void ws_confirm_request(void*, const char*);
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(void* data);
void* decode_post_request(void* data);
void* resolve_request(void* data);
void* decode_multi_part_request(void*,const char*);
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);
void set_nonblock(int);
void* execute_plugin(void* data, const char *path);

View File

@ -10,8 +10,8 @@ static int server_sock = -1;
// define the cipher suit used
// 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;
SSL_CTX *ctx;

View File

@ -22,19 +22,33 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "dictionary.h"
#include "utils.h"
dictionary dict()
dictionary_t dict()
{
dictionary d = (dictionary)malloc(DHASHSIZE*sizeof(association));
for(int i=0; i< DHASHSIZE;i++)
d[i] = NULL;
return dict_n(DHASHSIZE);
}
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;
}
association dlookup(dictionary dic,const char* key)
chain_t dlookup(dictionary_t dic,const char* key)
{
association np;
if(dic == NULL) return NULL;
for (np = dic[hash(key,DHASHSIZE)]; np != NULL; np = np->next)
chain_t np;
if(dic->map == NULL) return NULL;
for (np = dic->map[hash(key,dic->cap)]; np != NULL; np = np->next)
{
if(!np || !np->key)
{
@ -45,26 +59,27 @@ association dlookup(dictionary dic,const char* key)
}
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;
if(dic == NULL) return NULL;
if(dic->map == NULL) return NULL;
if ((np = dlookup(dic,key)) == NULL) { /* not found */
np = (association) malloc(sizeof(*np));
np->value = NULL;
np = (chain_t) malloc(sizeof(*np));
if (np == NULL || (np->key = strdup(key)) == NULL)
return NULL;
hashval = hash(key, DHASHSIZE);
np->next = dic[hashval];
dic[hashval] = np;
np->value = NULL;
hashval = hash(key, dic->cap);
np->next = dic->map[hashval];
dic->map[hashval] = np;
dic->size++;
}
// found
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(value) free(value);
@ -74,38 +89,43 @@ association dput(dictionary dic,const char* key, void* value)
np->value = value;
return np;
}
int dremove(dictionary dic, const char* key)
chain_t dremove(dictionary_t dic, const char* key)
{
if(dic == NULL) return 0;
int hashval = hash(key, DHASHSIZE);
association np = dic[hashval];
if(dic->map == NULL) return 0;
int hashval = hash(key, dic->cap);
chain_t np = dic->map[hashval];
if(np!=NULL && strcmp(key,np->key)==0)
{
dic[hashval] = np->next;
return 1;
dic->size--;
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)
{
chain_t ret = np->next;
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;
return as->value;
}
void free_association(association * asoc)
void free_association(chain_t * asoc)
{
while( (*asoc) != NULL )
{
association a = *asoc;
chain_t a = *asoc;
(* asoc) = (*asoc) ->next;
if(a->key)
@ -118,11 +138,11 @@ void free_association(association * asoc)
}
void freedict(dictionary dic){
for(int i = 0; i < DHASHSIZE; i++)
free_association(&(dic[i]));
void freedict(dictionary_t dic){
for(unsigned int i = 0; i < dic->cap; i++)
free_association(&(dic->map[i]));
free(dic->map);
free(dic);
}

View File

@ -24,10 +24,10 @@ THE SOFTWARE.
#ifndef DICTIONARY_H
#define DICTIONARY_H
#include "utils.h"
#define DHASHSIZE 16
#define for_each_assoc(assoc, dic) \
for(int i = 0; i < DHASHSIZE; i++) \
for(assoc = dic[i];assoc!= NULL; assoc = assoc->next)
for(unsigned int i = 0; i < dic->cap; i++) \
for(assoc = dic->map[i];assoc!= NULL; assoc = assoc->next)
/**
* Dictionary for header
@ -37,14 +37,22 @@ typedef struct __assoc{
char *key;
void* value;
//char *value;
} * association;
} * chain_t;
typedef association* dictionary;
dictionary dict();
association dlookup(dictionary,const char*);
void* dvalue(dictionary, const char*);
association dput(dictionary,const char*, void*);
int dremove(dictionary, const char*);
void freedict(dictionary);
typedef chain_t* map_t;
typedef struct __dict{
unsigned int cap;
map_t map;
unsigned int size;
}* 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

View File

@ -1,4 +1,5 @@
#include "handle.h"
#define HTML_TPL "<HTML><HEAD><TITLE>%s</TITLE></HEAD><BODY><h2>%s</h2></BODY></HTML>"
#ifdef USE_OPENSSL
int usessl()
{
@ -18,36 +19,110 @@ void server_log(const char* fmt, ...)
return;
}
#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);
response(client, s);
free(s);
s = __s("Server: %s ", SERVER_NAME);
response(client, s);
free(s);
}
void redirect(void* client,const char*path)
{
__t(client,"<html><head><meta http-equiv=\"refresh\" content=\"0; url=%s\"></head><body></body></html>",path);
switch(stat)
{
case 100: return "Continue";
case 101: return "Switching Protocols";
case 102: return "Processing";
case 103: return "Early Hints";
case 200: return "OK";
case 201: return "Created";
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");
}
void text(void* client)
{
ctype(client,"text/plain; charset=utf-8");
}
void json(void* client)
{
ctype(client,"application/json");
}
void textstream(void* client)
{
ctype(client, "text/event-stream");
if(!res->header)
res->header = dict();
dput(res->header,"Server", strdup(SERVER_NAME));
const char* stat_str = get_status_str(res->status);
__t(client, "HTTP/1.1 %d %s", res->status, stat_str);
chain_t it;
for_each_assoc(it, res->header)
{
__t(client,"%s: %s", it->key, (const char*)it->value);
}
// send out cookie
if(res->cookie)
{
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)
{
set_status(client,200,"OK");
@ -55,38 +130,15 @@ void octstream(void* client, char* name)
__t(client,"Content-Disposition: attachment; filename=\"%s\"", name);
response(client,"");
//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)
{
if(!src || !data) return -1;
int written;
antd_client_t * source = (antd_client_t *) src;
char* ptr;
int writelen;
int writelen = 0;
int count;
#ifdef USE_OPENSSL
if(usessl())
@ -200,7 +252,9 @@ int antd_send(void *src, const void* data, int len)
}
else if(count == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
{
return written;
ERROR("Error while writing: %s", strerror(errno));
break;
//return written;
}
}
#ifdef USE_OPENSSL
@ -351,6 +405,7 @@ int antd_recv(void *src, void* data, int len)
}
else if(errno != EAGAIN && errno != EWOULDBLOCK)
{
ERROR("Error while writing: %s", strerror(errno));
break;
}
}
@ -408,66 +463,27 @@ int antd_close(void* src)
src = NULL;
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 nbytes;
int dlen;
int sent = 0;
int buflen = 0;
int st;
va_list arguments;
char * data;
char* chunk;
va_start( arguments, fstring);
dlen = vsnprintf(0,0,fstring,arguments) + 1;
dlen = vsnprintf(0,0,fstring,arguments)+1;
va_end(arguments);
if ((data = (char*)malloc(dlen*sizeof(char))) != 0)
{
va_start(arguments, fstring);
vsnprintf(data, dlen, fstring, arguments);
va_end(arguments);
if(dlen < BUFFLEN)
{
int ret = response(client,data);
free(data);
return ret;
}
else
{
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));
}
st = __b(client, (const unsigned char*)data, strlen(data));
__b(client, (unsigned char*)"\r\n", 2);
free(data);
return st;
}
return 1;
return 0;
//
}
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];
int sent = 0;
int buflen = 0;
int nbytes;
int nbytes = 0;
if(size <= BUFFLEN)
/*if(size <= BUFFLEN)
{
nbytes = antd_send(client,data,size);
return (nbytes==-1?0:1);
}
else
{
{*/
while(sent < size)
{
if(size - sent > BUFFLEN)
@ -492,10 +508,13 @@ int __b(void* client, const unsigned char* data, int size)
buflen = size - sent;
memcpy(buf,data+sent,buflen);
nbytes = antd_send(client,buf,buflen);
sent += buflen;
if(nbytes == -1) return 0;
if(nbytes == -1)
{
return 0;
}
sent += nbytes;
}
}
//}
return 1;
}
int __f(void* client, const char* file)
@ -517,95 +536,64 @@ int __f(void* client, const char* file)
fclose(ptr);
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)
{
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");
__t(client,"Content-Type: %s",type);
association assoc;
chain_t assoc;
for_each_assoc(assoc,dic){
__t(client,"Set-Cookie: %s=%s; Path=/%s",assoc->key, (char*)assoc->value, name);
}
response(client,"");
}
void clear_cookie(void* client, dictionary dic)
void clear_cookie(void* client, dictionary_t dic)
{
set_status(client,200,"OK");
__t(client,"Content-Type: text/html; charset=utf-8");
association assoc;
chain_t assoc;
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,"");
}
void unknow(void* client)
*/
void antd_error(void* client, int status, const char* msg)
{
set_status(client,520,"Unknown Error");
__t(client,"Content-Type: text/html; charset=utf-8");
response(client,"");
__t(client,"520 Unknow request");
antd_response_header_t rsh;
rsh.header = dict();
rsh.cookie = NULL;
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");
__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)
int ws_enable(dictionary_t dic)
{
if(!dic) return 0;
char*v = (char*)dvalue(dic, "__web_socket__");
@ -667,7 +655,7 @@ void destroy_request(void *data)
// free all other thing
if (rq->request)
{
dictionary tmp = dvalue(rq->request, "COOKIE");
dictionary_t tmp = dvalue(rq->request, "COOKIE");
if (tmp)
freedict(tmp);
tmp = dvalue(rq->request, "REQUEST_HEADER");

View File

@ -13,6 +13,7 @@
#include "dbhelper.h"
#endif
#include <fcntl.h>
#include <stdlib.h>
#include "dictionary.h"
#include "list.h"
#include "ini.h"
@ -48,9 +49,17 @@ typedef struct{
typedef struct {
antd_client_t* client;
dictionary request;
dictionary_t request;
} antd_request_t;
typedef struct
{
dictionary_t header;
list_t cookie;
int status;
} antd_response_header_t;
typedef struct {
int port;
@ -59,8 +68,8 @@ typedef struct {
char *db_path;
char* htdocs;
char* tmpdir;
list rules;
dictionary handlers;
list_t rules;
dictionary_t handlers;
int backlog;
int maxcon;
int connection;
@ -73,6 +82,8 @@ typedef struct {
int usessl;
char* sslcert;
char* sslkey;
char* ssl_cipher;
dictionary_t mimes;
// #endif
}config_t;
@ -90,31 +101,19 @@ typedef struct {
void set_nonblock(int socket);
//void set_block(int socket);
int response(void*, const char*);
void ctype(void*,const char*);
void redirect(void*,const char*);
void html(void*);
void text(void*);
void json(void*);
void jpeg(void*);
void octstream(void*, char*);
void textstream(void*);
int __ti(void*,int);
void antd_send_header(void*,antd_response_header_t*);
const char* get_status_str(int stat);
int __t(void*, const char*,...);
int __b(void*, const unsigned char*, int);
int __f(void*, const char*);
//int __fb(void*, 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*/
void unknow(void*);
void badrequest(void* client);
void unimplemented(void* client);
void notfound(void* client);
int ws_enable(dictionary);
void antd_error(void* client, int status, const char* msg);
int ws_enable(dictionary_t);
char* read_line(void* sock);
int read_buf(void* sock,char* buf,int i);
int antd_send( void *source, const void* data, int len);

View File

@ -23,52 +23,52 @@ THE SOFTWARE.
*/
#include "list.h"
list list_init()
list_t list_init()
{
list ret = (list)malloc(sizeof *ret);
ret->type = RPC_TYPE_NIL;
list_t ret = (list_t)malloc(sizeof *ret);
ret->type = LIST_TYPE_NIL;
ret->next = NULL;
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);
*l = it;
return ;
}
item np = list_last(*l);
item_t np = list_last(*l);
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))
{
v = list_item(RPC_TYPE_INT);
v = list_item(LIST_TYPE_INT);
v->value.i = atoi(str);
}
else if(IS_FLOAT(str))
{
v = list_item(RPC_TYPE_DOUBLE);
v = list_item(LIST_TYPE_DOUBLE);
v->value.d = (double)atof(str);
}
else
{
v = list_item(RPC_TYPE_STRING);
v = list_item(LIST_TYPE_STRING);
v->value.s = strdup(str);
}
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)
p = p->next;
return p;
}
int list_remove(list l,int idx)
int list_remove(list_t l,int idx)
{
if(l==NULL) 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;
return 1;
}
item np = list_at(l,idx-1);
item_t np = list_at(l,idx-1);
if(np == NULL) return 0;
if(np->next == NULL) return 1;
np->next = np->next->next;
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;
item np = l;
item_t np = l;
while(np)
{
np = np->next;
@ -95,46 +95,46 @@ int list_size(list l)
}
return i;
}
char* as_string(list l)
char* as_string(list_t l)
{
char* str = "";
if(l != NULL && l->type != RPC_TYPE_NIL)
if(l != NULL && l->type != LIST_TYPE_NIL)
{
switch(l->type)
{
case RPC_TYPE_BASE64:
case LIST_TYPE_BASE64:
str = __s("b64:%s", l->value.b64);
break;
case RPC_TYPE_BOOL:
case LIST_TYPE_BOOL:
str = __s("bool:%d", l->value.b);
break;
case RPC_TYPE_DOUBLE:
case LIST_TYPE_DOUBLE:
str = __s("double:%lf", l->value.d);
break;
case RPC_TYPE_DATE:
case LIST_TYPE_DATE:
str = __s("date:%s", l->value.date);
break;
case RPC_TYPE_INT:
case RPC_TYPE_I4:
case LIST_TYPE_INT:
case LIST_TYPE_I4:
str = __s("int:%d", l->value.i);
break;
case RPC_TYPE_STRING:
case LIST_TYPE_STRING:
str = __s("string:%s", l->value.s);
break;
case RPC_TYPE_ARRAY:
case LIST_TYPE_ARRAY:
str = __s("[%s]", as_string(l->value.array));
break;
default:
str = "<Unknown>";
break;
}
item np = l->next;
item_t np = l->next;
if(np)
{
str = __s("%s,\n%s", str, as_string(np));
@ -143,12 +143,12 @@ char* as_string(list l)
}
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))
return NULL;
int i=0;
item np = l;
item_t np = l;
while(np)
{
if(i==idx)
@ -158,20 +158,20 @@ item list_at(list l,int idx)
}
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->next = NULL;
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;
char* str_cpy = strdup(str);
char* org_str = str_cpy;
char* token;
list l = list_init();
list_t l = list_init();
while((token = strsep(&str_cpy,delim)))
{
if(strlen(token) > 0)
@ -180,69 +180,72 @@ list split(const char* str, const char* delim)
}
}
free(org_str);
if(l->type== RPC_TYPE_NIL)
if(l->type== LIST_TYPE_NIL)
{
free(l);
return NULL;
}
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;
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;
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;
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);
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);
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);
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;
list_put(l,it);
}
void list_free(list *l)
void list_free(list_t *l)
{
item curr;
item_t curr;
while ((curr = (*l)) != NULL) {
(*l) = (*l)->next;
if(curr->type == RPC_TYPE_ARRAY)
if(curr->type == LIST_TYPE_ARRAY)
list_free(&curr->value.array);
else if(curr->type == RPC_TYPE_STRING)
else if(curr->type == LIST_TYPE_STRING)
free(curr->value.s);
else if(curr->type == RPC_TYPE_DATE)
else if(curr->type == LIST_TYPE_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);
}
}
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;
}

View File

@ -24,7 +24,17 @@ THE SOFTWARE.
#ifndef LIST_H
#define LIST_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{
int type;
union{
@ -37,25 +47,25 @@ typedef struct __item{
struct __item* array;
} value;
struct __item* next;
}*item;
list list_init();
void list_put(list*,item);
void list_put_i(list*,int);
void list_put_d(list*,double);
void list_put_b(list*,int);
void list_put_b64(list*,const char*);
void list_put_date(list*,const char*);
void list_put_s(list*,const char*);
void list_put_array(list*,list);
item list_last(list);
int list_remove(list,int);
int list_size(list);
item list_at(list,int);
int list_empty(list);
item list_item(int type);
list split(const char*, const char*);
char* as_string(list);
void list_put_special(list*, const char*);
void list_free(list *);
}*item_t;
typedef item_t list_t;
list_t list_init();
void list_put(list_t*,item_t);
void list_put_i(list_t*,int);
void list_put_d(list_t*,double);
void list_put_b(list_t*,int);
void list_put_b64(list_t*,const char*);
void list_put_date(list_t*,const char*);
void list_put_s(list_t*,const char*);
void list_put_array(list_t*,list_t);
item_t list_last(list_t);
int list_remove(list_t,int);
int list_size(list_t);
item_t list_at(list_t,int);
int list_empty(list_t);
item_t list_item(int type);
list_t split(const char*, const char*);
char* as_string(list_t);
void list_put_special(list_t*, const char*);
void list_free(list_t *);
#endif

View File

@ -23,58 +23,6 @@ THE SOFTWARE.
*/
#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
* @param str The target string
@ -162,21 +110,47 @@ char* ext(const char* file)
/*get mime file info from extension*/
mime_t mime_from_ext(const char* ex)
{
for(int i = 0; _mimes[i].type != NULL; i++)
for(int j = 0; _mimes[i].ext[j] != NULL; j++)
{
if(IEQU(ex,_mimes[i].ext[j])) return _mimes[i];
}
return (mime_t){"application/octet-stream",(const char *[]){(char*)ext,NULL},1};
dictionary_t mime_list = mimes_list();
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(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*/
mime_t mime_from_type(const char* type)
{
for(int i = 0; _mimes[i].type != NULL; i++)
if(strstr(type, _mimes[i].type) != NULL)
return _mimes[i];
return (mime_t){NULL,NULL,0};
dictionary_t mime_list = mimes_list();
mime_t ret = (mime_t){NULL,NULL};
if(!mime_list)
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
@ -194,18 +168,7 @@ char* mime(const char* file)
{
free(ex);
}
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;
return (char*)m.type;
}
int match_int(const char* search)
@ -475,3 +438,23 @@ void sha1(const char* text, char* out)
SHA1_Final(d, &context);
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 "";
}

View File

@ -43,6 +43,7 @@ THE SOFTWARE.
#include "sha1.h"
#endif
#include "base64.h"
#include "dictionary.h"
#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
#define EQU(a,b) (strcmp(a,b) == 0)
@ -54,36 +55,25 @@ THE SOFTWARE.
#define true 1
#define false 0
#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__)
#else
#define LOG(a,...) do{}while(0)
#endif
#define ERROR(a,...) error_log("%s:%d: " a "\n", __FILE__, \
#define ERROR(a,...) error_log("[%s: %d]: " a "\n", __FILE__, \
__LINE__, ##__VA_ARGS__)
// add this to the utils
#define UNUSED(x) (void)(x)
#define BUFFLEN 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{
const char* type;
const char** ext;
int bin;
const char* ext;
} mime_t;
dictionary_t __attribute__((weak)) mimes_list();
char* __s(const char*,...);
void trim(char*,const char);
void removeAll(const char* path,int mode);
@ -91,7 +81,6 @@ char* __time(time_t time);
char* server_time();
char* ext(const char*);
char* mime(const char*);
int is_bin(const char*);
int match_int(const char*);
int match_float(const char*);
int regex_match(const char*,const char*, int, regmatch_t*);