sqmongoose.cpp 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdarg.h>
  5. #include "squirrel.h"
  6. #include "sqstdblobimpl.h"
  7. SQ_OPT_STRING_STRLEN();
  8. #ifdef USE_SQ_SQLITE3
  9. #include "lsqlite3.h"
  10. #endif
  11. #ifdef USE_AXTLS
  12. #ifdef __cplusplus
  13. extern "C" {
  14. #endif
  15. void * SSL_CTX_new(void *);
  16. #ifdef __cplusplus
  17. }
  18. #endif
  19. #endif
  20. #define USE_MG_MD5 1
  21. #include "mongoose.h"
  22. #define PRINT_FILE_LINE printf("%s %d\n", __FILE__,__LINE__);
  23. #ifdef UNUSED
  24. #elif defined(__GNUC__)
  25. # define UNUSED(x) UNUSED_ ## x __attribute__((unused))
  26. #elif defined(__LCLINT__)
  27. # define UNUSED(x) /*@unused@*/ x
  28. #else
  29. # define UNUSED(x) x
  30. #endif
  31. #define MARK() do { \
  32. printf("%s:%d (%s)\n", __FILE__, __LINE__, __FUNCTION__); \
  33. } while (0)
  34. typedef struct SQ_Mg_Context SQ_Mg_Context;
  35. typedef struct SQ_MG_Callback SQ_MG_Callback;
  36. struct SQ_MG_Callback {
  37. char *buf;
  38. size_t len;
  39. size_t size;
  40. const char *name;
  41. };
  42. struct SQ_Mg_Context {
  43. HSQUIRRELVM v;
  44. struct mg_context *ctx;
  45. SQ_MG_Callback master_plugin;
  46. SQ_MG_Callback master_plugin_exit;
  47. SQ_MG_Callback user_callback;
  48. SQ_MG_Callback user_callback_setup;
  49. SQ_MG_Callback user_callback_exit;
  50. };
  51. static const char SQ_MG_CONN_TAG[] = "sq_mg_conn_tag";
  52. static SQRESULT sq_mg_conn_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
  53. {
  54. return 1;
  55. }
  56. static SQRESULT sq_mg_conn_constructor(HSQUIRRELVM v)
  57. {
  58. //SQ_FUNC_VARS_NO_TOP(v);
  59. struct mg_connection *conn = 0;
  60. sq_setinstanceup(v, 1, conn);
  61. sq_setreleasehook(v,1, sq_mg_conn_releasehook);
  62. return 1;
  63. }
  64. #define GET_MG_CONNECION() \
  65. struct mg_connection *conn; \
  66. if((_rc_ = sq_getinstanceup(v,1,(SQUserPointer*)&conn,(void*)SQ_MG_CONN_TAG)) < 0) return _rc_;
  67. static SQRESULT
  68. sq_mg_conn_print(HSQUIRRELVM v)
  69. {
  70. SQ_FUNC_VARS(v);
  71. GET_MG_CONNECION();
  72. SQInteger i, write_count = 0;
  73. for (i = 2; i <= _top_; ++i) {
  74. sq_tostring(v, i);
  75. SQ_GET_STRING(v, -1, value);
  76. write_count += mg_write(conn, value, value_size);
  77. sq_poptop(v);
  78. }
  79. sq_pushinteger(v, write_count);
  80. return 1;
  81. }
  82. #ifdef USE_SQ_LSQLITE3
  83. static SQRESULT
  84. sq_mg_conn_vm_print(HSQUIRRELVM v)
  85. {
  86. GET_MG_CONNECION();
  87. lsqlite3_sdb_vm *svm = (lsqlite3_sdb_vm *)luaL_checkudata(v, 1,
  88. lsqlite3_sqlite_vm_meta);
  89. SQInteger idx = luaL_checkint(v,2);
  90. SQInteger len = sqlite3_column_bytes(svm->vm, idx);
  91. if(len) sq_pushinteger(v, mg_write(conn, sqlite3_column_text(svm->vm, idx), len));
  92. else sq_pushinteger(v, 0);
  93. return 1;
  94. }
  95. #endif
  96. static SQRESULT
  97. sq_mg_conn_write(HSQUIRRELVM v)
  98. {
  99. SQ_FUNC_VARS(v);
  100. GET_MG_CONNECION();
  101. SQ_GET_STRING(v, 2, buf);
  102. SQ_OPT_INTEGER(v, 3, write_size, buf_size);
  103. sq_pushinteger(v, mg_write(conn, buf, write_size));
  104. return 1;
  105. }
  106. static SQRESULT
  107. sq_mg_conn_read(HSQUIRRELVM v)
  108. {
  109. SQ_FUNC_VARS(v);
  110. GET_MG_CONNECION();
  111. SQ_OPT_INTEGER(v, 2, n, 1024*2000);
  112. size_t rlen; /* how much to read */
  113. size_t nr; /* number of chars actually read */
  114. rlen = 8192; /* try to read that much each time */
  115. SQBlob blob(0, rlen);
  116. if (rlen > n) rlen = n; /* cannot read more than asked */
  117. char *p = sq_getscratchpad(v,rlen);
  118. do {
  119. nr = mg_read(conn, p, rlen);
  120. blob.Write(p, nr);
  121. n -= nr; /* still have to read `n' chars */
  122. } while (n > 0 && nr == rlen); /* until end of count or eof */
  123. sq_pushstring(v, (const SQChar *)blob.GetBuf(), blob.Len()); /* close buffer */
  124. return 1;
  125. }
  126. static SQRESULT
  127. sq_mg_conn_send_file(HSQUIRRELVM v)
  128. {
  129. SQ_FUNC_VARS_NO_TOP(v);
  130. GET_MG_CONNECION();
  131. SQ_GET_STRING(v, 2, file_path);
  132. mg_send_file(conn, file_path);
  133. return 0;
  134. }
  135. static SQRESULT
  136. sq_mg_conn_write_blob(HSQUIRRELVM v)
  137. {
  138. SQ_FUNC_VARS_NO_TOP(v);
  139. GET_MG_CONNECION();
  140. SQBlob *blob = NULL;
  141. { if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&blob,(SQUserPointer)SQBlob::SQBlob_TAG)))
  142. return sq_throwerror(v,_SC("invalid type tag")); }
  143. if(!blob || !blob->IsValid())
  144. return sq_throwerror(v,_SC("the blob is invalid"));
  145. sq_pushinteger(v, mg_write(conn, (const SQChar*)blob->GetBuf(), blob->Len()));
  146. return 1;
  147. }
  148. static SQRESULT
  149. sq_mg_conn_get_header(HSQUIRRELVM v)
  150. {
  151. SQ_FUNC_VARS_NO_TOP(v);
  152. GET_MG_CONNECION();
  153. SQ_GET_STRING(v, 2, name);
  154. sq_pushstring(v, mg_get_header(conn, name), -1);
  155. return 1;
  156. }
  157. static SQRESULT
  158. sq_mg_conn_get_cookie(HSQUIRRELVM v)
  159. {
  160. SQ_FUNC_VARS_NO_TOP(v);
  161. GET_MG_CONNECION();
  162. SQ_GET_STRING(v, 2, cookie_name);
  163. const char *start;
  164. int len = mg_find_cookie(conn, cookie_name, &start);
  165. if(len > 0) sq_pushstring(v, start, len);
  166. else sq_pushnull(v);
  167. return 1;
  168. }
  169. static SQRESULT
  170. sq_mg_conn_get_var(HSQUIRRELVM v)
  171. {
  172. SQ_FUNC_VARS_NO_TOP(v);
  173. GET_MG_CONNECION();
  174. SQ_GET_STRING(v, 2, data);
  175. SQ_GET_STRING(v, 3, name);
  176. const char *start;
  177. size_t buffer_len;
  178. int var_len = mg_find_var(data, data_size, name, &start);
  179. if(var_len > 0){
  180. buffer_len = var_len+1;
  181. char *buffer = sq_getscratchpad(v,buffer_len);
  182. if(buffer){
  183. var_len = mg_url_decode(start, var_len, buffer, buffer_len, 1);
  184. sq_pushstring(v, buffer, var_len);
  185. return 1;
  186. }
  187. }
  188. sq_pushnull(v);
  189. return 1;
  190. }
  191. static SQRESULT
  192. sq_mg_conn_handle_cgi_request(HSQUIRRELVM v)
  193. {
  194. SQ_FUNC_VARS_NO_TOP(v);
  195. GET_MG_CONNECION();
  196. SQ_GET_STRING(v, 2, prog);
  197. mg_handle_cgi_request(conn, prog);
  198. return 0;
  199. }
  200. static SQRESULT
  201. sq_mg_conn_get_option(HSQUIRRELVM v)
  202. {
  203. SQ_FUNC_VARS_NO_TOP(v);
  204. GET_MG_CONNECION();
  205. SQ_GET_STRING(v, 2, name);
  206. SQ_Mg_Context *sq_mg_ctx = (SQ_Mg_Context *) mg_get_user_data(conn);
  207. sq_pushstring(v, mg_get_option(sq_mg_ctx->ctx, name), -1);
  208. return 1;
  209. }
  210. #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_mg_conn_##name,nparams,tycheck}
  211. static SQRegFunction mg_conn_methods[] =
  212. {
  213. _DECL_FUNC(constructor, 1, _SC("x")),
  214. _DECL_FUNC(print, -2, _SC("x n|s")),
  215. _DECL_FUNC(read, 2, _SC("xi")),
  216. _DECL_FUNC(write, 3, _SC("xsi")),
  217. _DECL_FUNC(write_blob, -2, _SC("xxi")),
  218. _DECL_FUNC(get_var, 2, _SC("xs")),
  219. _DECL_FUNC(get_cookie, 2, _SC("xs")),
  220. _DECL_FUNC(get_header, 2, _SC("xs")),
  221. _DECL_FUNC(send_file, 2, _SC("xs")),
  222. _DECL_FUNC(handle_cgi_request, 2, _SC("xs")),
  223. _DECL_FUNC(get_option, 2, _SC("xs")),
  224. {0,0}
  225. };
  226. #undef _DECL_FUNC
  227. /***********/
  228. // helper function to extract a single mg_config value from a Lua table
  229. static void
  230. fetchfield(HSQUIRRELVM v, int idx, const char *key, char **value, const char *d)
  231. {
  232. const char *s;
  233. sq_pushstring(v, key, -1);
  234. if(sq_rawget(v, idx) == SQ_OK){
  235. if(sq_gettype(v, -1) != OT_NULL){
  236. sq_tostring(v, -1);
  237. sq_getstring(v, -1, &s);
  238. *value = mg_strdup(s);
  239. sq_pop(v, 2); //retrieved value and converted value
  240. return;
  241. }
  242. }
  243. *value = NULL;
  244. }
  245. // initializes an options string array from a Lua table
  246. static SQRESULT
  247. fetchoptions(HSQUIRRELVM v, int idx, const char **options)
  248. {
  249. struct {
  250. const char *key;
  251. const char *value;
  252. } OPTIONS[] = {
  253. { "cgi_extensions", ".cgi,.pl,.php" },
  254. { "cgi_environment", NULL },
  255. { "put_delete_passwords_file", NULL },
  256. { "cgi_interpreter", NULL },
  257. { "protect_uri", NULL },
  258. { "authentication_domain", "mydomain.com" },
  259. { "ssi_extensions", ".shtml,.shtm" },
  260. { "access_log_file", NULL },
  261. { "ssl_chain_file", NULL },
  262. { "enable_directory_listing", "yes" },
  263. { "error_log_file", NULL },
  264. { "global_passwords_file", NULL },
  265. { "index_files", "index.html,index.htm,index.cgi" },
  266. { "enable_keep_alive", "no" },
  267. { "access_control_list", NULL },
  268. { "max_request_size", "16384" },
  269. { "extra_mime_types", NULL },
  270. { "listening_ports", "8080" },
  271. { "document_root", "." },
  272. { "ssl_certificate", NULL },
  273. { "num_threads", "10" },
  274. { "run_as_user", NULL },
  275. { NULL, NULL }
  276. };
  277. char *value;
  278. int i, j;
  279. if(sq_gettype(v, idx) != OT_TABLE) return sq_throwerror(v, "a table is needed to retrieve options");
  280. for (i = 0, j = 0; OPTIONS[i].key; ++i) {
  281. fetchfield(v, idx, OPTIONS[i].key, &value, OPTIONS[i].value);
  282. if (NULL != value) {
  283. options[j++] = mg_strdup(OPTIONS[i].key);
  284. options[j++] = value;
  285. }
  286. }
  287. options[j] = NULL;
  288. return 0;
  289. }
  290. /***********/
  291. static const char SQ_MONGOOSE_TAG[] = "sq_mongoose_tag";
  292. static SQBool show_errors_on_stdout = SQFalse;
  293. static SQRESULT sq_mongoose_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
  294. {
  295. SQ_Mg_Context *sq_mg_ctx = ( SQ_Mg_Context *)p;
  296. sq_free(sq_mg_ctx, sizeof(SQ_Mg_Context));
  297. return 1;
  298. }
  299. static SQRESULT sq_mongoose_constructor(HSQUIRRELVM v)
  300. {
  301. //SQ_FUNC_VARS_NO_TOP(v);
  302. SQ_Mg_Context *sq_mg_ctx = (SQ_Mg_Context *)sq_malloc(sizeof(SQ_Mg_Context));
  303. memset(sq_mg_ctx, 0, sizeof(SQ_Mg_Context));
  304. sq_setinstanceup(v, 1, sq_mg_ctx);
  305. sq_setreleasehook(v,1, sq_mongoose_releasehook);
  306. return 1;
  307. }
  308. #define GET_mongoose_INSTANCE() \
  309. SQ_Mg_Context *self; \
  310. if((_rc_ = sq_getinstanceup(v,1,(SQUserPointer*)&self,(void*)SQ_MONGOOSE_TAG)) < 0) return _rc_;
  311. static SQRESULT
  312. sq_mongoose_show_errors_on_stdout(HSQUIRRELVM v)
  313. {
  314. SQ_FUNC_VARS_NO_TOP(v);
  315. SQ_GET_BOOL(v, 2, onOff);
  316. show_errors_on_stdout = onOff;
  317. return 0;
  318. }
  319. static SQRESULT
  320. sq_mongoose_modify_passwords_file(HSQUIRRELVM v)
  321. {
  322. SQ_FUNC_VARS_NO_TOP(v);
  323. SQ_GET_STRING(v, 2, passwords_file_name);
  324. SQ_GET_STRING(v, 3, domain);
  325. SQ_GET_STRING(v, 4, user);
  326. SQ_GET_STRING(v, 5, password);
  327. sq_pushinteger(v, mg_modify_passwords_file(passwords_file_name,
  328. domain, user, password));
  329. return 1;
  330. }
  331. static SQRESULT
  332. sq_mongoose_version(HSQUIRRELVM v)
  333. {
  334. sq_pushstring(v, mg_version(), -1);
  335. return 1;
  336. }
  337. SQInteger blob_write(SQUserPointer file,SQUserPointer p,SQInteger size);
  338. // creates a reference dispatching callbacks to squirrel functions
  339. static SQRESULT
  340. fetchcallback(HSQUIRRELVM v, const char *key, SQ_MG_Callback *dump)
  341. {
  342. if(sq_gettype(v, -1) != OT_TABLE) return sq_throwerror(v, "table expected to fetch callbacks");
  343. sq_pushstring(v, key, -1);
  344. sq_rawget(v, -2);
  345. dump->buf = NULL;
  346. dump->len = 0;
  347. dump->size = 0;
  348. dump->name = key;
  349. if (sq_gettype(v, -1) == OT_CLOSURE){
  350. SQBlob b(0, 8192);
  351. if (sq_writeclosure(v, blob_write, &b) != 0)
  352. return sq_throwerror(v, "unable to dump given function");
  353. dump->buf = (char*)sq_malloc(b.Len());
  354. if(dump->buf) {
  355. dump->len = b.Len();
  356. memcpy(dump->buf, b.GetBuf(), dump->len);
  357. }
  358. }
  359. sq_pop(v, 1);
  360. return 1;
  361. }
  362. static void *
  363. user_callback_proxy(enum mg_event event,
  364. struct mg_connection *conn,
  365. const struct mg_request_info *ri);
  366. // creates a new server using a configuration table
  367. static SQRESULT
  368. sq_mongoose_start(HSQUIRRELVM v)
  369. {
  370. SQ_FUNC_VARS_NO_TOP(v);
  371. GET_mongoose_INSTANCE();
  372. _rc_ = 1; //assumes succeed
  373. const char *options[64];
  374. SQInteger i;
  375. if(self->ctx) return sq_throwerror(v, _SC("mongoose already running or stoped incorrectly"));
  376. // store the Lua state for use in callback proxies
  377. self->v = v;
  378. // prepare the mg_config structure from the squirrel table argument
  379. memset(options, 0, sizeof (options));
  380. fetchoptions(v, 2, options);
  381. fetchcallback(v, "master_plugin", &self->master_plugin);
  382. fetchcallback(v, "master_plugin_exit", &self->master_plugin_exit);
  383. fetchcallback(v, "user_callback", &self->user_callback);
  384. fetchcallback(v, "user_callback_setup", &self->user_callback_setup);
  385. fetchcallback(v, "user_callback_exit", &self->user_callback_exit);
  386. self->ctx = mg_start(user_callback_proxy, self, options);
  387. // free the options string list memory
  388. for (i = 0; options[i]; ++i)
  389. free((void *) options[i]);
  390. // throw an error if the server did not start
  391. if (self->ctx == NULL) {
  392. _rc_ = sq_throwerror(v, "could not start mongoose");
  393. }
  394. // return the context so it can be stopped later
  395. return _rc_;
  396. }
  397. static SQRESULT
  398. sq_mongoose_stop(HSQUIRRELVM v)
  399. {
  400. SQ_FUNC_VARS_NO_TOP(v);
  401. GET_mongoose_INSTANCE();
  402. if(self->ctx){
  403. mg_stop(self->ctx);
  404. if(self->user_callback.buf) {
  405. sq_free(self->user_callback.buf, self->user_callback.size);
  406. self->user_callback.buf = NULL;
  407. }
  408. self->ctx = 0;
  409. }
  410. return 0;
  411. }
  412. #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_mongoose_##name,nparams,tycheck}
  413. static SQRegFunction sq_mongoose_methods[] =
  414. {
  415. _DECL_FUNC(constructor, 1, _SC("x")),
  416. _DECL_FUNC(start, -1, _SC("x")),
  417. _DECL_FUNC(stop, 1, _SC("x")),
  418. _DECL_FUNC(modify_passwords_file, 1, _SC("x")),
  419. _DECL_FUNC(version, 1, _SC("x")),
  420. _DECL_FUNC(show_errors_on_stdout, 2, _SC("xb")),
  421. {0,0}
  422. };
  423. #undef _DECL_FUNC
  424. static SQRESULT
  425. sq_mg_url_decode_base(HSQUIRRELVM v, SQInteger is_form_url_encoded)
  426. {
  427. SQ_FUNC_VARS_NO_TOP(v);
  428. GET_MG_CONNECION();
  429. SQ_GET_STRING(v, 2, src);
  430. int dst_len = src_size +1;
  431. char *dst = sq_getscratchpad(v,dst_len);
  432. dst_len = mg_url_decode(src, src_size, dst, dst_len, is_form_url_encoded);
  433. sq_pushstring(v, dst, dst_len);
  434. return 1;
  435. }
  436. static SQRESULT
  437. sq_mg_url_decode(HSQUIRRELVM v)
  438. {
  439. return sq_mg_url_decode_base(v, 1);
  440. }
  441. static SQRESULT
  442. sq_mg_uri_decode(HSQUIRRELVM v)
  443. {
  444. return sq_mg_url_decode_base(v, 0);
  445. }
  446. static SQRESULT
  447. sq_mg_url_encode(HSQUIRRELVM v)
  448. {
  449. SQ_FUNC_VARS_NO_TOP(v);
  450. GET_MG_CONNECION();
  451. SQ_GET_STRING(v, 2, src);
  452. char *dst = mg_url_encode(src);
  453. sq_pushstring(v, dst, -1);
  454. free(dst);
  455. return 1;
  456. }
  457. static SQRESULT
  458. sq_mg_md5(HSQUIRRELVM v)
  459. {
  460. SQ_FUNC_VARS(v);
  461. char buf[32 + 1];
  462. unsigned char hash[16];
  463. MD5_CTX ctx;
  464. MD5Init(&ctx);
  465. for (int i = 2; i <= _top_; ++i) {
  466. SQ_GET_STRING(v, i, p);
  467. MD5Update(&ctx, (const unsigned char *) p, p_size);
  468. }
  469. MD5Final(hash, &ctx);
  470. mg_bin2str(buf, hash, sizeof(hash));
  471. sq_pushstring(v, buf, -1);
  472. return 1;
  473. }
  474. static SQRESULT
  475. sq_mg_debug_print(HSQUIRRELVM v)
  476. {
  477. SQ_FUNC_VARS(v);
  478. GET_MG_CONNECION();
  479. SQInteger i, write_count = 0;
  480. for (i = 2; i <= _top_; ++i) {
  481. sq_tostring(v, i);
  482. SQ_GET_STRING(v, -1, value);
  483. write_count += fwrite(value, 1, value_size, stderr);
  484. sq_poptop(v);
  485. }
  486. sq_pushinteger(v, write_count);
  487. return 1;
  488. }
  489. #ifdef JNI_ENABLE_LOG
  490. #include <android/log.h>
  491. /*
  492. ** A callback for the android_log() SQIntegererface.
  493. */
  494. static void jniLog(int iErrCode, const char *zMsg){
  495. __android_log_print(ANDROID_LOG_ERROR,"jniLuaServerLog","(%d) %s\n", iErrCode, zMsg);
  496. }
  497. static SQRESULT sq_mg_jniLog(HSQUIRRELVM v)
  498. {
  499. SQ_FUNC_VARS_NO_TOP(v);
  500. SQ_GET_INTEGER(v, 2, code);
  501. SQ_GET_STRING(v, 3, error_message);
  502. jniLog(code, error_message);
  503. return 0;
  504. }
  505. #endif
  506. #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_mg_##name,nparams,tycheck}
  507. static SQRegFunction sq_mg_methods[] =
  508. {
  509. _DECL_FUNC(url_decode, 2, _SC(".s")),
  510. _DECL_FUNC(uri_decode, 2, _SC(".s")),
  511. _DECL_FUNC(url_encode, 2, _SC(".s")),
  512. _DECL_FUNC(md5, -2, _SC("xs")),
  513. #ifdef JNI_ENABLE_LOG
  514. _DECL_FUNC(jniLog, -2, _SC("xs")),
  515. #endif
  516. _DECL_FUNC(debug_print, -2, _SC("xs")),
  517. {0,0}
  518. };
  519. #undef _DECL_FUNC
  520. static void reg_string(HSQUIRRELVM v, const char *name, const char *val) {
  521. sq_pushstring(v, name, -1);
  522. if(val) sq_pushstring(v, val, -1);
  523. else sq_pushnull(v);
  524. sq_rawset(v, -3);
  525. }
  526. static void reg_integer(HSQUIRRELVM v, const char *name, int val) {
  527. sq_pushstring(v, name, -1);
  528. sq_pushinteger(v, val);
  529. sq_rawset(v, -3);
  530. }
  531. // pushes request info on the Lua stack as a table
  532. static void
  533. push_request(HSQUIRRELVM v, const struct mg_request_info *ri)
  534. {
  535. int i;
  536. sq_newtable(v);
  537. #define NEWSLOT_STR(ks) reg_string(v, #ks, ri->ks);
  538. NEWSLOT_STR(request_method);
  539. NEWSLOT_STR(uri);
  540. NEWSLOT_STR(http_version);
  541. NEWSLOT_STR(query_string);
  542. NEWSLOT_STR(remote_user);
  543. NEWSLOT_STR(log_message);
  544. #define NEWSLOT_INT(ks) reg_integer(v, #ks, ri->ks);
  545. NEWSLOT_INT(remote_ip);
  546. NEWSLOT_INT(remote_port);
  547. NEWSLOT_INT(status_code);
  548. NEWSLOT_INT(is_ssl);
  549. #undef NEWSLOT_STR
  550. #undef NEWSLOT_INT
  551. sq_pushliteral(v, "http_headers");
  552. sq_newtable(v);
  553. for (i = 0; i < ri->num_headers; ++i) {
  554. reg_string(v, ri->http_headers[i].name, ri->http_headers[i].value);
  555. }
  556. sq_newslot(v, -3, SQFalse);
  557. }
  558. static int copy_array(HSQUIRRELVM dst, HSQUIRRELVM src, int i, int top){
  559. }
  560. static int copy_table(HSQUIRRELVM dst, HSQUIRRELVM src, int i, int top){
  561. }
  562. /*
  563. ** Copies values from State src to State dst.
  564. */
  565. static int copy_values (HSQUIRRELVM dst, HSQUIRRELVM src, int i, int top) {
  566. int _rc_;
  567. sq_reservestack(dst, top - i + 1);
  568. for (; i <= top; i++) {
  569. switch (sq_gettype(src, i)) {
  570. case OT_INTEGER:
  571. SQ_GET_INTEGER(src, i, vint);
  572. sq_pushinteger(dst, vint);
  573. break;
  574. case OT_FLOAT:
  575. SQ_GET_FLOAT(src, i, vfloat);
  576. sq_pushfloat (dst, vfloat);
  577. break;
  578. case OT_BOOL:
  579. SQ_GET_BOOL(src, i, vbool);
  580. sq_pushbool (dst, vbool);
  581. break;
  582. case OT_STRING: {
  583. SQ_GET_STRING(src, i, vstr)
  584. sq_pushstring (dst, vstr, vstr_size);
  585. break;
  586. }
  587. case OT_ARRAY:{
  588. SQInteger size = sq_getsize(src, i);
  589. sq_newarray(dst, size);
  590. copy_array(dst, src, i, top);
  591. }
  592. break;
  593. case OT_TABLE:{
  594. sq_newtable(dst);
  595. copy_table(dst, src, i, top);
  596. }
  597. break;
  598. case OT_USERPOINTER: {
  599. SQUserPointer ptr;
  600. sq_getuserpointer(src, i, &ptr);
  601. sq_pushuserpointer(dst, ptr);
  602. break;
  603. }
  604. case OT_NULL:
  605. default:
  606. sq_pushnull(dst);
  607. break;
  608. }
  609. }
  610. }
  611. static SQInteger
  612. sq_mg_pcall_master_plugin(HSQUIRRELVM v)
  613. {
  614. #if 0
  615. SQ_FUNC_VARS_NO_TOP(v);
  616. GET_MG_CONNECION();
  617. SQ_GET_STRING(v, 2, func_name);
  618. const SQChar *error_message = _SC("No master plugin installed !");
  619. HSQUIRRELVM master_plugin = (HSQUIRRELVM) mg_lock_master_plugin(conn);
  620. if(master_plugin){
  621. int master_plugin_saved_top = sq_gettop(master_plugin);
  622. //sq_pushcfunction(master_plugin, traceback); /* push traceback function */
  623. //int error_func = sq_gettop(master_plugin);
  624. sq_pushstring(master_plugin, func_name, func_name_size);
  625. sq_getonroottable(master_plugin);
  626. if(sq_gettype(master_plugin, -1) == OT_CLOSURE){
  627. sq_pushroottable(master_plugin);
  628. int arg_top = sq_gettop (v);
  629. /* Push arguments to dst stack */
  630. int idx = 4;
  631. copy_values (master_plugin, v, idx, arg_top);
  632. if (sq_pcall (master_plugin, arg_top-idx+1, SQTrue, SQTrue) == SQ_OK) {
  633. /* run OK? */
  634. int ret_top = sq_gettop (master_plugin);
  635. /* Push status = OK */
  636. sq_pushbool (v, SQTrue);
  637. /* Return values to src */
  638. copy_values (v, master_plugin, master_plugin_saved_top+2, ret_top);
  639. /* pops debug.traceback and result from dst state */
  640. sq_settop(master_plugin, master_plugin_saved_top);
  641. /*unlock master plugin*/
  642. mg_unlock_master_plugin(conn);
  643. /* Return true (success) plus return values */
  644. return 1;
  645. }
  646. error_message = sq_tostring (master_plugin, -1);
  647. } else error_message = "Attempt to call an invalid function on master plugin !";
  648. /* pops debug.traceback and result from dst state */
  649. sq_settop(master_plugin, master_plugin_saved_top);
  650. /*unlock master plugin*/
  651. mg_unlock_master_plugin(conn);
  652. }
  653. return sq_throwerror(v, error_message);
  654. #endif
  655. }
  656. static void write_error_message(struct mg_connection *conn,
  657. const char * error_msg, SQInteger error_len){
  658. #define PRE_TAG_OPEN "<pre>"
  659. #define PRE_TAG_CLOSE "</pre>"
  660. mg_write(conn, PRE_TAG_OPEN, sizeof(PRE_TAG_OPEN));
  661. mg_write(conn, error_msg, error_len);
  662. mg_write(conn, PRE_TAG_CLOSE, sizeof(PRE_TAG_CLOSE));
  663. }
  664. #ifdef __cplusplus
  665. extern "C" {
  666. #endif
  667. SQUIRREL_API SQRESULT sqstd_register_SQLite3(HSQUIRRELVM v);
  668. SQUIRREL_API SQRESULT sqstd_register_base64(HSQUIRRELVM v);
  669. SQUIRREL_API SQRESULT sq_register_mix(HSQUIRRELVM v);
  670. SQUIRREL_API SQRESULT sqstd_register_bloblib(HSQUIRRELVM v);
  671. SQUIRREL_API SQRESULT sqstd_register_iolib(HSQUIRRELVM v);
  672. SQUIRREL_API SQInteger sqstd_register_systemlib(HSQUIRRELVM v);
  673. SQUIRREL_API SQRESULT sqstd_register_mathlib(HSQUIRRELVM v);
  674. SQUIRREL_API SQRESULT sqstd_register_stringlib(HSQUIRRELVM v);
  675. SQUIRREL_API SQRESULT sqstd_register_Sq_Fpdf(HSQUIRRELVM v);
  676. //SQUIRREL_API SQRESULT sqopen_lfs(HSQUIRRELVM v);
  677. SQUIRREL_API void sqstd_seterrorhandlers(HSQUIRRELVM v);
  678. SQUIRREL_API void sqstd_printcallstack(HSQUIRRELVM v);
  679. #ifdef __cplusplus
  680. } /*extern "C"*/
  681. #endif
  682. void sq_printfunc(HSQUIRRELVM v,const SQChar *s,...)
  683. {
  684. va_list vl;
  685. va_start(vl, s);
  686. vfprintf(stdout, s, vl);
  687. va_end(vl);
  688. }
  689. void sq_errorfunc(HSQUIRRELVM v,const SQChar *s,...)
  690. {
  691. va_list vl;
  692. va_start(vl, s);
  693. vfprintf(stderr, s, vl);
  694. va_end(vl);
  695. }
  696. static HSQUIRRELVM my_new_squirrel(struct mg_context *ctx) {
  697. HSQUIRRELVM v = sq_open(1024);
  698. if(!v) return 0;
  699. sq_pushroottable(v);
  700. sqstd_register_bloblib(v);
  701. sqstd_register_iolib(v);
  702. sqstd_register_systemlib(v);
  703. sqstd_register_mathlib(v);
  704. sqstd_register_stringlib(v);
  705. sqstd_register_base64(v);
  706. sqstd_register_Sq_Fpdf(v);
  707. sqstd_register_SQLite3(v);
  708. sq_register_mix(v);
  709. sqstd_seterrorhandlers(v); //registers the default error handlers
  710. sq_setprintfunc(v, sq_printfunc, sq_errorfunc); //sets the print function
  711. sq_pushliteral(v,_SC("mg_connection"));
  712. sq_newclass(v,SQFalse);
  713. sq_settypetag(v,-1,(void*)SQ_MG_CONN_TAG);
  714. sq_insert_reg_funcs(v, mg_conn_methods);
  715. sq_newslot(v,-3,SQTrue);
  716. sq_insert_reg_funcs(v, sq_mg_methods);
  717. sq_pushliteral(v, "APP_ROOT_FOLDER");
  718. sq_pushstring(v, mg_get_option(ctx, "document_root"), -1);
  719. sq_newslot(v, -3, SQFalse);
  720. sq_poptop(v); //remove roottable
  721. return v;
  722. }
  723. // dispatches a callback to a Lua function if one is registered
  724. static void *
  725. user_callback_proxy(enum mg_event event,
  726. struct mg_connection *conn,
  727. const struct mg_request_info *ri)
  728. {
  729. HSQUIRRELVM v;
  730. int e;
  731. switch(event){
  732. case MG_NEW_MASTER_PLUGIN: {
  733. SQ_Mg_Context *sq_mg_ctx = (SQ_Mg_Context *) conn;
  734. SQ_MG_Callback *dump = &sq_mg_ctx->master_plugin;
  735. v = my_new_squirrel((struct mg_context *)ri);
  736. if(!v) return 0;
  737. if(dump->buf){
  738. if (sq_compilebuffer(v, dump->buf, dump->len, dump->name, SQFalse) == SQ_OK) {
  739. sq_pushroottable(v);
  740. if(sq_call(v, 1, SQFalse, SQTrue) != SQ_OK){
  741. sq_errorfunc(v, "sq_call failed %d\n%s", __LINE__, sq_getlasterror_str(v));
  742. }
  743. sq_poptop(v); //remove function from stack
  744. }
  745. }
  746. return v;
  747. }
  748. break;
  749. case MG_FREE_MASTER_PLUGIN:
  750. v = (HSQUIRRELVM)conn;
  751. if(v) {
  752. SQ_Mg_Context *sq_mg_ctx = (SQ_Mg_Context *) ri;
  753. SQ_MG_Callback *dump = &sq_mg_ctx->master_plugin_exit;
  754. if(dump->buf){
  755. if (sq_compilebuffer(v, dump->buf, dump->len, dump->name, SQFalse) == SQ_OK) {
  756. sq_pushroottable(v);
  757. if(sq_call(v, 1, SQFalse, SQTrue) != SQ_OK){
  758. sq_errorfunc(v, "sq_call failed %d\n%s", __LINE__, sq_getlasterror_str(v));
  759. }
  760. sq_poptop(v); //remove function from stack
  761. }
  762. }
  763. sq_close(v);
  764. }
  765. return 0;
  766. break;
  767. case MG_NEW_PLUGIN:{
  768. SQ_Mg_Context *sq_mg_ctx = (SQ_Mg_Context *) mg_get_user_data(conn);
  769. if(!sq_mg_ctx) return 0;
  770. SQ_MG_Callback *dump = &sq_mg_ctx->user_callback;
  771. if (dump->buf) {
  772. v = my_new_squirrel((struct mg_context *)ri);
  773. if(!v) return 0;
  774. sq_pushroottable(v);
  775. sq_pushregistrytable(v);
  776. sq_pushstring(v, SQ_MG_CONN_TAG,-1);
  777. int rc = sq_rawget(v, -2);
  778. sq_remove(v, -2); //remove registrytable
  779. sq_pushroottable(v);
  780. rc = sq_call(v, 1, SQTrue, SQFalse);
  781. if(rc == SQ_ERROR) {
  782. printf("%d %s\n", __LINE__, sq_getlasterror_str(v));
  783. return 0;
  784. }
  785. sq_remove(v, -2); //class
  786. rc = sq_getinstanceup(v, -1, (void**)sq_mg_ctx, (void*)SQ_MG_CONN_TAG);
  787. //_g_io_dostring(v, dump->buf, dump->len, dump->name);
  788. //sq_setglobal(v, "__manage_conn___");
  789. dump = &sq_mg_ctx->user_callback_setup;
  790. if(dump->buf){
  791. if (sq_compilebuffer(v, dump->buf, dump->len, dump->name, SQFalse) == SQ_OK) {
  792. sq_pushroottable(v);
  793. if(sq_call(v, 1, SQFalse, SQTrue) != SQ_OK){
  794. sq_errorfunc(v, "sq_call failed %d\n%s", __LINE__, sq_getlasterror_str(v));
  795. }
  796. sq_poptop(v); //remove function from stack
  797. }
  798. }
  799. sq_poptop(v); //remove root table
  800. return v;
  801. }
  802. }
  803. return 0;
  804. case MG_FREE_PLUGIN:
  805. v = (HSQUIRRELVM)mg_get_plugin(conn);
  806. if(v){
  807. SQ_Mg_Context *sq_mg_ctx = (SQ_Mg_Context *) ri;
  808. if(sq_mg_ctx){
  809. SQ_MG_Callback *dump = &sq_mg_ctx->user_callback_exit;
  810. if(dump->buf){
  811. if (sq_compilebuffer(v, dump->buf, dump->len, dump->name, SQFalse) == SQ_OK) {
  812. sq_pushroottable(v);
  813. if(sq_call(v, 1, SQFalse, SQTrue) != SQ_OK){
  814. sq_errorfunc(v, "sq_call failed %d\n%s", __LINE__, sq_getlasterror_str(v));
  815. }
  816. sq_poptop(v); //remove function from stack
  817. }
  818. }
  819. }
  820. sq_close(v);
  821. }
  822. return NULL;
  823. case MG_INIT_SSL:
  824. #ifdef USE_AXTLS
  825. //lua_pushstring(L, "MG_INIT_SSL");
  826. *((void**)conn) = SSL_CTX_new(0);
  827. return 0;
  828. #endif
  829. case MG_NEW_REQUEST:
  830. case MG_HTTP_ERROR:
  831. case MG_EVENT_LOG:{
  832. v = (HSQUIRRELVM) mg_get_plugin(conn);
  833. if (v) {
  834. SQInteger saved_top = sq_gettop(v);
  835. if(sq_gettype(v,-1) != OT_CLOSURE) {
  836. const char *error_msg = "SquiLu interpreter lost manage_conn";
  837. write_error_message(conn, error_msg, sizeof(error_msg));
  838. };
  839. switch (event) {
  840. case MG_NEW_REQUEST: sq_pushliteral(v, "MG_NEW_REQUEST"); break;
  841. case MG_HTTP_ERROR: sq_pushliteral(v, "MG_HTTP_ERROR"); break;
  842. case MG_EVENT_LOG: sq_pushliteral(v, "MG_EVENT_LOG"); break;
  843. case MG_INIT_SSL: sq_pushliteral(v, "MG_INIT_SSL"); break;
  844. default: sq_pushnull(v); break;
  845. }
  846. sq_pushroottable(v);
  847. push_request(v, ri);
  848. // sq_call(v, 2, 1);
  849. // e = sq_toboolean(v, -1) ? 1 : 0;
  850. if(sq_call(v, 2, SQTrue, SQFalse) != SQ_OK) {
  851. sq_getlasterror(v);
  852. const SQChar *error_msg;
  853. sq_getstring(v, -1, &error_msg);
  854. //printf("%s\n", error_msg);
  855. write_error_message(conn, error_msg, sq_getsize(v, -1));
  856. e = 0;
  857. } else {
  858. SQBool bval;
  859. if(sq_getbool(v, -1, &bval) == SQ_OK) e = bval == SQTrue ? 1 : 0;
  860. else e = 0;
  861. }
  862. sq_settop(v, saved_top);
  863. return (void *) e;
  864. }
  865. }
  866. default:
  867. return NULL;
  868. }
  869. return NULL;
  870. }
  871. #ifdef __cplusplus
  872. extern "C" {
  873. #endif
  874. SQRESULT sqstd_register_mongoose(HSQUIRRELVM v)
  875. {
  876. sq_insert_reg_funcs(v, sq_mg_methods);
  877. sq_pushliteral(v,_SC("mongoose"));
  878. sq_newclass(v,SQFalse);
  879. sq_settypetag(v,-1,(void*)SQ_MONGOOSE_TAG);
  880. sq_insert_reg_funcs(v, sq_mongoose_methods);
  881. sq_newslot(v,-3,SQTrue);
  882. return 1;
  883. }
  884. #ifdef __cplusplus
  885. }
  886. #endif