the mainline http server

This commit is contained in:
LE Xuan Sang
2015-10-22 11:39:11 +02:00
commit af964b1896
214 changed files with 20824 additions and 0 deletions

BIN
plugins/.DS_Store vendored Normal file

Binary file not shown.

229
plugins/dbhelper.c Normal file
View File

@ -0,0 +1,229 @@
#include "dbhelper.h"
sqlite3 * database(const char* file)
{
sqlite3* db;
int rc = sqlite3_open(file,&db);
if (rc != SQLITE_OK) {
LOG( "Cannot open database: %s %s\n",file, sqlite3_errmsg(db));
sqlite3_close(db);
return NULL;
}
return db;
}
void dbclose(sqlite3* db)
{
sqlite3_close(db);
}
int dbquery(sqlite3* db,const char* sql, int (*call_back)())
{
char *err_msg = 0;
sqlite3_mutex_enter(sqlite3_db_mutex(db));
int rc = sqlite3_exec(db,sql,call_back,0,&err_msg);
sqlite3_mutex_leave(sqlite3_db_mutex(db));
if(rc != SQLITE_OK)
{
LOG("Cannot query : '%s' [%s]\n", sql,err_msg);
sqlite3_free(err_msg);
return 0;
}
return 1;
}
dbfield __field()
{
dbfield ret = malloc(sizeof *ret);
ret->name = NULL;
ret->value = NULL;
ret->next = NULL;
return ret;
}
dbrecord __record()
{
dbrecord ret = malloc(sizeof *ret);
ret->fields = NULL;
ret->idx = 0;
ret->next = NULL;
return ret;
}
char* __name_list(const dbfield f)
{
char* sql = f->name;
for(dbfield p=f->next;p!=NULL;p=p->next)
{
sql = __s("%s,%s",sql,p->name);
}
return sql;
}
char* __value_list(const dbfield f)
{
char* sql = __s("'%s'",f->value);
for(dbfield p=f->next;p!=NULL;p=p->next)
{
sql = __s("%s,'%s'",sql,p->value);
}
return sql;
}
char* __name_value_list(const dbfield f)
{
char* sql = __s("%s='%s'", f->name,f->value);
for(dbfield p=f->next;p!=NULL;p=p->next)
{
sql = __s("%s,%s='%s'",sql, p->name,f->value);
}
return sql;
}
void add_record(dbrecord* r,dbfield f)
{
dbrecord new_r = malloc(sizeof *new_r);
new_r->fields = f;
new_r->idx = 1;
new_r->next = NULL;
if((*r)->idx == 0)
*r = new_r;
else
{
dbrecord* temp;
for(temp = r;(*temp)->next!=NULL;temp=&((*temp)->next))
{
(*temp)->idx++;
}
(*temp)->next = new_r;
}
//new_r->next = *r;
//*r = new_r;
}
void add_field(dbfield* field,const char* name, const char* value)
{
dbfield new_field = malloc(sizeof *new_field);
new_field->name = strdup(name);
new_field->value = strdup(value);
new_field->next = *field;
*field = new_field;
}
char* value_of(const dbfield f,const char* key)
{
for(dbfield t = f; t != NULL; t=t->next)
if(strcmp(t->name,key)==0)
return t->value;
return NULL;
}
int dbinsert(sqlite3* db,const char* table, const dbfield fields)
{
char* sqlprefix = "INSERT INTO %s (%s) VALUES (%s)";
char* name_list = __name_list(fields);
char* value_list = __value_list(fields);
char* sql = __s(sqlprefix,table,name_list,value_list);
int ret = dbquery(db,sql,NULL);
free(name_list);
free(value_list);
free(sql);
if(ret == 0)
return -1;
return sqlite3_last_insert_rowid(db);
}
dbrecord dball(sqlite3* db,const char* table)
{
return dbselect(db,table,"1=%d",1);
}
dbrecord dbselect(sqlite3* db, const char* table,const char* fstring,...)
{
char* sql;
char* prefix = "SELECT * FROM %s WHERE (%s)";
char* cond;
va_list arguments;
int dlen;
sqlite3_stmt *statement;
dbrecord records = __record();
va_start( arguments, fstring);
dlen = vsnprintf(0,0,fstring,arguments) + 1;
va_end(arguments);
cond = (char*) malloc(dlen*sizeof(char));
va_start(arguments, fstring);
vsnprintf(cond, dlen, fstring, arguments);
va_end(arguments);
sql = __s(prefix,table,cond);
if(sqlite3_prepare_v2(db, sql, -1, &statement, 0) == SQLITE_OK)
{
int cols = sqlite3_column_count(statement);
int result = 0;
while((result = sqlite3_step(statement)) == SQLITE_ROW)
{
dbfield fields = __field();
for(int col = 0; col < cols; col++)
{
char *value = (char*)sqlite3_column_text(statement, col);
char *name = (char*)sqlite3_column_name(statement, col);
add_field(&fields,name,(value!=0)?value:"");
}
add_record(&records,fields);
}
sqlite3_finalize(statement);
}
else
{
LOG("Can not select:%s [%s]\n",sql,sqlite3_errmsg(db));
}
free(cond);
free(sql);
return records;
}
int hastable(sqlite3* db,const char* table)
{
char * prefix = "select * from sqlite_master where type='table' and name='%s'";
char* sql = __s(prefix,table);
int ret = dbquery(db,sql,NULL);
free(sql);
return ~ret;
}
int dbupdate(sqlite3* db,const char* table,const dbfield field,const char* fstring,...)
{
char* sql;
char* prefix = "UPDATE %s SET %s WHERE (%s)";
char* cond;
char* list;
va_list arguments;
int dlen;
va_start( arguments, fstring);
dlen = vsnprintf(0,0,fstring,arguments) + 1;
va_end(arguments);
cond = (char*) malloc(dlen*sizeof(char));
va_start(arguments, fstring);
vsnprintf(cond, dlen, fstring, arguments);
va_end(arguments);
list = __name_value_list(field);
sql = __s(prefix,table,list,cond);
int ret = dbquery(db,sql,NULL);
free(cond);
free(list);
free(sql);
return ret;
}
int dbdelete(sqlite3* db,const char* table,const char* fstring,...)
{
char* sql;
char* prefix = "DELETE FROM %s WHERE (%s)";
char* cond;
va_list arguments;
int dlen;
va_start( arguments, fstring);
dlen = vsnprintf(0,0,fstring,arguments) + 1;
va_end(arguments);
cond = (char*) malloc(dlen*sizeof(char));
va_start(arguments, fstring);
vsnprintf(cond, dlen, fstring, arguments);
va_end(arguments);
sql = __s(prefix,table,cond);
int ret = dbquery(db,sql,NULL);
free(cond);
free(sql);
return ret;
}

34
plugins/dbhelper.h Normal file
View File

@ -0,0 +1,34 @@
#include <sqlite3.h>
#include "utils.h"
sqlite3 * database(const char*);
typedef struct _dbfield
{
char* name;
char* value;
struct _dbfield* next;
} *dbfield ;
typedef struct _dbrecord
{
dbfield fields;
int idx;
struct _dbrecord* next;
} * dbrecord;
int dbquery(sqlite3*,const char*, int (*)());
int dbinsert(sqlite3*,const char*,const dbfield);
int hastable(sqlite3*,const char*);
int dbupdate(sqlite3*,const char*,const dbfield,const char*,...);
dbrecord dbselect(sqlite3*, const char*,const char*,...);
dbrecord dball(sqlite3*,const char*);
int dbdelete(sqlite3*,const char*,const char*,...);
dbfield __field();
dbrecord __record();
char* __name_list(const dbfield);
char* __value_list(const dbfield);
char* __name_value_list(const dbfield);
char* value_of(const dbfield,const char*);
void add_field(dbfield*,const char*, const char*);
void add_record(dbrecord*,dbfield);
void dbclose(sqlite3*);

138
plugins/dictionary.c Normal file
View File

@ -0,0 +1,138 @@
#include "dictionary.h"
dictionary dict()
{
dictionary d = (dictionary)malloc(HASHSIZE*sizeof(association));
for(int i=0; i< HASHSIZE;i++)
d[i] = NULL;
return d;
}
unsigned hash(const char* key)
{
unsigned hashval;
for (hashval = 0; *key != '\0'; key++)
hashval = *key + 31 * hashval;
return hashval % HASHSIZE;
}
association dlookup(dictionary dic,const char* key)
{
association np;
if(dic == NULL) return NULL;
for (np = dic[hash(key)]; np != NULL; np = np->next)
{
if(!np || !np->key)
{
return NULL;
}
if (strcmp(key, np->key) == 0)
return np; /* found */
}
return NULL; /* not found */
}
association __put_el_with_key(dictionary dic, const char* key)
{
association np;
unsigned hashval;
if(dic == NULL) return NULL;
if ((np = dlookup(dic,key)) == NULL) { /* not found */
np = (association) malloc(sizeof(*np));
if (np == NULL || (np->key = strdup(key)) == NULL)
return NULL;
hashval = hash(key);
np->next = dic[hashval];
dic[hashval] = np;
}
return np;
}
association dput(dictionary dic,const char* key, const char* value)
{
if(IS_INT(value))
return dput_i(dic,key,atoi(value));
else if(IS_FLOAT(value))
return dput_f(dic,key,atof(value));
else
return dput_s(dic,key,value);
}
association dput_s(dictionary dic,const char* key, const char* value)
{
association np = __put_el_with_key(dic,key);
if(np == NULL) return NULL;
if(value == NULL) np->value.s="";
else if ((np->value.s = strdup(value)) == NULL)
return NULL;
return np;
}
association dput_i(dictionary dic,const char* key, int value)
{
association np = __put_el_with_key(dic,key);
if(np == NULL) return NULL;
np->value.i = value;
return np;
}
association dput_f(dictionary dic,const char* key, float value)
{
association np = __put_el_with_key(dic,key);
if(np == NULL) return NULL;
np->value.f = value;
return np;
}
association dput_p(dictionary dic,const char* key, void* value)
{
association np = __put_el_with_key(dic,key);
if(np == NULL) return NULL;
np->value.p = value;
return np;
}
int dremove(dictionary dic, const char* key)
{
if(dic == NULL) return 0;
int hashval = hash(key);
association np = dic[hashval];
if(np!=NULL && strcmp(key,np->key)==0)
{
dic[hashval] = np->next;
return 1;
}
for (np= dic[hashval]; np != NULL; np = np->next)
if (np->next!=NULL&&strcmp(key, np->next->key) == 0)
{
np->next = np->next->next; /* found */
return 1;
}
return 0; /* not found */
}
/**
* Get the string data by key
* @param dic the dictionary
* @param key @
* @return the string value
*/
char* dvalue(dictionary dic,const char* key)
{
association as = dlookup(dic,key);
if(as == NULL) return NULL;
return as->value.s;
}
int dvalue_i(dictionary dic, const char* key)
{
association as = dlookup(dic,key);
if(as == NULL) return 0;
return as->value.i;
}
float dvalue_f(dictionary dic, const char* key)
{
association as = dlookup(dic,key);
if(as == NULL) return 0;
return as->value.f;
}
void* dvalue_p(dictionary dic, const char* key)
{
association as = dlookup(dic,key);
if(as == NULL) return NULL;
return as->value.p;
}
void freedict(dictionary dic){free(dic);}

38
plugins/dictionary.h Normal file
View File

@ -0,0 +1,38 @@
#include "utils.h"
#define HASHSIZE 255
#define for_each_assoc(assoc, dic) \
for(int i = 0; i < HASHSIZE; i++) \
for(assoc = dic[i];assoc!= NULL; assoc = assoc->next)
/**
* Dictionary for header
*/
typedef struct __assoc{
struct __assoc *next;
char *key;
union
{
int i;
char* s;
float f;
void* p;
} value;
//char *value;
} * association;
typedef association* dictionary;
dictionary dict();
unsigned hash(const char*);
association dlookup(dictionary,const char*);
char* dvalue(dictionary, const char*);
int dvalue_i(dictionary, const char*);
float dvalue_f(dictionary, const char*);
void* dvalue_p(dictionary, const char*);
association dput(dictionary,const char*, const char*);
association dput_s(dictionary,const char*, const char*);
association dput_i(dictionary,const char*, int);
association dput_f(dictionary,const char*, float);
association dput_p(dictionary,const char*, void*);
int dremove(dictionary, const char*);
void freedict(dictionary);
void stest(const char* );

BIN
plugins/dummy/.DS_Store vendored Normal file

Binary file not shown.

128
plugins/dummy/dummy.c Normal file
View File

@ -0,0 +1,128 @@
#include "../plugin.h"
void init();
call __init__ = init;
sqldb db;
void init()
{
db = getdb();
if(db == NULL)
printf("Unable to get database %s \n", __plugin__.name);
// create table
char* sql = "CREATE TABLE dummy(id INTEGER PRIMARY KEY, color TEXT);";
if(hastable(db,"dummy") == 0)
dbquery(db,sql,NULL);
printf("Finish init\n");
}
void execute(int client,const char* method,dictionary rq)
{
char * question;
question = dvalue(rq,"color");
dbfield field = __field();
if(question != NULL)
{
add_field(&field,"color",question);
dbinsert(db,"dummy",field);
}
free(field);
json(client);
dbrecord records = dball(db,"dummy");
__t(client,"{ \"records\":[");
int cnt = 0;
for(dbrecord r = records;r != NULL; r=r->next)
{
if(cnt!=0) __t(client,",");
dbfield row = r-> fields;
__t(client,"{\"id\":%s,\"color\":\"%s\"}",
value_of(row,"id"),
value_of(row,"color"));
free(row);
cnt++;
}
__t(client, "],\"total\":%d}",records->idx);
free(records);
//__t(client, query);
}
// delete record
void delete(int client,const char* method,dictionary rq)
{
char* id = dvalue(rq,"id");
html(client);
if(id==NULL)
{
__t(client,"<p>Invalid delere request <a href='%s'>Back</a></p>", route(NULL));
}
else
{
if(dbdelete(db,"dummy","id=%s",id))
{
redirect(client,route(NULL));
} else
{
__t(client,"<p>Invalid delere request <a href='%s'>Back</a></p>", route(NULL));
}
}
}
void update(int client,const char* method,dictionary rq)
{
char * id;
html(client);
if(IS_GET(method))
{
id = dvalue(rq,"id");
if(id!=NULL)
{
dbrecord rc = dbselect(db,"dummy","id=%s",id);
if(rc->idx > 0)
{
__t(client,"<html><body><FORM ACTION=\"%s\" METHOD=\"POST\">\
Enter a color: \
<textarea rows=\"4\" cols=\"50\" NAME=\"color\">%s</textarea>\
<INPUT TYPE=\"hidden\" NAME=\"id\" Value=\"%s\">\
<INPUT id=\"button\" TYPE=\"submit\">\
</FORM> </body></html>",route("update"),value_of(rc->fields,"color"),id);
free(rc);
return;
}
}
__t(client,"<p>No data found. <a href='%s'>Back</a></p>",route(NULL));
}
else
{
char* color;
id = dvalue(rq,"id");
color = dvalue(rq,"color");
dbfield fields = __field();
add_field(&fields,"color",color);
if(dbupdate(db,"dummy",fields,"id=%s",id))
{
redirect(client,route(NULL));
}
else
{
__t(client,"<p>Invalid Update request <a href='%s'>Back</a></p>", route(NULL));
}
free(fields);
}
}
void jsonex(int client,const char* method,dictionary rq)
{
//json(client);
//__t(client,"{name:\"%s\", age:%d}","Sang",30);
jpeg(client);
__f(client,htdocs("images/ex.jpg"));
}

164
plugins/list.c Normal file
View File

@ -0,0 +1,164 @@
#include "list.h"
Atom __atom()
{
Atom ret = (Atom){.type = T_UNDEF};
return ret;
}
Atom atom(int type)
{
Atom ret = (Atom){.type = type};
return ret;
}
list __list()
{
list ret = malloc(sizeof *ret);
ret->e.type = T_UNDEF;
ret->next = NULL;
return ret;
}
list last(list l)
{
list p = l;
while( p && p->next != NULL)
p = p->next;
return p;
}
int size(list l)
{
int i = 0;
list np = l;
while(np)
{
np = np->next;
i++;
}
return i;
}
Atom lvalueAt(list l,int idx)
{
list np = lat(l,idx);
if(np == NULL) return __atom();
return np->e;
}
list lat(list l,int idx)
{
int i = 0;
list np = l;
while(np && np->next != NULL)
{
if(i== idx)
return np;
np = np->next;
i++;
}
return NULL;
}
list lput(list* l, Atom a)
{
list new_item = malloc(sizeof *new_item);
new_item->e = a;
new_item->next = NULL;
if((*l) == NULL || (*l)->e.type == T_UNDEF)
{
(*l) = new_item;
return (*l);
}
list np = last(*l);
np->next = new_item;
return np->next;
}
int lremove(list l,int idx)
{
if(l == NULL) return 0;
if(idx == 0)
{
l = l->next;
return 1;
}
list np = lat(l,idx-1);
if(np == NULL) return 0;
if(np->next == NULL) return 1;
np->next = np->next->next;
return 1;
}
char* to_string(Atom a)
{
switch(a.type)
{
case T_STR:
return a.value.s;
break;
case T_INT:
return __s("%d",a.value.i);
break;
case T_FLOAT:
return __s("%f",a.value.f);
break;
case T_FIELD:
return f2s(a.value.fi);
break;
default:
return "";
}
}
char* fv2s(field f)
{
switch(f.type)
{
case T_STR:
return __s("%s",f.value.s);
break;
case T_INT:
return __s("%d",f.value.i);
break;
case T_FLOAT:
return __s("%f",f.value.f);
break;
default:
return "";
}
}
char* f2s(field f)
{
switch(f.type)
{
case T_STR:
return __s("%s='%s'",f.name,f.value.s);
break;
case T_INT:
return __s("%s=%d",f.name,f.value.i);
break;
case T_FLOAT:
return __s("%s=%f",f.name,f.value.f);
break;
default:
return "";
}
}
list split(const char* str, const char* delim)
{
if(str == NULL || delim == NULL) return NULL;
char* str_cpy = strdup(str);
char* token;
Atom v = atom(T_STR);
list l = __list();
while((token = strsep(&str_cpy,delim)))
{
if(strlen(token) > 0)
{
v = (Atom){.value.s = strdup(token)};
lput(&l,v);
}
}
free(str_cpy);
if(l->e.type== T_UNDEF)
return NULL;
return l;
}

57
plugins/list.h Normal file
View File

@ -0,0 +1,57 @@
#include "utils.h"
#define T_STR 0
#define T_INT 1
#define T_FLOAT 2
#define T_FIELD 3
#define T_UNDEF 4
typedef struct
{
char* name;
int type;
union
{
int i;
float f;
char* s;
} value;
} field;
typedef struct
{
int type;
union
{
int i;
float f;
char* s;
field fi;
} value;
} Atom;
typedef struct _item
{
Atom e;
struct _item* next;
} *list ;
list __list();
list lput(list*,Atom);
list last(list);
int lremove(list,int);
int size(list);
list lat(list,int);
Atom lvalueAt(list, int);
Atom atom(int type);
char* a2s(Atom);
char* f2s(field);
char* fv2s(field);
list split(const char*, const char*);

214
plugins/plugin.c Normal file
View File

@ -0,0 +1,214 @@
#include "plugin.h"
plugin_header __plugin__;
call __init__;
// private function
void __init_plugin__(const char* pl,const char*ph,const char* htdocs, const char* pdir){
__plugin__.name = strdup(pl);
__plugin__.dbpath= strdup(ph);
__plugin__.htdocs = strdup(htdocs);
__plugin__.pdir = strdup(pdir);
if(__init__ != NULL) __init__();
};
sqldb getdb()
{
int plen = strlen(__plugin__.name)+strlen(__plugin__.dbpath)+4;
char* path = (char*) malloc(plen*sizeof(char));
strcpy(path,__plugin__.dbpath);
strcat(path,__plugin__.name);
strcat(path,".db");
sqldb ret = (sqldb)database(path);
free(path);
return ret;
}
void header_base(int client)
{
response(client, "HTTP/1.0 200 OK");
response(client, "RPI CAR SERVER ");
}
void redirect(int client,const char*path)
{
__t(client,"<html><head><meta http-equiv=\"refresh\" content=\"0; url=%s\"></head><body></body></html>",path);
}
void html(int client)
{
header(client,"text/html; charset=utf-8");
}
void text(int client)
{
header(client,"text/plain; charset=utf-8");
}
void json(int client)
{
header(client,"application/json");
}
void jpeg(int client)
{
header(client,"image/jpeg");
}
void header(int client, const char* type)
{
header_base(client);
__t(client,"Content-Type: %s",type);
response(client,"");
}
void response(int client, const char* data)
{
char buf[BUFFLEN+3];
strcpy(buf, data);
int size = strlen(data);
buf[size] = '\r';
buf[size+1] = '\n';
buf[size+2] = '\0';
send(client, buf, strlen(buf), 0);
}
void __ti(int client,int data)
{
char str[15];
sprintf(str, "%d", data);
response(client,str);
}
void __t(int client, const char* fstring,...)
{
int dlen;
int sent = 0;
int buflen = 0;
va_list arguments;
char * data;
char* chunk;
va_start( arguments, fstring);
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)
response(client,data);
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;
send(client, chunk, buflen, 0);
free(chunk);
}
chunk = "\r\n";
send(client, chunk, strlen(chunk), 0);
}
free(data);
}
//
}
void __b(int client, const unsigned char* data, int size)
{
char buf[BUFFLEN];
int sent = 0;
int buflen = 0;
if(size <= BUFFLEN)
send(client,data,size,0);
else
{
while(sent < size)
{
if(size - sent > BUFFLEN)
buflen = BUFFLEN;
else
buflen = size - sent;
memcpy(buf,data+sent,buflen);
send(client,buf,buflen,0);
sent += buflen;
}
}
}
void __fb(int client, const char* file)
{
printf("Open file %s\n",file );
unsigned char buffer[BUFFLEN];
FILE *ptr;
ptr = fopen(file,"rb");
if(!ptr)
{
LOG("Cannot read : %s\n", file);
return;
}
while(!feof(ptr))
{
fread(buffer,BUFFLEN,1,ptr);
__b(client,buffer,BUFFLEN);
}
fclose(ptr);
}
void __f(int client, const char* file)
{
unsigned char buf[BUFFLEN];
FILE *ptr;
ptr = fopen(file,"r");
if(!ptr)
{
LOG("Cannot read : %s\n", file);
return;
}
fgets(buf, sizeof(buf), ptr);
while(!feof(ptr))
{
send(client, buf, strlen(buf), 0);
fgets(buf, sizeof(buf), ptr);
}
fclose(ptr);
}
char* route(const char* repath)
{
int len = strlen(__plugin__.name) + 2;
if(repath != NULL)
len += strlen(repath)+1;
char * path = (char*) malloc(len*sizeof(char));
strcpy(path,"/");
strcat(path,__plugin__.name);
if(repath != NULL)
{
strcat(path,"/");
strcat(path,repath);
}
return path;
}
char* htdocs(const char* repath)
{
if(repath != NULL)
return __s("%s/%s",__plugin__.htdocs,repath);
else
return __s("%s",__plugin__.htdocs);
}
int upload(const char* tmp, const char* path)
{
return !rename(tmp, path);
}
void set_cookie(int client,dictionary dic)
{
header_base(client);
__t(client,"Content-Type: text/html; charset=utf-8");
association assoc;
for_each_assoc(assoc,dic){
__t(client,"Set-Cookie: %s=%s",assoc->key, assoc->value.s);
}
response(client,"");
}

54
plugins/plugin.h Normal file
View File

@ -0,0 +1,54 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "dbhelper.h"
#include "dictionary.h"
#include "list.h"
#define IS_POST(method) (strcmp(method,"POST")== 0)
#define IS_GET(method) (strcmp(method,"GET")== 0)
#define R_STR(d,k) (dvalue(d,k))
#define R_INT(d,k) (dvalue_i(d,k))
#define R_FLOAT(d,k) (dvalue_f(d,k))
#define R_PTR(d,k) (dvalue_p(d,k))
#define __RESULT__ "{\"result\":%d,\"msg\":\"%s\"}"
typedef struct {
char *name;
char *dbpath;
char * htdocs;
char*pdir;
} plugin_header;
typedef void(*call)();
typedef sqlite3* sqldb;
extern plugin_header __plugin__;
extern call __init__;
void response(int, const char*);
void header_base(int);
void header(int,const char*);
void redirect(int,const char*);
void html(int);
void text(int);
void json(int);
void jpeg(int);
void __ti(int,int);
void __t(int, const char*,...);
void __b(int, const unsigned char*, int);
void __f(int, const char*);
void __fb(int, const char*);
int upload(const char*, const char*);
char* route(const char*);
char* htdocs(const char*);
sqldb getdb();
void dbclose(sqldb);
void set_cookie(int,dictionary);
/*Default function for plugin*/
void execute(int, const char*,dictionary);

10
plugins/urldecode_test.c Normal file
View File

@ -0,0 +1,10 @@
#include "utils.h"
int main(int argc, char const *argv[])
{
char* v = url_decode("code=3%2B4");
if(match_float(argv[1]))
printf("It is a float\n");
printf("Result is %s\n",v);
return 0;
}

298
plugins/utils.c Normal file
View File

@ -0,0 +1,298 @@
#include "utils.h"
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 NULL;
}
/**
* Trim a string by a character on both ends
* @param str The target string
* @param delim the delim
*/
void trim(char* str, const char delim)
{
char * p = str;
int l = strlen(p);
while(p[l - 1] == delim) p[--l] = 0;
while(* p && (* p) == delim ) ++p, --l;
memmove(str, p, l + 1);
}
void removeAll(const char* path,int mode)
{
DIR *d;
struct dirent *dir;
char* file;
struct stat st;
if( stat(path, &st) == 0)
{
if(S_ISDIR(st.st_mode))
{
d = opendir(path);
if(d)
{
while ((dir = readdir(d)) != NULL)
{
if(strcmp(dir->d_name,".") == 0 || strcmp(dir->d_name,"..")==0) continue;
file = __s("%s/%s",path,dir->d_name);
removeAll(file,1);
free(file);
}
closedir(d);
}
}
if(mode)
remove(path);
}
}
char* __time(time_t time)
{
struct tm *t = localtime(&time);
char * buf = asctime(t);
char* pos = strchr(buf,'\n');
if(pos) *pos = '\0';
return buf;
}
char* server_time()
{
return __time(time(NULL));
}
/**
* Get extension of a file name
* @param file The file name
* @return the extension
*/
char* ext(const char* file)
{
char* token,*ltoken = "";
if(file == NULL) return NULL;
char* str_cpy = strdup(file);
if(strstr(str_cpy,".")<= 0) return "";
if(*file == '.')
trim(str_cpy,'.');
while((token = strsep(&str_cpy,".")) && strlen(token)>0) {ltoken = token;}
free(str_cpy);
return ltoken;
}
/**
* Get correct HTTP mime type of a file
* This is a minimalistic mime type list supported
* by the server
* @param file File name
* @return The HTTP Mime Type
*/
char* mime(const char* file)
{
char * ex = ext(file);
if(IEQU(ex,"bmp"))
return "image/bmp";
else if(IEQU(ex,"jpg") || IEQU(ex,"jpeg"))
return "image/jpeg";
else if(IEQU(ex,"css"))
return "text/css";
else if(IEQU(ex,"csv"))
return "text/csv";
else if(IEQU(ex,"pdf"))
return "application/pdf";
else if(IEQU(ex,"gif"))
return "image/gif";
else if(IEQU(ex,"html")||(IEQU(ex,"htm")))
return "text/html";
else if(IEQU(ex,"json"))
return "application/json";
else if(IEQU(ex,"js"))
return "application/javascript";
else if(IEQU(ex,"png"))
return "image/png";
else if(IEQU(ex,"ppm"))
return "image/x-portable-pixmap";
else if(IEQU(ex,"rar"))
return "application/x-rar-compressed";
else if(IEQU(ex,"tiff"))
return "image/tiff";
else if(IEQU(ex,"tar"))
return "application/x-tar";
else if(IEQU(ex,"txt"))
return "text/plain";
else if(IEQU(ex,"ttf"))
return "application/x-font-ttf";
else if(IEQU(ex,"xhtml"))
return "application/xhtml+xml";
else if(IEQU(ex,"xml"))
return "application/xml";
else if(IEQU(ex,"zip"))
return "application/zip";
else if(IEQU(ex,"svg"))
return "image/svg+xml";
else if(IEQU(ex,"eot"))
return "application/vnd.ms-fontobject";
else if(IEQU(ex,"woff") || IEQU(ex,"woff2"))
return "application/x-font-woff";
else if(IEQU(ex,"otf"))
return "application/x-font-otf";
else
// The other type will be undestant as binary
return "application/octet-stream";
}
int is_bin(const char* file)
{
char * ex = ext(file);
if(IEQU(ex,"bmp"))
return true;
else if(IEQU(ex,"jpg") || IEQU(ex,"jpeg"))
return true;
else if(IEQU(ex,"css"))
return false;
else if(IEQU(ex,"csv"))
return false;
else if(IEQU(ex,"pdf"))
return true;
else if(IEQU(ex,"gif"))
return true;
else if(IEQU(ex,"html")||(IEQU(ex,"htm")))
return false;
else if(IEQU(ex,"json"))
return false;
else if(IEQU(ex,"js"))
return false;
else if(IEQU(ex,"png"))
return true;
else if(IEQU(ex,"ppm"))
return true;
else if(IEQU(ex,"rar"))
return true;
else if(IEQU(ex,"tiff"))
return true;
else if(IEQU(ex,"tar"))
return true;
else if(IEQU(ex,"txt"))
return false;
else if(IEQU(ex,"ttf"))
return true;
else if(IEQU(ex,"xhtml"))
return false;
else if(IEQU(ex,"xml"))
return false;
else if(IEQU(ex,"zip"))
return true;
else if(IEQU(ex,"svg"))
return false;
else if(IEQU(ex,"eot"))
return true;
else if(IEQU(ex,"woff") || IEQU(ex,"woff2"))
return true;
else if(IEQU(ex,"otf"))
return true;
else
// The other type will be undestant as binary
return "application/octet-stream";
}
int match_int(const char* search)
{
return regex_match("^[-+]?[0-9]+$",search);
}
int match_float(const char* search)
{
return regex_match("^[+-]?[0-9]*\\.[0-9]+$",search);
}
int regex_match(const char* expr,const char* search)
{
regex_t regex;
int reti;
char msgbuf[100];
int ret;
/* Compile regular expression */
reti = regcomp(&regex, expr, REG_ICASE | REG_EXTENDED);
if( reti ){
LOG("Could not compile regex: %s\n",expr);
return 0;
}
/* Execute regular expression */
reti = regexec(&regex, search, 0, NULL, 0);
if( !reti ){
//LOG("Match");
ret = 1;
}
else if( reti == REG_NOMATCH ){
//LOG("No match");
ret = 0;
}
else{
regerror(reti, &regex, msgbuf, sizeof(msgbuf));
LOG("Regex match failed: %s\n", msgbuf);
ret = 0;
}
regfree(&regex);
return ret;
}
char *url_decode(const char *str) {
char *pstr = str, *buf = malloc(strlen(str) + 1), *pbuf = buf;
while (*pstr) {
if (*pstr == '%') {
if (pstr[1] && pstr[2]) {
*pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
pstr += 2;
}
} else if (*pstr == '+') {
*pbuf++ = ' ';
} else {
*pbuf++ = *pstr;
}
pstr++;
}
*pbuf = '\0';
return buf;
}
char *url_encode(const char *str) {
char *pstr = str, *buf = malloc(strlen(str) * 3 + 1), *pbuf = buf;
while (*pstr) {
if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~')
*pbuf++ = *pstr;
else if (*pstr == ' ')
*pbuf++ = '+';
else
*pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
pstr++;
}
*pbuf = '\0';
return buf;
}
char from_hex(char ch) {
return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
}
char to_hex(char code) {
static char hex[] = "0123456789abcdef";
return hex[code & 15];
}

43
plugins/utils.h Normal file
View File

@ -0,0 +1,43 @@
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <ctype.h>
#include <regex.h>
#include <time.h>
#define EQU(a,b) (strcmp(a,b) == 0)
#define IEQU(a,b) (strcasecmp(a,b) == 0)
#define IS_INT(a) (match_int(a))
#define IS_FLOAT(a) (match_float(a))
#define DIR_SEP "/"
#define true 1
#define false 0
#ifdef DEBUG
#define LOG(a,...) printf("%s:%d: " a, __FILE__, \
__LINE__, ##__VA_ARGS__)
#else
#define LOG(a,...) do{}while(0)
#endif
#define BUFFLEN 1024
char* __s(const char*,...);
void trim(char*,const char);
void removeAll(const char* path,int mode);
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*);
char *url_decode(const char *str);
char *url_encode(const char *str);
char from_hex(char ch);
char to_hex(char code);