ngx_http_script.c 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901
  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */
  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_http.h>
  8. static ngx_int_t ngx_http_script_init_arrays(ngx_http_script_compile_t *sc);
  9. static ngx_int_t ngx_http_script_done(ngx_http_script_compile_t *sc);
  10. static ngx_int_t ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc,
  11. ngx_str_t *value, ngx_uint_t last);
  12. static ngx_int_t ngx_http_script_add_var_code(ngx_http_script_compile_t *sc,
  13. ngx_str_t *name);
  14. static ngx_int_t ngx_http_script_add_args_code(ngx_http_script_compile_t *sc);
  15. #if (NGX_PCRE)
  16. static ngx_int_t ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc,
  17. ngx_uint_t n);
  18. #endif
  19. static ngx_int_t
  20. ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc);
  21. static size_t ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e);
  22. static void ngx_http_script_full_name_code(ngx_http_script_engine_t *e);
  23. #define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code
  24. static uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL;
  25. void
  26. ngx_http_script_flush_complex_value(ngx_http_request_t *r,
  27. ngx_http_complex_value_t *val)
  28. {
  29. ngx_uint_t *index;
  30. index = val->flushes;
  31. if (index) {
  32. while (*index != (ngx_uint_t) -1) {
  33. if (r->variables[*index].no_cacheable) {
  34. r->variables[*index].valid = 0;
  35. r->variables[*index].not_found = 0;
  36. }
  37. index++;
  38. }
  39. }
  40. }
  41. ngx_int_t
  42. ngx_http_complex_value(ngx_http_request_t *r, ngx_http_complex_value_t *val,
  43. ngx_str_t *value)
  44. {
  45. size_t len;
  46. ngx_http_script_code_pt code;
  47. ngx_http_script_len_code_pt lcode;
  48. ngx_http_script_engine_t e;
  49. if (val->lengths == NULL) {
  50. *value = val->value;
  51. return NGX_OK;
  52. }
  53. ngx_http_script_flush_complex_value(r, val);
  54. ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
  55. e.ip = val->lengths;
  56. e.request = r;
  57. e.flushed = 1;
  58. len = 0;
  59. while (*(uintptr_t *) e.ip) {
  60. lcode = *(ngx_http_script_len_code_pt *) e.ip;
  61. len += lcode(&e);
  62. }
  63. value->len = len;
  64. value->data = ngx_pnalloc(r->pool, len);
  65. if (value->data == NULL) {
  66. return NGX_ERROR;
  67. }
  68. e.ip = val->values;
  69. e.pos = value->data;
  70. e.buf = *value;
  71. while (*(uintptr_t *) e.ip) {
  72. code = *(ngx_http_script_code_pt *) e.ip;
  73. code((ngx_http_script_engine_t *) &e);
  74. }
  75. *value = e.buf;
  76. return NGX_OK;
  77. }
  78. size_t
  79. ngx_http_complex_value_size(ngx_http_request_t *r,
  80. ngx_http_complex_value_t *val, size_t default_value)
  81. {
  82. size_t size;
  83. ngx_str_t value;
  84. if (val == NULL) {
  85. return default_value;
  86. }
  87. if (val->lengths == NULL) {
  88. return val->u.size;
  89. }
  90. if (ngx_http_complex_value(r, val, &value) != NGX_OK) {
  91. return default_value;
  92. }
  93. size = ngx_parse_size(&value);
  94. if (size == (size_t) NGX_ERROR) {
  95. ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  96. "invalid size \"%V\"", &value);
  97. return default_value;
  98. }
  99. return size;
  100. }
  101. ngx_int_t
  102. ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv)
  103. {
  104. ngx_str_t *v;
  105. ngx_uint_t i, n, nv, nc;
  106. ngx_array_t flushes, lengths, values, *pf, *pl, *pv;
  107. ngx_http_script_compile_t sc;
  108. v = ccv->value;
  109. nv = 0;
  110. nc = 0;
  111. for (i = 0; i < v->len; i++) {
  112. if (v->data[i] == '$') {
  113. if (v->data[i + 1] >= '1' && v->data[i + 1] <= '9') {
  114. nc++;
  115. } else {
  116. nv++;
  117. }
  118. }
  119. }
  120. if ((v->len == 0 || v->data[0] != '$')
  121. && (ccv->conf_prefix || ccv->root_prefix))
  122. {
  123. if (ngx_conf_full_name(ccv->cf->cycle, v, ccv->conf_prefix) != NGX_OK) {
  124. return NGX_ERROR;
  125. }
  126. ccv->conf_prefix = 0;
  127. ccv->root_prefix = 0;
  128. }
  129. ccv->complex_value->value = *v;
  130. ccv->complex_value->flushes = NULL;
  131. ccv->complex_value->lengths = NULL;
  132. ccv->complex_value->values = NULL;
  133. if (nv == 0 && nc == 0) {
  134. return NGX_OK;
  135. }
  136. n = nv + 1;
  137. if (ngx_array_init(&flushes, ccv->cf->pool, n, sizeof(ngx_uint_t))
  138. != NGX_OK)
  139. {
  140. return NGX_ERROR;
  141. }
  142. n = nv * (2 * sizeof(ngx_http_script_copy_code_t)
  143. + sizeof(ngx_http_script_var_code_t))
  144. + sizeof(uintptr_t);
  145. if (ngx_array_init(&lengths, ccv->cf->pool, n, 1) != NGX_OK) {
  146. return NGX_ERROR;
  147. }
  148. n = (nv * (2 * sizeof(ngx_http_script_copy_code_t)
  149. + sizeof(ngx_http_script_var_code_t))
  150. + sizeof(uintptr_t)
  151. + v->len
  152. + sizeof(uintptr_t) - 1)
  153. & ~(sizeof(uintptr_t) - 1);
  154. if (ngx_array_init(&values, ccv->cf->pool, n, 1) != NGX_OK) {
  155. return NGX_ERROR;
  156. }
  157. pf = &flushes;
  158. pl = &lengths;
  159. pv = &values;
  160. ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
  161. sc.cf = ccv->cf;
  162. sc.source = v;
  163. sc.flushes = &pf;
  164. sc.lengths = &pl;
  165. sc.values = &pv;
  166. sc.complete_lengths = 1;
  167. sc.complete_values = 1;
  168. sc.zero = ccv->zero;
  169. sc.conf_prefix = ccv->conf_prefix;
  170. sc.root_prefix = ccv->root_prefix;
  171. if (ngx_http_script_compile(&sc) != NGX_OK) {
  172. return NGX_ERROR;
  173. }
  174. if (flushes.nelts) {
  175. ccv->complex_value->flushes = flushes.elts;
  176. ccv->complex_value->flushes[flushes.nelts] = (ngx_uint_t) -1;
  177. }
  178. ccv->complex_value->lengths = lengths.elts;
  179. ccv->complex_value->values = values.elts;
  180. return NGX_OK;
  181. }
  182. char *
  183. ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  184. {
  185. char *p = conf;
  186. ngx_str_t *value;
  187. ngx_http_complex_value_t **cv;
  188. ngx_http_compile_complex_value_t ccv;
  189. cv = (ngx_http_complex_value_t **) (p + cmd->offset);
  190. if (*cv != NGX_CONF_UNSET_PTR && *cv != NULL) {
  191. return "is duplicate";
  192. }
  193. *cv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
  194. if (*cv == NULL) {
  195. return NGX_CONF_ERROR;
  196. }
  197. value = cf->args->elts;
  198. ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
  199. ccv.cf = cf;
  200. ccv.value = &value[1];
  201. ccv.complex_value = *cv;
  202. if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
  203. return NGX_CONF_ERROR;
  204. }
  205. return NGX_CONF_OK;
  206. }
  207. char *
  208. ngx_http_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd,
  209. void *conf)
  210. {
  211. char *p = conf;
  212. ngx_str_t *value;
  213. ngx_http_complex_value_t **cv;
  214. ngx_http_compile_complex_value_t ccv;
  215. cv = (ngx_http_complex_value_t **) (p + cmd->offset);
  216. if (*cv != NGX_CONF_UNSET_PTR) {
  217. return "is duplicate";
  218. }
  219. *cv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
  220. if (*cv == NULL) {
  221. return NGX_CONF_ERROR;
  222. }
  223. value = cf->args->elts;
  224. ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
  225. ccv.cf = cf;
  226. ccv.value = &value[1];
  227. ccv.complex_value = *cv;
  228. ccv.zero = 1;
  229. if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
  230. return NGX_CONF_ERROR;
  231. }
  232. return NGX_CONF_OK;
  233. }
  234. char *
  235. ngx_http_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd,
  236. void *conf)
  237. {
  238. char *p = conf;
  239. char *rv;
  240. ngx_http_complex_value_t *cv;
  241. rv = ngx_http_set_complex_value_slot(cf, cmd, conf);
  242. if (rv != NGX_CONF_OK) {
  243. return rv;
  244. }
  245. cv = *(ngx_http_complex_value_t **) (p + cmd->offset);
  246. if (cv->lengths) {
  247. return NGX_CONF_OK;
  248. }
  249. cv->u.size = ngx_parse_size(&cv->value);
  250. if (cv->u.size == (size_t) NGX_ERROR) {
  251. return "invalid value";
  252. }
  253. return NGX_CONF_OK;
  254. }
  255. ngx_int_t
  256. ngx_http_test_predicates(ngx_http_request_t *r, ngx_array_t *predicates)
  257. {
  258. ngx_str_t val;
  259. ngx_uint_t i;
  260. ngx_http_complex_value_t *cv;
  261. if (predicates == NULL) {
  262. return NGX_OK;
  263. }
  264. cv = predicates->elts;
  265. for (i = 0; i < predicates->nelts; i++) {
  266. if (ngx_http_complex_value(r, &cv[i], &val) != NGX_OK) {
  267. return NGX_ERROR;
  268. }
  269. if (val.len && (val.len != 1 || val.data[0] != '0')) {
  270. return NGX_DECLINED;
  271. }
  272. }
  273. return NGX_OK;
  274. }
  275. ngx_int_t
  276. ngx_http_test_required_predicates(ngx_http_request_t *r,
  277. ngx_array_t *predicates)
  278. {
  279. ngx_str_t val;
  280. ngx_uint_t i;
  281. ngx_http_complex_value_t *cv;
  282. if (predicates == NULL) {
  283. return NGX_OK;
  284. }
  285. cv = predicates->elts;
  286. for (i = 0; i < predicates->nelts; i++) {
  287. if (ngx_http_complex_value(r, &cv[i], &val) != NGX_OK) {
  288. return NGX_ERROR;
  289. }
  290. if (val.len == 0 || (val.len == 1 && val.data[0] == '0')) {
  291. return NGX_DECLINED;
  292. }
  293. }
  294. return NGX_OK;
  295. }
  296. char *
  297. ngx_http_set_predicate_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  298. {
  299. char *p = conf;
  300. ngx_str_t *value;
  301. ngx_uint_t i;
  302. ngx_array_t **a;
  303. ngx_http_complex_value_t *cv;
  304. ngx_http_compile_complex_value_t ccv;
  305. a = (ngx_array_t **) (p + cmd->offset);
  306. if (*a == NGX_CONF_UNSET_PTR) {
  307. *a = ngx_array_create(cf->pool, 1, sizeof(ngx_http_complex_value_t));
  308. if (*a == NULL) {
  309. return NGX_CONF_ERROR;
  310. }
  311. }
  312. value = cf->args->elts;
  313. for (i = 1; i < cf->args->nelts; i++) {
  314. cv = ngx_array_push(*a);
  315. if (cv == NULL) {
  316. return NGX_CONF_ERROR;
  317. }
  318. ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
  319. ccv.cf = cf;
  320. ccv.value = &value[i];
  321. ccv.complex_value = cv;
  322. if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
  323. return NGX_CONF_ERROR;
  324. }
  325. }
  326. return NGX_CONF_OK;
  327. }
  328. ngx_uint_t
  329. ngx_http_script_variables_count(ngx_str_t *value)
  330. {
  331. ngx_uint_t i, n;
  332. for (n = 0, i = 0; i < value->len; i++) {
  333. if (value->data[i] == '$') {
  334. n++;
  335. }
  336. }
  337. return n;
  338. }
  339. ngx_int_t
  340. ngx_http_script_compile(ngx_http_script_compile_t *sc)
  341. {
  342. u_char ch;
  343. ngx_str_t name;
  344. ngx_uint_t i, bracket;
  345. if (ngx_http_script_init_arrays(sc) != NGX_OK) {
  346. return NGX_ERROR;
  347. }
  348. for (i = 0; i < sc->source->len; /* void */ ) {
  349. name.len = 0;
  350. if (sc->source->data[i] == '$') {
  351. if (++i == sc->source->len) {
  352. goto invalid_variable;
  353. }
  354. if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
  355. #if (NGX_PCRE)
  356. ngx_uint_t n;
  357. n = sc->source->data[i] - '0';
  358. if (sc->captures_mask & ((ngx_uint_t) 1 << n)) {
  359. sc->dup_capture = 1;
  360. }
  361. sc->captures_mask |= (ngx_uint_t) 1 << n;
  362. if (ngx_http_script_add_capture_code(sc, n) != NGX_OK) {
  363. return NGX_ERROR;
  364. }
  365. i++;
  366. continue;
  367. #else
  368. ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
  369. "using variable \"$%c\" requires "
  370. "PCRE library", sc->source->data[i]);
  371. return NGX_ERROR;
  372. #endif
  373. }
  374. if (sc->source->data[i] == '{') {
  375. bracket = 1;
  376. if (++i == sc->source->len) {
  377. goto invalid_variable;
  378. }
  379. name.data = &sc->source->data[i];
  380. } else {
  381. bracket = 0;
  382. name.data = &sc->source->data[i];
  383. }
  384. for ( /* void */ ; i < sc->source->len; i++, name.len++) {
  385. ch = sc->source->data[i];
  386. if (ch == '}' && bracket) {
  387. i++;
  388. bracket = 0;
  389. break;
  390. }
  391. if ((ch >= 'A' && ch <= 'Z')
  392. || (ch >= 'a' && ch <= 'z')
  393. || (ch >= '0' && ch <= '9')
  394. || ch == '_')
  395. {
  396. continue;
  397. }
  398. break;
  399. }
  400. if (bracket) {
  401. ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
  402. "the closing bracket in \"%V\" "
  403. "variable is missing", &name);
  404. return NGX_ERROR;
  405. }
  406. if (name.len == 0) {
  407. goto invalid_variable;
  408. }
  409. sc->variables++;
  410. if (ngx_http_script_add_var_code(sc, &name) != NGX_OK) {
  411. return NGX_ERROR;
  412. }
  413. continue;
  414. }
  415. if (sc->source->data[i] == '?' && sc->compile_args) {
  416. sc->args = 1;
  417. sc->compile_args = 0;
  418. if (ngx_http_script_add_args_code(sc) != NGX_OK) {
  419. return NGX_ERROR;
  420. }
  421. i++;
  422. continue;
  423. }
  424. name.data = &sc->source->data[i];
  425. while (i < sc->source->len) {
  426. if (sc->source->data[i] == '$') {
  427. break;
  428. }
  429. if (sc->source->data[i] == '?') {
  430. sc->args = 1;
  431. if (sc->compile_args) {
  432. break;
  433. }
  434. }
  435. i++;
  436. name.len++;
  437. }
  438. sc->size += name.len;
  439. if (ngx_http_script_add_copy_code(sc, &name, (i == sc->source->len))
  440. != NGX_OK)
  441. {
  442. return NGX_ERROR;
  443. }
  444. }
  445. return ngx_http_script_done(sc);
  446. invalid_variable:
  447. ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name");
  448. return NGX_ERROR;
  449. }
  450. u_char *
  451. ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value,
  452. void *code_lengths, size_t len, void *code_values)
  453. {
  454. ngx_uint_t i;
  455. ngx_http_script_code_pt code;
  456. ngx_http_script_len_code_pt lcode;
  457. ngx_http_script_engine_t e;
  458. ngx_http_core_main_conf_t *cmcf;
  459. cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
  460. for (i = 0; i < cmcf->variables.nelts; i++) {
  461. if (r->variables[i].no_cacheable) {
  462. r->variables[i].valid = 0;
  463. r->variables[i].not_found = 0;
  464. }
  465. }
  466. ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
  467. e.ip = code_lengths;
  468. e.request = r;
  469. e.flushed = 1;
  470. while (*(uintptr_t *) e.ip) {
  471. lcode = *(ngx_http_script_len_code_pt *) e.ip;
  472. len += lcode(&e);
  473. }
  474. value->len = len;
  475. value->data = ngx_pnalloc(r->pool, len);
  476. if (value->data == NULL) {
  477. return NULL;
  478. }
  479. e.ip = code_values;
  480. e.pos = value->data;
  481. while (*(uintptr_t *) e.ip) {
  482. code = *(ngx_http_script_code_pt *) e.ip;
  483. code((ngx_http_script_engine_t *) &e);
  484. }
  485. return e.pos;
  486. }
  487. void
  488. ngx_http_script_flush_no_cacheable_variables(ngx_http_request_t *r,
  489. ngx_array_t *indices)
  490. {
  491. ngx_uint_t n, *index;
  492. if (indices) {
  493. index = indices->elts;
  494. for (n = 0; n < indices->nelts; n++) {
  495. if (r->variables[index[n]].no_cacheable) {
  496. r->variables[index[n]].valid = 0;
  497. r->variables[index[n]].not_found = 0;
  498. }
  499. }
  500. }
  501. }
  502. static ngx_int_t
  503. ngx_http_script_init_arrays(ngx_http_script_compile_t *sc)
  504. {
  505. ngx_uint_t n;
  506. if (sc->flushes && *sc->flushes == NULL) {
  507. n = sc->variables ? sc->variables : 1;
  508. *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t));
  509. if (*sc->flushes == NULL) {
  510. return NGX_ERROR;
  511. }
  512. }
  513. if (*sc->lengths == NULL) {
  514. n = sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)
  515. + sizeof(ngx_http_script_var_code_t))
  516. + sizeof(uintptr_t);
  517. *sc->lengths = ngx_array_create(sc->cf->pool, n, 1);
  518. if (*sc->lengths == NULL) {
  519. return NGX_ERROR;
  520. }
  521. }
  522. if (*sc->values == NULL) {
  523. n = (sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)
  524. + sizeof(ngx_http_script_var_code_t))
  525. + sizeof(uintptr_t)
  526. + sc->source->len
  527. + sizeof(uintptr_t) - 1)
  528. & ~(sizeof(uintptr_t) - 1);
  529. *sc->values = ngx_array_create(sc->cf->pool, n, 1);
  530. if (*sc->values == NULL) {
  531. return NGX_ERROR;
  532. }
  533. }
  534. sc->variables = 0;
  535. return NGX_OK;
  536. }
  537. static ngx_int_t
  538. ngx_http_script_done(ngx_http_script_compile_t *sc)
  539. {
  540. ngx_str_t zero;
  541. uintptr_t *code;
  542. if (sc->zero) {
  543. zero.len = 1;
  544. zero.data = (u_char *) "\0";
  545. if (ngx_http_script_add_copy_code(sc, &zero, 0) != NGX_OK) {
  546. return NGX_ERROR;
  547. }
  548. }
  549. if (sc->conf_prefix || sc->root_prefix) {
  550. if (ngx_http_script_add_full_name_code(sc) != NGX_OK) {
  551. return NGX_ERROR;
  552. }
  553. }
  554. if (sc->complete_lengths) {
  555. code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
  556. if (code == NULL) {
  557. return NGX_ERROR;
  558. }
  559. *code = (uintptr_t) NULL;
  560. }
  561. if (sc->complete_values) {
  562. code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t),
  563. &sc->main);
  564. if (code == NULL) {
  565. return NGX_ERROR;
  566. }
  567. *code = (uintptr_t) NULL;
  568. }
  569. return NGX_OK;
  570. }
  571. void *
  572. ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size)
  573. {
  574. if (*codes == NULL) {
  575. *codes = ngx_array_create(pool, 256, 1);
  576. if (*codes == NULL) {
  577. return NULL;
  578. }
  579. }
  580. return ngx_array_push_n(*codes, size);
  581. }
  582. void *
  583. ngx_http_script_add_code(ngx_array_t *codes, size_t size, void *code)
  584. {
  585. u_char *elts, **p;
  586. void *new;
  587. elts = codes->elts;
  588. new = ngx_array_push_n(codes, size);
  589. if (new == NULL) {
  590. return NULL;
  591. }
  592. if (code) {
  593. if (elts != codes->elts) {
  594. p = code;
  595. *p += (u_char *) codes->elts - elts;
  596. }
  597. }
  598. return new;
  599. }
  600. static ngx_int_t
  601. ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value,
  602. ngx_uint_t last)
  603. {
  604. u_char *p;
  605. size_t size, len, zero;
  606. ngx_http_script_copy_code_t *code;
  607. zero = (sc->zero && last);
  608. len = value->len + zero;
  609. code = ngx_http_script_add_code(*sc->lengths,
  610. sizeof(ngx_http_script_copy_code_t), NULL);
  611. if (code == NULL) {
  612. return NGX_ERROR;
  613. }
  614. code->code = (ngx_http_script_code_pt) (void *)
  615. ngx_http_script_copy_len_code;
  616. code->len = len;
  617. size = (sizeof(ngx_http_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
  618. & ~(sizeof(uintptr_t) - 1);
  619. code = ngx_http_script_add_code(*sc->values, size, &sc->main);
  620. if (code == NULL) {
  621. return NGX_ERROR;
  622. }
  623. code->code = ngx_http_script_copy_code;
  624. code->len = len;
  625. p = ngx_cpymem((u_char *) code + sizeof(ngx_http_script_copy_code_t),
  626. value->data, value->len);
  627. if (zero) {
  628. *p = '\0';
  629. sc->zero = 0;
  630. }
  631. return NGX_OK;
  632. }
  633. size_t
  634. ngx_http_script_copy_len_code(ngx_http_script_engine_t *e)
  635. {
  636. ngx_http_script_copy_code_t *code;
  637. code = (ngx_http_script_copy_code_t *) e->ip;
  638. e->ip += sizeof(ngx_http_script_copy_code_t);
  639. return code->len;
  640. }
  641. void
  642. ngx_http_script_copy_code(ngx_http_script_engine_t *e)
  643. {
  644. u_char *p;
  645. ngx_http_script_copy_code_t *code;
  646. code = (ngx_http_script_copy_code_t *) e->ip;
  647. p = e->pos;
  648. if (!e->skip) {
  649. e->pos = ngx_copy(p, e->ip + sizeof(ngx_http_script_copy_code_t),
  650. code->len);
  651. }
  652. e->ip += sizeof(ngx_http_script_copy_code_t)
  653. + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
  654. ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  655. "http script copy: \"%*s\"", e->pos - p, p);
  656. }
  657. static ngx_int_t
  658. ngx_http_script_add_var_code(ngx_http_script_compile_t *sc, ngx_str_t *name)
  659. {
  660. ngx_int_t index, *p;
  661. ngx_http_script_var_code_t *code;
  662. index = ngx_http_get_variable_index(sc->cf, name);
  663. if (index == NGX_ERROR) {
  664. return NGX_ERROR;
  665. }
  666. if (sc->flushes) {
  667. p = ngx_array_push(*sc->flushes);
  668. if (p == NULL) {
  669. return NGX_ERROR;
  670. }
  671. *p = index;
  672. }
  673. code = ngx_http_script_add_code(*sc->lengths,
  674. sizeof(ngx_http_script_var_code_t), NULL);
  675. if (code == NULL) {
  676. return NGX_ERROR;
  677. }
  678. code->code = (ngx_http_script_code_pt) (void *)
  679. ngx_http_script_copy_var_len_code;
  680. code->index = (uintptr_t) index;
  681. code = ngx_http_script_add_code(*sc->values,
  682. sizeof(ngx_http_script_var_code_t),
  683. &sc->main);
  684. if (code == NULL) {
  685. return NGX_ERROR;
  686. }
  687. code->code = ngx_http_script_copy_var_code;
  688. code->index = (uintptr_t) index;
  689. return NGX_OK;
  690. }
  691. size_t
  692. ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e)
  693. {
  694. ngx_http_variable_value_t *value;
  695. ngx_http_script_var_code_t *code;
  696. code = (ngx_http_script_var_code_t *) e->ip;
  697. e->ip += sizeof(ngx_http_script_var_code_t);
  698. if (e->flushed) {
  699. value = ngx_http_get_indexed_variable(e->request, code->index);
  700. } else {
  701. value = ngx_http_get_flushed_variable(e->request, code->index);
  702. }
  703. if (value && !value->not_found) {
  704. return value->len;
  705. }
  706. return 0;
  707. }
  708. void
  709. ngx_http_script_copy_var_code(ngx_http_script_engine_t *e)
  710. {
  711. u_char *p;
  712. ngx_http_variable_value_t *value;
  713. ngx_http_script_var_code_t *code;
  714. code = (ngx_http_script_var_code_t *) e->ip;
  715. e->ip += sizeof(ngx_http_script_var_code_t);
  716. if (!e->skip) {
  717. if (e->flushed) {
  718. value = ngx_http_get_indexed_variable(e->request, code->index);
  719. } else {
  720. value = ngx_http_get_flushed_variable(e->request, code->index);
  721. }
  722. if (value && !value->not_found) {
  723. p = e->pos;
  724. e->pos = ngx_copy(p, value->data, value->len);
  725. ngx_log_debug2(NGX_LOG_DEBUG_HTTP,
  726. e->request->connection->log, 0,
  727. "http script var: \"%*s\"", e->pos - p, p);
  728. }
  729. }
  730. }
  731. static ngx_int_t
  732. ngx_http_script_add_args_code(ngx_http_script_compile_t *sc)
  733. {
  734. uintptr_t *code;
  735. code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
  736. if (code == NULL) {
  737. return NGX_ERROR;
  738. }
  739. *code = (uintptr_t) ngx_http_script_mark_args_code;
  740. code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t), &sc->main);
  741. if (code == NULL) {
  742. return NGX_ERROR;
  743. }
  744. *code = (uintptr_t) ngx_http_script_start_args_code;
  745. return NGX_OK;
  746. }
  747. size_t
  748. ngx_http_script_mark_args_code(ngx_http_script_engine_t *e)
  749. {
  750. e->is_args = 1;
  751. e->ip += sizeof(uintptr_t);
  752. return 1;
  753. }
  754. void
  755. ngx_http_script_start_args_code(ngx_http_script_engine_t *e)
  756. {
  757. ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  758. "http script args");
  759. e->is_args = 1;
  760. e->args = e->pos;
  761. e->ip += sizeof(uintptr_t);
  762. }
  763. #if (NGX_PCRE)
  764. void
  765. ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
  766. {
  767. size_t len;
  768. ngx_int_t rc;
  769. ngx_uint_t n;
  770. ngx_http_request_t *r;
  771. ngx_http_script_engine_t le;
  772. ngx_http_script_len_code_pt lcode;
  773. ngx_http_script_regex_code_t *code;
  774. code = (ngx_http_script_regex_code_t *) e->ip;
  775. r = e->request;
  776. ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  777. "http script regex: \"%V\"", &code->name);
  778. if (code->uri) {
  779. e->line = r->uri;
  780. } else {
  781. e->sp--;
  782. e->line.len = e->sp->len;
  783. e->line.data = e->sp->data;
  784. }
  785. rc = ngx_http_regex_exec(r, code->regex, &e->line);
  786. if (rc == NGX_DECLINED) {
  787. if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
  788. ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
  789. "\"%V\" does not match \"%V\"",
  790. &code->name, &e->line);
  791. }
  792. r->ncaptures = 0;
  793. if (code->test) {
  794. if (code->negative_test) {
  795. e->sp->len = 1;
  796. e->sp->data = (u_char *) "1";
  797. } else {
  798. e->sp->len = 0;
  799. e->sp->data = (u_char *) "";
  800. }
  801. e->sp++;
  802. e->ip += sizeof(ngx_http_script_regex_code_t);
  803. return;
  804. }
  805. e->ip += code->next;
  806. return;
  807. }
  808. if (rc == NGX_ERROR) {
  809. e->ip = ngx_http_script_exit;
  810. e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  811. return;
  812. }
  813. if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
  814. ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
  815. "\"%V\" matches \"%V\"", &code->name, &e->line);
  816. }
  817. if (code->test) {
  818. if (code->negative_test) {
  819. e->sp->len = 0;
  820. e->sp->data = (u_char *) "";
  821. } else {
  822. e->sp->len = 1;
  823. e->sp->data = (u_char *) "1";
  824. }
  825. e->sp++;
  826. e->ip += sizeof(ngx_http_script_regex_code_t);
  827. return;
  828. }
  829. if (code->status) {
  830. e->status = code->status;
  831. if (!code->redirect) {
  832. e->ip = ngx_http_script_exit;
  833. return;
  834. }
  835. }
  836. if (code->uri) {
  837. r->internal = 1;
  838. r->valid_unparsed_uri = 0;
  839. if (code->break_cycle) {
  840. r->valid_location = 0;
  841. r->uri_changed = 0;
  842. } else {
  843. r->uri_changed = 1;
  844. }
  845. }
  846. if (code->lengths == NULL) {
  847. e->buf.len = code->size;
  848. if (code->uri) {
  849. if (r->ncaptures && (r->quoted_uri || r->plus_in_uri)) {
  850. e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
  851. NGX_ESCAPE_ARGS);
  852. }
  853. }
  854. for (n = 2; n < r->ncaptures; n += 2) {
  855. e->buf.len += r->captures[n + 1] - r->captures[n];
  856. }
  857. } else {
  858. ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
  859. le.ip = code->lengths->elts;
  860. le.line = e->line;
  861. le.request = r;
  862. le.quote = code->redirect;
  863. len = 0;
  864. while (*(uintptr_t *) le.ip) {
  865. lcode = *(ngx_http_script_len_code_pt *) le.ip;
  866. len += lcode(&le);
  867. }
  868. e->buf.len = len;
  869. }
  870. if (code->add_args && r->args.len) {
  871. e->buf.len += r->args.len + 1;
  872. }
  873. e->buf.data = ngx_pnalloc(r->pool, e->buf.len);
  874. if (e->buf.data == NULL) {
  875. e->ip = ngx_http_script_exit;
  876. e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  877. return;
  878. }
  879. e->quote = code->redirect;
  880. e->pos = e->buf.data;
  881. e->ip += sizeof(ngx_http_script_regex_code_t);
  882. }
  883. void
  884. ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
  885. {
  886. u_char *dst, *src;
  887. ngx_http_request_t *r;
  888. ngx_http_script_regex_end_code_t *code;
  889. code = (ngx_http_script_regex_end_code_t *) e->ip;
  890. r = e->request;
  891. e->quote = 0;
  892. ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  893. "http script regex end");
  894. if (code->redirect) {
  895. dst = e->buf.data;
  896. src = e->buf.data;
  897. ngx_unescape_uri(&dst, &src, e->pos - e->buf.data,
  898. NGX_UNESCAPE_REDIRECT);
  899. if (src < e->pos) {
  900. dst = ngx_movemem(dst, src, e->pos - src);
  901. }
  902. e->pos = dst;
  903. if (code->add_args && r->args.len) {
  904. *e->pos++ = (u_char) (code->args ? '&' : '?');
  905. e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
  906. }
  907. e->buf.len = e->pos - e->buf.data;
  908. if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
  909. ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
  910. "rewritten redirect: \"%V\"", &e->buf);
  911. }
  912. ngx_http_clear_location(r);
  913. r->headers_out.location = ngx_list_push(&r->headers_out.headers);
  914. if (r->headers_out.location == NULL) {
  915. e->ip = ngx_http_script_exit;
  916. e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  917. return;
  918. }
  919. r->headers_out.location->hash = 1;
  920. r->headers_out.location->next = NULL;
  921. ngx_str_set(&r->headers_out.location->key, "Location");
  922. r->headers_out.location->value = e->buf;
  923. e->ip += sizeof(ngx_http_script_regex_end_code_t);
  924. return;
  925. }
  926. if (e->args) {
  927. e->buf.len = e->args - e->buf.data;
  928. if (code->add_args && r->args.len) {
  929. *e->pos++ = '&';
  930. e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
  931. }
  932. r->args.len = e->pos - e->args;
  933. r->args.data = e->args;
  934. e->args = NULL;
  935. } else {
  936. e->buf.len = e->pos - e->buf.data;
  937. if (!code->add_args) {
  938. r->args.len = 0;
  939. }
  940. }
  941. if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
  942. ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
  943. "rewritten data: \"%V\", args: \"%V\"",
  944. &e->buf, &r->args);
  945. }
  946. if (code->uri) {
  947. r->uri = e->buf;
  948. if (r->uri.len == 0) {
  949. ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  950. "the rewritten URI has a zero length");
  951. e->ip = ngx_http_script_exit;
  952. e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  953. return;
  954. }
  955. ngx_http_set_exten(r);
  956. }
  957. e->ip += sizeof(ngx_http_script_regex_end_code_t);
  958. }
  959. static ngx_int_t
  960. ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc, ngx_uint_t n)
  961. {
  962. ngx_http_script_copy_capture_code_t *code;
  963. code = ngx_http_script_add_code(*sc->lengths,
  964. sizeof(ngx_http_script_copy_capture_code_t),
  965. NULL);
  966. if (code == NULL) {
  967. return NGX_ERROR;
  968. }
  969. code->code = (ngx_http_script_code_pt) (void *)
  970. ngx_http_script_copy_capture_len_code;
  971. code->n = 2 * n;
  972. code = ngx_http_script_add_code(*sc->values,
  973. sizeof(ngx_http_script_copy_capture_code_t),
  974. &sc->main);
  975. if (code == NULL) {
  976. return NGX_ERROR;
  977. }
  978. code->code = ngx_http_script_copy_capture_code;
  979. code->n = 2 * n;
  980. if (sc->ncaptures < n) {
  981. sc->ncaptures = n;
  982. }
  983. return NGX_OK;
  984. }
  985. size_t
  986. ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e)
  987. {
  988. int *cap;
  989. u_char *p;
  990. ngx_uint_t n;
  991. ngx_http_request_t *r;
  992. ngx_http_script_copy_capture_code_t *code;
  993. r = e->request;
  994. code = (ngx_http_script_copy_capture_code_t *) e->ip;
  995. e->ip += sizeof(ngx_http_script_copy_capture_code_t);
  996. n = code->n;
  997. if (n < r->ncaptures) {
  998. cap = r->captures;
  999. if ((e->is_args || e->quote)
  1000. && (e->request->quoted_uri || e->request->plus_in_uri))
  1001. {
  1002. p = r->captures_data;
  1003. return cap[n + 1] - cap[n]
  1004. + 2 * ngx_escape_uri(NULL, &p[cap[n]], cap[n + 1] - cap[n],
  1005. NGX_ESCAPE_ARGS);
  1006. } else {
  1007. return cap[n + 1] - cap[n];
  1008. }
  1009. }
  1010. return 0;
  1011. }
  1012. void
  1013. ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
  1014. {
  1015. int *cap;
  1016. u_char *p, *pos;
  1017. ngx_uint_t n;
  1018. ngx_http_request_t *r;
  1019. ngx_http_script_copy_capture_code_t *code;
  1020. r = e->request;
  1021. code = (ngx_http_script_copy_capture_code_t *) e->ip;
  1022. e->ip += sizeof(ngx_http_script_copy_capture_code_t);
  1023. n = code->n;
  1024. pos = e->pos;
  1025. if (n < r->ncaptures) {
  1026. cap = r->captures;
  1027. p = r->captures_data;
  1028. if ((e->is_args || e->quote)
  1029. && (e->request->quoted_uri || e->request->plus_in_uri))
  1030. {
  1031. e->pos = (u_char *) ngx_escape_uri(pos, &p[cap[n]],
  1032. cap[n + 1] - cap[n],
  1033. NGX_ESCAPE_ARGS);
  1034. } else {
  1035. e->pos = ngx_copy(pos, &p[cap[n]], cap[n + 1] - cap[n]);
  1036. }
  1037. }
  1038. ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1039. "http script capture: \"%*s\"", e->pos - pos, pos);
  1040. }
  1041. #endif
  1042. static ngx_int_t
  1043. ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc)
  1044. {
  1045. ngx_http_script_full_name_code_t *code;
  1046. code = ngx_http_script_add_code(*sc->lengths,
  1047. sizeof(ngx_http_script_full_name_code_t),
  1048. NULL);
  1049. if (code == NULL) {
  1050. return NGX_ERROR;
  1051. }
  1052. code->code = (ngx_http_script_code_pt) (void *)
  1053. ngx_http_script_full_name_len_code;
  1054. code->conf_prefix = sc->conf_prefix;
  1055. code = ngx_http_script_add_code(*sc->values,
  1056. sizeof(ngx_http_script_full_name_code_t),
  1057. &sc->main);
  1058. if (code == NULL) {
  1059. return NGX_ERROR;
  1060. }
  1061. code->code = ngx_http_script_full_name_code;
  1062. code->conf_prefix = sc->conf_prefix;
  1063. return NGX_OK;
  1064. }
  1065. static size_t
  1066. ngx_http_script_full_name_len_code(ngx_http_script_engine_t *e)
  1067. {
  1068. ngx_http_script_full_name_code_t *code;
  1069. code = (ngx_http_script_full_name_code_t *) e->ip;
  1070. e->ip += sizeof(ngx_http_script_full_name_code_t);
  1071. return code->conf_prefix ? ngx_cycle->conf_prefix.len:
  1072. ngx_cycle->prefix.len;
  1073. }
  1074. static void
  1075. ngx_http_script_full_name_code(ngx_http_script_engine_t *e)
  1076. {
  1077. ngx_http_script_full_name_code_t *code;
  1078. ngx_str_t value, *prefix;
  1079. code = (ngx_http_script_full_name_code_t *) e->ip;
  1080. value.data = e->buf.data;
  1081. value.len = e->pos - e->buf.data;
  1082. prefix = code->conf_prefix ? (ngx_str_t *) &ngx_cycle->conf_prefix:
  1083. (ngx_str_t *) &ngx_cycle->prefix;
  1084. if (ngx_get_full_name(e->request->pool, prefix, &value) != NGX_OK) {
  1085. e->ip = ngx_http_script_exit;
  1086. e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  1087. return;
  1088. }
  1089. e->buf = value;
  1090. ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1091. "http script fullname: \"%V\"", &value);
  1092. e->ip += sizeof(ngx_http_script_full_name_code_t);
  1093. }
  1094. void
  1095. ngx_http_script_return_code(ngx_http_script_engine_t *e)
  1096. {
  1097. ngx_http_script_return_code_t *code;
  1098. code = (ngx_http_script_return_code_t *) e->ip;
  1099. if (code->status < NGX_HTTP_BAD_REQUEST
  1100. || code->text.value.len
  1101. || code->text.lengths)
  1102. {
  1103. e->status = ngx_http_send_response(e->request, code->status, NULL,
  1104. &code->text);
  1105. } else {
  1106. e->status = code->status;
  1107. }
  1108. e->ip = ngx_http_script_exit;
  1109. }
  1110. void
  1111. ngx_http_script_break_code(ngx_http_script_engine_t *e)
  1112. {
  1113. ngx_http_request_t *r;
  1114. r = e->request;
  1115. if (r->uri_changed) {
  1116. r->valid_location = 0;
  1117. r->uri_changed = 0;
  1118. }
  1119. e->ip = ngx_http_script_exit;
  1120. }
  1121. void
  1122. ngx_http_script_if_code(ngx_http_script_engine_t *e)
  1123. {
  1124. ngx_http_script_if_code_t *code;
  1125. code = (ngx_http_script_if_code_t *) e->ip;
  1126. ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1127. "http script if");
  1128. e->sp--;
  1129. if (e->sp->len && (e->sp->len != 1 || e->sp->data[0] != '0')) {
  1130. if (code->loc_conf) {
  1131. e->request->loc_conf = code->loc_conf;
  1132. ngx_http_update_location_config(e->request);
  1133. }
  1134. e->ip += sizeof(ngx_http_script_if_code_t);
  1135. return;
  1136. }
  1137. ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1138. "http script if: false");
  1139. e->ip += code->next;
  1140. }
  1141. void
  1142. ngx_http_script_equal_code(ngx_http_script_engine_t *e)
  1143. {
  1144. ngx_http_variable_value_t *val, *res;
  1145. ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1146. "http script equal");
  1147. e->sp--;
  1148. val = e->sp;
  1149. res = e->sp - 1;
  1150. e->ip += sizeof(uintptr_t);
  1151. if (val->len == res->len
  1152. && ngx_strncmp(val->data, res->data, res->len) == 0)
  1153. {
  1154. *res = ngx_http_variable_true_value;
  1155. return;
  1156. }
  1157. ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1158. "http script equal: no");
  1159. *res = ngx_http_variable_null_value;
  1160. }
  1161. void
  1162. ngx_http_script_not_equal_code(ngx_http_script_engine_t *e)
  1163. {
  1164. ngx_http_variable_value_t *val, *res;
  1165. ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1166. "http script not equal");
  1167. e->sp--;
  1168. val = e->sp;
  1169. res = e->sp - 1;
  1170. e->ip += sizeof(uintptr_t);
  1171. if (val->len == res->len
  1172. && ngx_strncmp(val->data, res->data, res->len) == 0)
  1173. {
  1174. ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1175. "http script not equal: no");
  1176. *res = ngx_http_variable_null_value;
  1177. return;
  1178. }
  1179. *res = ngx_http_variable_true_value;
  1180. }
  1181. void
  1182. ngx_http_script_file_code(ngx_http_script_engine_t *e)
  1183. {
  1184. ngx_str_t path;
  1185. ngx_http_request_t *r;
  1186. ngx_open_file_info_t of;
  1187. ngx_http_core_loc_conf_t *clcf;
  1188. ngx_http_variable_value_t *value;
  1189. ngx_http_script_file_code_t *code;
  1190. value = e->sp - 1;
  1191. code = (ngx_http_script_file_code_t *) e->ip;
  1192. e->ip += sizeof(ngx_http_script_file_code_t);
  1193. path.len = value->len - 1;
  1194. path.data = value->data;
  1195. r = e->request;
  1196. ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1197. "http script file op %p \"%V\"", (void *) code->op, &path);
  1198. clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
  1199. ngx_memzero(&of, sizeof(ngx_open_file_info_t));
  1200. of.read_ahead = clcf->read_ahead;
  1201. of.directio = clcf->directio;
  1202. of.valid = clcf->open_file_cache_valid;
  1203. of.min_uses = clcf->open_file_cache_min_uses;
  1204. of.test_only = 1;
  1205. of.errors = clcf->open_file_cache_errors;
  1206. of.events = clcf->open_file_cache_events;
  1207. if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
  1208. e->ip = ngx_http_script_exit;
  1209. e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  1210. return;
  1211. }
  1212. if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
  1213. != NGX_OK)
  1214. {
  1215. if (of.err == 0) {
  1216. e->ip = ngx_http_script_exit;
  1217. e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  1218. return;
  1219. }
  1220. if (of.err != NGX_ENOENT
  1221. && of.err != NGX_ENOTDIR
  1222. && of.err != NGX_ENAMETOOLONG)
  1223. {
  1224. ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
  1225. "%s \"%s\" failed", of.failed, value->data);
  1226. }
  1227. switch (code->op) {
  1228. case ngx_http_script_file_plain:
  1229. case ngx_http_script_file_dir:
  1230. case ngx_http_script_file_exists:
  1231. case ngx_http_script_file_exec:
  1232. goto false_value;
  1233. case ngx_http_script_file_not_plain:
  1234. case ngx_http_script_file_not_dir:
  1235. case ngx_http_script_file_not_exists:
  1236. case ngx_http_script_file_not_exec:
  1237. goto true_value;
  1238. }
  1239. goto false_value;
  1240. }
  1241. switch (code->op) {
  1242. case ngx_http_script_file_plain:
  1243. if (of.is_file) {
  1244. goto true_value;
  1245. }
  1246. goto false_value;
  1247. case ngx_http_script_file_not_plain:
  1248. if (of.is_file) {
  1249. goto false_value;
  1250. }
  1251. goto true_value;
  1252. case ngx_http_script_file_dir:
  1253. if (of.is_dir) {
  1254. goto true_value;
  1255. }
  1256. goto false_value;
  1257. case ngx_http_script_file_not_dir:
  1258. if (of.is_dir) {
  1259. goto false_value;
  1260. }
  1261. goto true_value;
  1262. case ngx_http_script_file_exists:
  1263. if (of.is_file || of.is_dir || of.is_link) {
  1264. goto true_value;
  1265. }
  1266. goto false_value;
  1267. case ngx_http_script_file_not_exists:
  1268. if (of.is_file || of.is_dir || of.is_link) {
  1269. goto false_value;
  1270. }
  1271. goto true_value;
  1272. case ngx_http_script_file_exec:
  1273. if (of.is_exec) {
  1274. goto true_value;
  1275. }
  1276. goto false_value;
  1277. case ngx_http_script_file_not_exec:
  1278. if (of.is_exec) {
  1279. goto false_value;
  1280. }
  1281. goto true_value;
  1282. }
  1283. false_value:
  1284. ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1285. "http script file op false");
  1286. *value = ngx_http_variable_null_value;
  1287. return;
  1288. true_value:
  1289. *value = ngx_http_variable_true_value;
  1290. return;
  1291. }
  1292. void
  1293. ngx_http_script_complex_value_code(ngx_http_script_engine_t *e)
  1294. {
  1295. size_t len;
  1296. ngx_http_script_engine_t le;
  1297. ngx_http_script_len_code_pt lcode;
  1298. ngx_http_script_complex_value_code_t *code;
  1299. code = (ngx_http_script_complex_value_code_t *) e->ip;
  1300. e->ip += sizeof(ngx_http_script_complex_value_code_t);
  1301. ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1302. "http script complex value");
  1303. ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
  1304. le.ip = code->lengths->elts;
  1305. le.line = e->line;
  1306. le.request = e->request;
  1307. le.quote = e->quote;
  1308. for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) {
  1309. lcode = *(ngx_http_script_len_code_pt *) le.ip;
  1310. }
  1311. e->buf.len = len;
  1312. e->buf.data = ngx_pnalloc(e->request->pool, len);
  1313. if (e->buf.data == NULL) {
  1314. e->ip = ngx_http_script_exit;
  1315. e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
  1316. return;
  1317. }
  1318. e->pos = e->buf.data;
  1319. e->sp->len = e->buf.len;
  1320. e->sp->data = e->buf.data;
  1321. e->sp++;
  1322. }
  1323. void
  1324. ngx_http_script_value_code(ngx_http_script_engine_t *e)
  1325. {
  1326. ngx_http_script_value_code_t *code;
  1327. code = (ngx_http_script_value_code_t *) e->ip;
  1328. e->ip += sizeof(ngx_http_script_value_code_t);
  1329. e->sp->len = code->text_len;
  1330. e->sp->data = (u_char *) code->text_data;
  1331. ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1332. "http script value: \"%v\"", e->sp);
  1333. e->sp++;
  1334. }
  1335. void
  1336. ngx_http_script_set_var_code(ngx_http_script_engine_t *e)
  1337. {
  1338. ngx_http_request_t *r;
  1339. ngx_http_script_var_code_t *code;
  1340. code = (ngx_http_script_var_code_t *) e->ip;
  1341. e->ip += sizeof(ngx_http_script_var_code_t);
  1342. r = e->request;
  1343. e->sp--;
  1344. r->variables[code->index].len = e->sp->len;
  1345. r->variables[code->index].valid = 1;
  1346. r->variables[code->index].no_cacheable = 0;
  1347. r->variables[code->index].not_found = 0;
  1348. r->variables[code->index].data = e->sp->data;
  1349. #if (NGX_DEBUG)
  1350. {
  1351. ngx_http_variable_t *v;
  1352. ngx_http_core_main_conf_t *cmcf;
  1353. cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
  1354. v = cmcf->variables.elts;
  1355. ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1356. "http script set $%V", &v[code->index].name);
  1357. }
  1358. #endif
  1359. }
  1360. void
  1361. ngx_http_script_var_set_handler_code(ngx_http_script_engine_t *e)
  1362. {
  1363. ngx_http_script_var_handler_code_t *code;
  1364. ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1365. "http script set var handler");
  1366. code = (ngx_http_script_var_handler_code_t *) e->ip;
  1367. e->ip += sizeof(ngx_http_script_var_handler_code_t);
  1368. e->sp--;
  1369. code->handler(e->request, e->sp, code->data);
  1370. }
  1371. void
  1372. ngx_http_script_var_code(ngx_http_script_engine_t *e)
  1373. {
  1374. ngx_http_variable_value_t *value;
  1375. ngx_http_script_var_code_t *code;
  1376. ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1377. "http script var");
  1378. code = (ngx_http_script_var_code_t *) e->ip;
  1379. e->ip += sizeof(ngx_http_script_var_code_t);
  1380. value = ngx_http_get_flushed_variable(e->request, code->index);
  1381. if (value && !value->not_found) {
  1382. ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
  1383. "http script var: \"%v\"", value);
  1384. *e->sp = *value;
  1385. e->sp++;
  1386. return;
  1387. }
  1388. *e->sp = ngx_http_variable_null_value;
  1389. e->sp++;
  1390. }
  1391. void
  1392. ngx_http_script_nop_code(ngx_http_script_engine_t *e)
  1393. {
  1394. e->ip += sizeof(uintptr_t);
  1395. }