该版本在module_request.c文件中增加了url_decode的静态C函数,该函数用于对字符串进行url解码,同时新增builtin模块,该模块对应的C文件为:module_builtin.c,该模块目前有两个模块函数:bltArray和bltIterArray,bltArray用于创建数组,bltIterArray用于迭代数组成员...
/** * 对str字符串参数进行url解码, * 例如:%E7%A8%8B%E5%BA%8F%E5%91%98 解码后对应的就是UTF8编码的字符串“程序员” * 通过将%E7转为0xE7的字节,%A8转为0xA8的字节,从而实现解码 */ static char * url_decode(char * str) { int str_len = strlen(str); char e_char[] = "00"; for(int i = 0; i < str_len;i++) { switch(str[i]) { case '%': if(str[i+1] == '\0') return str; if(isxdigit(str[i+1]) && isxdigit(str[i+2])) { e_char[0] = str[i+1]; e_char[1] = str[i+2]; long int x = strtol(e_char, NULL, 16); /* remove the hex */ memmove(&str[i+1], &str[i+3], strlen(&str[i+3])+1); str_len -= 2; str[i] = x; } break; case '+': str[i] = ' '; break; } } return str; } |
/** * rqtGetQuery模块函数,用于返回查询字符串的哈希数组形式 * 例如: * querys = rqtGetQuery(); * print 'querys[\'name\']: ' + querys['name'] + '<br/>'; * print 'querys[\'job\']: ' + querys['job'] + '<br/>'; * 对于 GET /test.zl?name=zengl&job=programmer HTTP/1.1 的http请求, * 上面例子显示的结果就是: * querys['name']: zengl * querys['job']: programmer * * 该模块函数会自动将key:value进行url解码,例如: * 对于 GET /v0_1_1/test.zl?%E5%B7%A5%E4%BD%9C=%E7%BC%96%E7%A8%8B HTTP/1.1 的http请求, * 解析后的数组成员为: * 工作: 编程 * 其中%E5%B7%A5%E4%BD%9C解码为UTF8字符串“工作”,%E7%BC%96%E7%A8%8B则解码为UTF8字符串“编程” * * 该模块函数只会在第一次调用时,创建哈希数组,之后再调用该模块函数时,就会直接将之前创建过的数组返回 */ ZL_EXP_VOID module_request_GetQuery(ZL_EXP_VOID * VM_ARG,ZL_EXP_INT argcount) { ZENGL_EXPORT_MOD_FUN_ARG arg = {ZL_EXP_FAT_NONE,{0}}; MAIN_DATA * my_data = zenglApi_GetExtraData(VM_ARG, "my_data"); MY_PARSER_DATA * my_parser_data = my_data->my_parser_data; struct http_parser_url * url_parser = &my_parser_data->url_parser; if(my_data->query_memblock.ptr == ZL_EXP_NULL) { if(zenglApi_CreateMemBlock(VM_ARG,&my_data->query_memblock,0) == -1) { zenglApi_Exit(VM_ARG,zenglApi_GetErrorString(VM_ARG)); } zenglApi_AddMemBlockRefCount(VM_ARG,&my_data->query_memblock,1); // 手动增加该内存块的引用计数值,使其不会在脚本函数返回时,被释放掉。 if((url_parser->field_set & (1 << UF_QUERY)) && (url_parser->field_data[UF_QUERY].len > 0)) { ZL_EXP_CHAR * q = my_parser_data->request_url.str + url_parser->field_data[UF_QUERY].off; ZL_EXP_INT q_len = url_parser->field_data[UF_QUERY].len; ZL_EXP_INT k = -1; ZL_EXP_INT v = -1; ZL_EXP_CHAR * decode_k = ZL_EXP_NULL; ZL_EXP_CHAR * decode_v = ZL_EXP_NULL; for(ZL_EXP_INT i = 0; i <= q_len; i++) { if(k == -1 && q[i] != '=' && q[i] != '&') { k = i; } switch(q[i]) { case '=': v = i + 1; break; case '&': case '#': case STR_NULL: if(k >= 0 && v > 0) { ZL_EXP_CHAR prev_v_char = q[v - 1]; ZL_EXP_CHAR current_char = q[i]; q[i] = q[v - 1] = STR_NULL; if(decode_k == ZL_EXP_NULL) decode_k = zenglApi_AllocMem(VM_ARG, (strlen(&q[k]) + 1)); else decode_k = zenglApi_ReAllocMem(VM_ARG, decode_k, (strlen(&q[k]) + 1)); strcpy(decode_k, &q[k]); if(decode_v == ZL_EXP_NULL) decode_v = zenglApi_AllocMem(VM_ARG, (strlen(&q[v]) + 1)); else decode_v = zenglApi_ReAllocMem(VM_ARG, decode_v, (strlen(&q[v]) + 1)); strcpy(decode_v, &q[v]); arg.type = ZL_EXP_FAT_STR; arg.val.str = url_decode(decode_v); zenglApi_SetMemBlockByHashKey(VM_ARG, &my_data->query_memblock, url_decode(decode_k), &arg); q[v - 1] = prev_v_char; if(current_char != STR_NULL) q[i] = current_char; k = v = -1; } else { k = v = -1; } break; } } if(decode_k != ZL_EXP_NULL) zenglApi_FreeMem(VM_ARG, decode_k); if(decode_v != ZL_EXP_NULL) zenglApi_FreeMem(VM_ARG, decode_v); } zenglApi_SetRetValAsMemBlock(VM_ARG,&my_data->query_memblock); } else { zenglApi_SetRetValAsMemBlock(VM_ARG,&my_data->query_memblock); } } |
/* * module_builtin.c * * Created on: 2017-7-16 * Author: zengl */ #include "module_builtin.h" /** * bltIterArray模块函数,用于对数组成员进行迭代操作 * 例如: * test['name'] = 'zengl'; * test['job'] = 'programmer'; * for(i=0;bltIterArray(test,&i,&k,&v);) * print k +": " + v + '<br/>'; * endfor * 该脚本在浏览器中的输出结果就是(<br/>会被浏览器做换行处理): * name: zengl * job: programmer * * 上面例子中,该模块函数的第一个参数test,是需要迭代的数组, * 第二个参数i是整数类型的变量的引用,用于表示需要访问的成员的索引值, * 该函数会将i索引位置处的名值对读取出来并分别设置到k,v参数中,所以k,v参数必须是引用,才能获取到值, * 如果i对应的成员是NONE类型(没有被赋予任何值)时,模块函数会跳过i,并自动往后去找有效的成员, * 第二个参数i之所以也是引用类型,是因为模块函数在结束时,会将下一次需要访问的索引值赋值给参数i * * 如果数组里的成员没有对应的key的话,第三个参数就会被设置为成员的整数索引值,例如: * test = bltArray('hello', 'world'); * test[6] = "i'm end"; * for(i=0;bltIterArray(test,&i,&k,&v);) * print k +": " + v + '<br/>'; * endfor * 结果就是: * 0: hello * 1: world * 6: i'm end * 上面例子中hello成员的索引值为0,world的索引值为1,"i'm end"成员的索引值为6,模块函数会自动跳过索引值为2,3,4,5的成员, * 因为这些成员并没有被赋予具体的值,其成员类型是NONE类型 * * 可以只设置三个参数,如果只设置三个参数的话,就只会将数组中的值迭代出来,例如: * test['name'] = 'zengl'; * test['job'] = 'programmer'; * for(i=0;bltIterArray(test,&i,&v);) * print v + '<br/>'; * endfor * 结果会是: * zengl * programmer * * 当有成员可以进行迭代时,模块函数会返回整数1,否则返回整数0,因此, * 上面的for循环就可以根据,该模块函数的返回值来判断是否跳出循环,如果返回0,就跳出循环 */ ZL_EXP_VOID module_builtin_iterate_array(ZL_EXP_VOID * VM_ARG,ZL_EXP_INT argcount) { ZENGL_EXPORT_MOD_FUN_ARG arg = {ZL_EXP_FAT_NONE,{0}}; ZL_EXP_BOOL no_index = ZL_EXP_FALSE; if(argcount == 3) no_index = ZL_EXP_TRUE; else if(argcount != 4) zenglApi_Exit(VM_ARG,"usage: bltIterArray(array, &index, &[key|curindex], &value) | bltIterArray(array, &index, &value)"); zenglApi_GetFunArg(VM_ARG,1,&arg); // 如果第一个参数不是数组之类的内存块,则无需迭代,直接返回0 if(arg.type != ZL_EXP_FAT_MEMBLOCK) { zenglApi_SetRetVal(VM_ARG, ZL_EXP_FAT_INT, ZL_EXP_NULL, 0, 0); return; } ZENGL_EXPORT_MEMBLOCK memblock = {0}; memblock = arg.val.memblock; zenglApi_GetFunArgInfo(VM_ARG,2,&arg); switch(arg.type){ case ZL_EXP_FAT_ADDR: case ZL_EXP_FAT_ADDR_LOC: case ZL_EXP_FAT_ADDR_MEMBLK: break; default: zenglApi_Exit(VM_ARG,"second argument of bltIterArray must be address type"); break; } zenglApi_GetFunArg(VM_ARG,2,&arg); if(arg.type != ZL_EXP_FAT_INT) zenglApi_Exit(VM_ARG,"second argument value of bltIterArray must be integer"); ZL_EXP_INT index = (ZL_EXP_INT)arg.val.integer; ZENGL_EXPORT_MOD_FUN_ARG mblk_val = {ZL_EXP_FAT_NONE,{0}}; ZL_EXP_INT size; zenglApi_GetMemBlockInfo(VM_ARG,&memblock,&size, ZL_EXP_NULL); check_index: if(index < 0 || index >= size) { zenglApi_SetRetVal(VM_ARG, ZL_EXP_FAT_INT, ZL_EXP_NULL, 0, 0); return; } mblk_val = zenglApi_GetMemBlock(VM_ARG,&memblock,index + 1); if(mblk_val.type == ZL_EXP_FAT_NONE) { index++; goto check_index; } zenglApi_GetFunArgInfo(VM_ARG,3,&arg); switch(arg.type){ case ZL_EXP_FAT_ADDR: case ZL_EXP_FAT_ADDR_LOC: case ZL_EXP_FAT_ADDR_MEMBLK: break; default: zenglApi_Exit(VM_ARG,"the third argument of bltIterArray must be address type"); break; } ZL_EXP_CHAR * key; if(no_index == ZL_EXP_FALSE) { zenglApi_GetMemBlockHashKey(VM_ARG,&memblock,index,&key); if(key != ZL_EXP_NULL) { arg.type = ZL_EXP_FAT_STR; arg.val.str = key; zenglApi_SetFunArg(VM_ARG,3,&arg); } else { arg.type = ZL_EXP_FAT_INT; arg.val.integer = index; zenglApi_SetFunArg(VM_ARG,3,&arg); } zenglApi_GetFunArgInfo(VM_ARG,4,&arg); switch(arg.type){ case ZL_EXP_FAT_ADDR: case ZL_EXP_FAT_ADDR_LOC: case ZL_EXP_FAT_ADDR_MEMBLK: break; default: zenglApi_Exit(VM_ARG,"the forth argument of bltIterArray must be address type"); break; } zenglApi_SetFunArg(VM_ARG,4,&mblk_val); } else { zenglApi_SetFunArg(VM_ARG,3,&mblk_val); } arg.type = ZL_EXP_FAT_INT; arg.val.integer = index + 1; zenglApi_SetFunArg(VM_ARG,2,&arg); zenglApi_SetRetVal(VM_ARG, ZL_EXP_FAT_INT, ZL_EXP_NULL, 1, 0); } /** * builtin模块的初始化函数,里面设置了与该模块相关的各个模块函数及其相关的处理句柄 */ ZL_EXP_VOID module_builtin_init(ZL_EXP_VOID * VM_ARG,ZL_EXP_INT moduleID) { zenglApi_SetModFunHandle(VM_ARG,moduleID,"bltArray",zenglApiBMF_array); zenglApi_SetModFunHandle(VM_ARG,moduleID,"bltIterArray",module_builtin_iterate_array); } |
use builtin; use request; print '<!Doctype html>'; // 设置utf-8编码,中间的-不能少,ie10不识别utf8,只识别utf-8 print '<html><head><meta http-equiv="content-type" content="text/html;charset=utf-8" /></head><body>'; headers = rqtGetHeaders(); print 'user agent: ' + headers['User-Agent'] + '<br/>'; query_string = rqtGetQueryAsString(); if(query_string) print 'query string: ' + query_string + '<br/>'; querys = rqtGetQuery(); // 通过bltIterArray模块函数来迭代数组成员 for(i=0;bltIterArray(querys,&i,&k,&v);) print k +": " + v + '<br/>'; endfor endif print '<br/>'; test = bltArray('hello', 'world'); test[6] = "i'm end"; for(i=0;bltIterArray(test,&i,&k,&v);) print k +": " + v + '<br/>'; endfor print '</body></html>'; |
user agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0 query string: name=zengl&job=%E7%A8%8B%E5%BA%8F%E5%91%98 name: zengl job: 程序员 0: hello 1: world 6: i'm end |
/* * common_header.h * * Created on: 2017-7-16 * Author: zengl */ #ifndef COMMON_HEADER_H_ #define COMMON_HEADER_H_ #ifndef ZL_EXP_OS_IN_LINUX #define ZL_EXP_OS_IN_LINUX #endif #include "zengl/linux/zengl_exportfuns.h" #endif /* COMMON_HEADER_H_ */ |
/* * module_builtin.h * * Created on: 2017-7-16 * Author: zengl */ #ifndef MODULE_BUILTIN_H_ #define MODULE_BUILTIN_H_ #include "common_header.h" /** * builtin模块的初始化函数,里面设置了与该模块相关的各个模块函数及其相关的处理句柄 */ ZL_EXP_VOID module_builtin_init(ZL_EXP_VOID * VM_ARG,ZL_EXP_INT moduleID); #endif /* MODULE_BUILTIN_H_ */ |