ngx_http_parse.c 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416
  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 uint32_t usual[] = {
  9. 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
  10. /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
  11. 0x7fff37d6, /* 0111 1111 1111 1111 0011 0111 1101 0110 */
  12. /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
  13. #if (NGX_WIN32)
  14. 0xefffffff, /* 1110 1111 1111 1111 1111 1111 1111 1111 */
  15. #else
  16. 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
  17. #endif
  18. /* ~}| {zyx wvut srqp onml kjih gfed cba` */
  19. 0x7fffffff, /* 0111 1111 1111 1111 1111 1111 1111 1111 */
  20. 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
  21. 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
  22. 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
  23. 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
  24. };
  25. #if (NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED)
  26. #define ngx_str3_cmp(m, c0, c1, c2, c3) \
  27. *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)
  28. #define ngx_str3Ocmp(m, c0, c1, c2, c3) \
  29. *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)
  30. #define ngx_str4cmp(m, c0, c1, c2, c3) \
  31. *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0)
  32. #define ngx_str5cmp(m, c0, c1, c2, c3, c4) \
  33. *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) \
  34. && m[4] == c4
  35. #define ngx_str6cmp(m, c0, c1, c2, c3, c4, c5) \
  36. *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) \
  37. && (((uint32_t *) m)[1] & 0xffff) == ((c5 << 8) | c4)
  38. #define ngx_str7_cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \
  39. *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) \
  40. && ((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4)
  41. #define ngx_str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \
  42. *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) \
  43. && ((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4)
  44. #define ngx_str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8) \
  45. *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) \
  46. && ((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4) \
  47. && m[8] == c8
  48. #else /* !(NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED) */
  49. #define ngx_str3_cmp(m, c0, c1, c2, c3) \
  50. m[0] == c0 && m[1] == c1 && m[2] == c2
  51. #define ngx_str3Ocmp(m, c0, c1, c2, c3) \
  52. m[0] == c0 && m[2] == c2 && m[3] == c3
  53. #define ngx_str4cmp(m, c0, c1, c2, c3) \
  54. m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3
  55. #define ngx_str5cmp(m, c0, c1, c2, c3, c4) \
  56. m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 && m[4] == c4
  57. #define ngx_str6cmp(m, c0, c1, c2, c3, c4, c5) \
  58. m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \
  59. && m[4] == c4 && m[5] == c5
  60. #define ngx_str7_cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \
  61. m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \
  62. && m[4] == c4 && m[5] == c5 && m[6] == c6
  63. #define ngx_str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \
  64. m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \
  65. && m[4] == c4 && m[5] == c5 && m[6] == c6 && m[7] == c7
  66. #define ngx_str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8) \
  67. m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \
  68. && m[4] == c4 && m[5] == c5 && m[6] == c6 && m[7] == c7 && m[8] == c8
  69. #endif
  70. /* gcc, icc, msvc and others compile these switches as an jump table */
  71. ngx_int_t
  72. ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
  73. {
  74. u_char c, ch, *p, *m;
  75. enum {
  76. sw_start = 0,
  77. sw_method,
  78. sw_spaces_before_uri,
  79. sw_schema,
  80. sw_schema_slash,
  81. sw_schema_slash_slash,
  82. sw_host_start,
  83. sw_host,
  84. sw_host_end,
  85. sw_host_ip_literal,
  86. sw_port,
  87. sw_after_slash_in_uri,
  88. sw_check_uri,
  89. sw_uri,
  90. sw_http_09,
  91. sw_http_H,
  92. sw_http_HT,
  93. sw_http_HTT,
  94. sw_http_HTTP,
  95. sw_first_major_digit,
  96. sw_major_digit,
  97. sw_first_minor_digit,
  98. sw_minor_digit,
  99. sw_spaces_after_digit,
  100. sw_almost_done
  101. } state;
  102. state = r->state;
  103. for (p = b->pos; p < b->last; p++) {
  104. ch = *p;
  105. switch (state) {
  106. /* HTTP methods: GET, HEAD, POST */
  107. case sw_start:
  108. r->request_start = p;
  109. if (ch == CR || ch == LF) {
  110. break;
  111. }
  112. if ((ch < 'A' || ch > 'Z') && ch != '_' && ch != '-') {
  113. return NGX_HTTP_PARSE_INVALID_METHOD;
  114. }
  115. state = sw_method;
  116. break;
  117. case sw_method:
  118. if (ch == ' ') {
  119. r->method_end = p - 1;
  120. m = r->request_start;
  121. switch (p - m) {
  122. case 3:
  123. if (ngx_str3_cmp(m, 'G', 'E', 'T', ' ')) {
  124. r->method = NGX_HTTP_GET;
  125. break;
  126. }
  127. if (ngx_str3_cmp(m, 'P', 'U', 'T', ' ')) {
  128. r->method = NGX_HTTP_PUT;
  129. break;
  130. }
  131. break;
  132. case 4:
  133. if (m[1] == 'O') {
  134. if (ngx_str3Ocmp(m, 'P', 'O', 'S', 'T')) {
  135. r->method = NGX_HTTP_POST;
  136. break;
  137. }
  138. if (ngx_str3Ocmp(m, 'C', 'O', 'P', 'Y')) {
  139. r->method = NGX_HTTP_COPY;
  140. break;
  141. }
  142. if (ngx_str3Ocmp(m, 'M', 'O', 'V', 'E')) {
  143. r->method = NGX_HTTP_MOVE;
  144. break;
  145. }
  146. if (ngx_str3Ocmp(m, 'L', 'O', 'C', 'K')) {
  147. r->method = NGX_HTTP_LOCK;
  148. break;
  149. }
  150. } else {
  151. if (ngx_str4cmp(m, 'H', 'E', 'A', 'D')) {
  152. r->method = NGX_HTTP_HEAD;
  153. break;
  154. }
  155. }
  156. break;
  157. case 5:
  158. if (ngx_str5cmp(m, 'M', 'K', 'C', 'O', 'L')) {
  159. r->method = NGX_HTTP_MKCOL;
  160. break;
  161. }
  162. if (ngx_str5cmp(m, 'P', 'A', 'T', 'C', 'H')) {
  163. r->method = NGX_HTTP_PATCH;
  164. break;
  165. }
  166. if (ngx_str5cmp(m, 'T', 'R', 'A', 'C', 'E')) {
  167. r->method = NGX_HTTP_TRACE;
  168. break;
  169. }
  170. break;
  171. case 6:
  172. if (ngx_str6cmp(m, 'D', 'E', 'L', 'E', 'T', 'E')) {
  173. r->method = NGX_HTTP_DELETE;
  174. break;
  175. }
  176. if (ngx_str6cmp(m, 'U', 'N', 'L', 'O', 'C', 'K')) {
  177. r->method = NGX_HTTP_UNLOCK;
  178. break;
  179. }
  180. break;
  181. case 7:
  182. if (ngx_str7_cmp(m, 'O', 'P', 'T', 'I', 'O', 'N', 'S', ' '))
  183. {
  184. r->method = NGX_HTTP_OPTIONS;
  185. }
  186. if (ngx_str7_cmp(m, 'C', 'O', 'N', 'N', 'E', 'C', 'T', ' '))
  187. {
  188. r->method = NGX_HTTP_CONNECT;
  189. }
  190. break;
  191. case 8:
  192. if (ngx_str8cmp(m, 'P', 'R', 'O', 'P', 'F', 'I', 'N', 'D'))
  193. {
  194. r->method = NGX_HTTP_PROPFIND;
  195. }
  196. break;
  197. case 9:
  198. if (ngx_str9cmp(m,
  199. 'P', 'R', 'O', 'P', 'P', 'A', 'T', 'C', 'H'))
  200. {
  201. r->method = NGX_HTTP_PROPPATCH;
  202. }
  203. break;
  204. }
  205. state = sw_spaces_before_uri;
  206. break;
  207. }
  208. if ((ch < 'A' || ch > 'Z') && ch != '_' && ch != '-') {
  209. return NGX_HTTP_PARSE_INVALID_METHOD;
  210. }
  211. break;
  212. /* space* before URI */
  213. case sw_spaces_before_uri:
  214. if (ch == '/') {
  215. r->uri_start = p;
  216. state = sw_after_slash_in_uri;
  217. break;
  218. }
  219. c = (u_char) (ch | 0x20);
  220. if (c >= 'a' && c <= 'z') {
  221. r->schema_start = p;
  222. state = sw_schema;
  223. break;
  224. }
  225. switch (ch) {
  226. case ' ':
  227. break;
  228. default:
  229. return NGX_HTTP_PARSE_INVALID_REQUEST;
  230. }
  231. break;
  232. case sw_schema:
  233. c = (u_char) (ch | 0x20);
  234. if (c >= 'a' && c <= 'z') {
  235. break;
  236. }
  237. if ((ch >= '0' && ch <= '9') || ch == '+' || ch == '-' || ch == '.')
  238. {
  239. break;
  240. }
  241. switch (ch) {
  242. case ':':
  243. r->schema_end = p;
  244. state = sw_schema_slash;
  245. break;
  246. default:
  247. return NGX_HTTP_PARSE_INVALID_REQUEST;
  248. }
  249. break;
  250. case sw_schema_slash:
  251. switch (ch) {
  252. case '/':
  253. state = sw_schema_slash_slash;
  254. break;
  255. default:
  256. return NGX_HTTP_PARSE_INVALID_REQUEST;
  257. }
  258. break;
  259. case sw_schema_slash_slash:
  260. switch (ch) {
  261. case '/':
  262. state = sw_host_start;
  263. break;
  264. default:
  265. return NGX_HTTP_PARSE_INVALID_REQUEST;
  266. }
  267. break;
  268. case sw_host_start:
  269. r->host_start = p;
  270. if (ch == '[') {
  271. state = sw_host_ip_literal;
  272. break;
  273. }
  274. state = sw_host;
  275. /* fall through */
  276. case sw_host:
  277. c = (u_char) (ch | 0x20);
  278. if (c >= 'a' && c <= 'z') {
  279. break;
  280. }
  281. if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-') {
  282. break;
  283. }
  284. /* fall through */
  285. case sw_host_end:
  286. r->host_end = p;
  287. switch (ch) {
  288. case ':':
  289. state = sw_port;
  290. break;
  291. case '/':
  292. r->uri_start = p;
  293. state = sw_after_slash_in_uri;
  294. break;
  295. case '?':
  296. r->uri_start = p;
  297. r->args_start = p + 1;
  298. r->empty_path_in_uri = 1;
  299. state = sw_uri;
  300. break;
  301. case ' ':
  302. /*
  303. * use single "/" from request line to preserve pointers,
  304. * if request line will be copied to large client buffer
  305. */
  306. r->uri_start = r->schema_end + 1;
  307. r->uri_end = r->schema_end + 2;
  308. state = sw_http_09;
  309. break;
  310. default:
  311. return NGX_HTTP_PARSE_INVALID_REQUEST;
  312. }
  313. break;
  314. case sw_host_ip_literal:
  315. if (ch >= '0' && ch <= '9') {
  316. break;
  317. }
  318. c = (u_char) (ch | 0x20);
  319. if (c >= 'a' && c <= 'z') {
  320. break;
  321. }
  322. switch (ch) {
  323. case ':':
  324. break;
  325. case ']':
  326. state = sw_host_end;
  327. break;
  328. case '-':
  329. case '.':
  330. case '_':
  331. case '~':
  332. /* unreserved */
  333. break;
  334. case '!':
  335. case '$':
  336. case '&':
  337. case '\'':
  338. case '(':
  339. case ')':
  340. case '*':
  341. case '+':
  342. case ',':
  343. case ';':
  344. case '=':
  345. /* sub-delims */
  346. break;
  347. default:
  348. return NGX_HTTP_PARSE_INVALID_REQUEST;
  349. }
  350. break;
  351. case sw_port:
  352. if (ch >= '0' && ch <= '9') {
  353. break;
  354. }
  355. switch (ch) {
  356. case '/':
  357. r->uri_start = p;
  358. state = sw_after_slash_in_uri;
  359. break;
  360. case '?':
  361. r->uri_start = p;
  362. r->args_start = p + 1;
  363. r->empty_path_in_uri = 1;
  364. state = sw_uri;
  365. break;
  366. case ' ':
  367. /*
  368. * use single "/" from request line to preserve pointers,
  369. * if request line will be copied to large client buffer
  370. */
  371. r->uri_start = r->schema_end + 1;
  372. r->uri_end = r->schema_end + 2;
  373. state = sw_http_09;
  374. break;
  375. default:
  376. return NGX_HTTP_PARSE_INVALID_REQUEST;
  377. }
  378. break;
  379. /* check "/.", "//", "%", and "\" (Win32) in URI */
  380. case sw_after_slash_in_uri:
  381. if (usual[ch >> 5] & (1U << (ch & 0x1f))) {
  382. state = sw_check_uri;
  383. break;
  384. }
  385. switch (ch) {
  386. case ' ':
  387. r->uri_end = p;
  388. state = sw_http_09;
  389. break;
  390. case CR:
  391. r->uri_end = p;
  392. r->http_minor = 9;
  393. state = sw_almost_done;
  394. break;
  395. case LF:
  396. r->uri_end = p;
  397. r->http_minor = 9;
  398. goto done;
  399. case '.':
  400. r->complex_uri = 1;
  401. state = sw_uri;
  402. break;
  403. case '%':
  404. r->quoted_uri = 1;
  405. state = sw_uri;
  406. break;
  407. case '/':
  408. r->complex_uri = 1;
  409. state = sw_uri;
  410. break;
  411. #if (NGX_WIN32)
  412. case '\\':
  413. r->complex_uri = 1;
  414. state = sw_uri;
  415. break;
  416. #endif
  417. case '?':
  418. r->args_start = p + 1;
  419. state = sw_uri;
  420. break;
  421. case '#':
  422. r->complex_uri = 1;
  423. state = sw_uri;
  424. break;
  425. case '+':
  426. r->plus_in_uri = 1;
  427. break;
  428. default:
  429. if (ch < 0x20 || ch == 0x7f) {
  430. return NGX_HTTP_PARSE_INVALID_REQUEST;
  431. }
  432. state = sw_check_uri;
  433. break;
  434. }
  435. break;
  436. /* check "/", "%" and "\" (Win32) in URI */
  437. case sw_check_uri:
  438. if (usual[ch >> 5] & (1U << (ch & 0x1f))) {
  439. break;
  440. }
  441. switch (ch) {
  442. case '/':
  443. #if (NGX_WIN32)
  444. if (r->uri_ext == p) {
  445. r->complex_uri = 1;
  446. state = sw_uri;
  447. break;
  448. }
  449. #endif
  450. r->uri_ext = NULL;
  451. state = sw_after_slash_in_uri;
  452. break;
  453. case '.':
  454. r->uri_ext = p + 1;
  455. break;
  456. case ' ':
  457. r->uri_end = p;
  458. state = sw_http_09;
  459. break;
  460. case CR:
  461. r->uri_end = p;
  462. r->http_minor = 9;
  463. state = sw_almost_done;
  464. break;
  465. case LF:
  466. r->uri_end = p;
  467. r->http_minor = 9;
  468. goto done;
  469. #if (NGX_WIN32)
  470. case '\\':
  471. r->complex_uri = 1;
  472. state = sw_after_slash_in_uri;
  473. break;
  474. #endif
  475. case '%':
  476. r->quoted_uri = 1;
  477. state = sw_uri;
  478. break;
  479. case '?':
  480. r->args_start = p + 1;
  481. state = sw_uri;
  482. break;
  483. case '#':
  484. r->complex_uri = 1;
  485. state = sw_uri;
  486. break;
  487. case '+':
  488. r->plus_in_uri = 1;
  489. break;
  490. default:
  491. if (ch < 0x20 || ch == 0x7f) {
  492. return NGX_HTTP_PARSE_INVALID_REQUEST;
  493. }
  494. break;
  495. }
  496. break;
  497. /* URI */
  498. case sw_uri:
  499. if (usual[ch >> 5] & (1U << (ch & 0x1f))) {
  500. break;
  501. }
  502. switch (ch) {
  503. case ' ':
  504. r->uri_end = p;
  505. state = sw_http_09;
  506. break;
  507. case CR:
  508. r->uri_end = p;
  509. r->http_minor = 9;
  510. state = sw_almost_done;
  511. break;
  512. case LF:
  513. r->uri_end = p;
  514. r->http_minor = 9;
  515. goto done;
  516. case '#':
  517. r->complex_uri = 1;
  518. break;
  519. default:
  520. if (ch < 0x20 || ch == 0x7f) {
  521. return NGX_HTTP_PARSE_INVALID_REQUEST;
  522. }
  523. break;
  524. }
  525. break;
  526. /* space+ after URI */
  527. case sw_http_09:
  528. switch (ch) {
  529. case ' ':
  530. break;
  531. case CR:
  532. r->http_minor = 9;
  533. state = sw_almost_done;
  534. break;
  535. case LF:
  536. r->http_minor = 9;
  537. goto done;
  538. case 'H':
  539. r->http_protocol.data = p;
  540. state = sw_http_H;
  541. break;
  542. default:
  543. return NGX_HTTP_PARSE_INVALID_REQUEST;
  544. }
  545. break;
  546. case sw_http_H:
  547. switch (ch) {
  548. case 'T':
  549. state = sw_http_HT;
  550. break;
  551. default:
  552. return NGX_HTTP_PARSE_INVALID_REQUEST;
  553. }
  554. break;
  555. case sw_http_HT:
  556. switch (ch) {
  557. case 'T':
  558. state = sw_http_HTT;
  559. break;
  560. default:
  561. return NGX_HTTP_PARSE_INVALID_REQUEST;
  562. }
  563. break;
  564. case sw_http_HTT:
  565. switch (ch) {
  566. case 'P':
  567. state = sw_http_HTTP;
  568. break;
  569. default:
  570. return NGX_HTTP_PARSE_INVALID_REQUEST;
  571. }
  572. break;
  573. case sw_http_HTTP:
  574. switch (ch) {
  575. case '/':
  576. state = sw_first_major_digit;
  577. break;
  578. default:
  579. return NGX_HTTP_PARSE_INVALID_REQUEST;
  580. }
  581. break;
  582. /* first digit of major HTTP version */
  583. case sw_first_major_digit:
  584. if (ch < '1' || ch > '9') {
  585. return NGX_HTTP_PARSE_INVALID_REQUEST;
  586. }
  587. r->http_major = ch - '0';
  588. if (r->http_major > 1) {
  589. return NGX_HTTP_PARSE_INVALID_VERSION;
  590. }
  591. state = sw_major_digit;
  592. break;
  593. /* major HTTP version or dot */
  594. case sw_major_digit:
  595. if (ch == '.') {
  596. state = sw_first_minor_digit;
  597. break;
  598. }
  599. if (ch < '0' || ch > '9') {
  600. return NGX_HTTP_PARSE_INVALID_REQUEST;
  601. }
  602. r->http_major = r->http_major * 10 + (ch - '0');
  603. if (r->http_major > 1) {
  604. return NGX_HTTP_PARSE_INVALID_VERSION;
  605. }
  606. break;
  607. /* first digit of minor HTTP version */
  608. case sw_first_minor_digit:
  609. if (ch < '0' || ch > '9') {
  610. return NGX_HTTP_PARSE_INVALID_REQUEST;
  611. }
  612. r->http_minor = ch - '0';
  613. state = sw_minor_digit;
  614. break;
  615. /* minor HTTP version or end of request line */
  616. case sw_minor_digit:
  617. if (ch == CR) {
  618. state = sw_almost_done;
  619. break;
  620. }
  621. if (ch == LF) {
  622. goto done;
  623. }
  624. if (ch == ' ') {
  625. state = sw_spaces_after_digit;
  626. break;
  627. }
  628. if (ch < '0' || ch > '9') {
  629. return NGX_HTTP_PARSE_INVALID_REQUEST;
  630. }
  631. if (r->http_minor > 99) {
  632. return NGX_HTTP_PARSE_INVALID_REQUEST;
  633. }
  634. r->http_minor = r->http_minor * 10 + (ch - '0');
  635. break;
  636. case sw_spaces_after_digit:
  637. switch (ch) {
  638. case ' ':
  639. break;
  640. case CR:
  641. state = sw_almost_done;
  642. break;
  643. case LF:
  644. goto done;
  645. default:
  646. return NGX_HTTP_PARSE_INVALID_REQUEST;
  647. }
  648. break;
  649. /* end of request line */
  650. case sw_almost_done:
  651. r->request_end = p - 1;
  652. switch (ch) {
  653. case LF:
  654. goto done;
  655. default:
  656. return NGX_HTTP_PARSE_INVALID_REQUEST;
  657. }
  658. }
  659. }
  660. b->pos = p;
  661. r->state = state;
  662. return NGX_AGAIN;
  663. done:
  664. b->pos = p + 1;
  665. if (r->request_end == NULL) {
  666. r->request_end = p;
  667. }
  668. r->http_version = r->http_major * 1000 + r->http_minor;
  669. r->state = sw_start;
  670. if (r->http_version == 9 && r->method != NGX_HTTP_GET) {
  671. return NGX_HTTP_PARSE_INVALID_09_METHOD;
  672. }
  673. return NGX_OK;
  674. }
  675. ngx_int_t
  676. ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
  677. ngx_uint_t allow_underscores)
  678. {
  679. u_char c, ch, *p;
  680. ngx_uint_t hash, i;
  681. enum {
  682. sw_start = 0,
  683. sw_name,
  684. sw_space_before_value,
  685. sw_value,
  686. sw_space_after_value,
  687. sw_ignore_line,
  688. sw_almost_done,
  689. sw_header_almost_done
  690. } state;
  691. /* the last '\0' is not needed because string is zero terminated */
  692. static u_char lowcase[] =
  693. "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  694. "\0\0\0\0\0\0\0\0\0\0\0\0\0-\0\0" "0123456789\0\0\0\0\0\0"
  695. "\0abcdefghijklmnopqrstuvwxyz\0\0\0\0\0"
  696. "\0abcdefghijklmnopqrstuvwxyz\0\0\0\0\0"
  697. "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  698. "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  699. "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  700. "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
  701. state = r->state;
  702. hash = r->header_hash;
  703. i = r->lowcase_index;
  704. for (p = b->pos; p < b->last; p++) {
  705. ch = *p;
  706. switch (state) {
  707. /* first char */
  708. case sw_start:
  709. r->header_name_start = p;
  710. r->invalid_header = 0;
  711. switch (ch) {
  712. case CR:
  713. r->header_end = p;
  714. state = sw_header_almost_done;
  715. break;
  716. case LF:
  717. r->header_end = p;
  718. goto header_done;
  719. default:
  720. state = sw_name;
  721. c = lowcase[ch];
  722. if (c) {
  723. hash = ngx_hash(0, c);
  724. r->lowcase_header[0] = c;
  725. i = 1;
  726. break;
  727. }
  728. if (ch == '_') {
  729. if (allow_underscores) {
  730. hash = ngx_hash(0, ch);
  731. r->lowcase_header[0] = ch;
  732. i = 1;
  733. } else {
  734. hash = 0;
  735. i = 0;
  736. r->invalid_header = 1;
  737. }
  738. break;
  739. }
  740. if (ch <= 0x20 || ch == 0x7f || ch == ':') {
  741. r->header_end = p;
  742. return NGX_HTTP_PARSE_INVALID_HEADER;
  743. }
  744. hash = 0;
  745. i = 0;
  746. r->invalid_header = 1;
  747. break;
  748. }
  749. break;
  750. /* header name */
  751. case sw_name:
  752. c = lowcase[ch];
  753. if (c) {
  754. hash = ngx_hash(hash, c);
  755. r->lowcase_header[i++] = c;
  756. i &= (NGX_HTTP_LC_HEADER_LEN - 1);
  757. break;
  758. }
  759. if (ch == '_') {
  760. if (allow_underscores) {
  761. hash = ngx_hash(hash, ch);
  762. r->lowcase_header[i++] = ch;
  763. i &= (NGX_HTTP_LC_HEADER_LEN - 1);
  764. } else {
  765. r->invalid_header = 1;
  766. }
  767. break;
  768. }
  769. if (ch == ':') {
  770. r->header_name_end = p;
  771. state = sw_space_before_value;
  772. break;
  773. }
  774. if (ch == CR) {
  775. r->header_name_end = p;
  776. r->header_start = p;
  777. r->header_end = p;
  778. state = sw_almost_done;
  779. break;
  780. }
  781. if (ch == LF) {
  782. r->header_name_end = p;
  783. r->header_start = p;
  784. r->header_end = p;
  785. goto done;
  786. }
  787. /* IIS may send the duplicate "HTTP/1.1 ..." lines */
  788. if (ch == '/'
  789. && r->upstream
  790. && p - r->header_name_start == 4
  791. && ngx_strncmp(r->header_name_start, "HTTP", 4) == 0)
  792. {
  793. state = sw_ignore_line;
  794. break;
  795. }
  796. if (ch <= 0x20 || ch == 0x7f) {
  797. r->header_end = p;
  798. return NGX_HTTP_PARSE_INVALID_HEADER;
  799. }
  800. r->invalid_header = 1;
  801. break;
  802. /* space* before header value */
  803. case sw_space_before_value:
  804. switch (ch) {
  805. case ' ':
  806. break;
  807. case CR:
  808. r->header_start = p;
  809. r->header_end = p;
  810. state = sw_almost_done;
  811. break;
  812. case LF:
  813. r->header_start = p;
  814. r->header_end = p;
  815. goto done;
  816. case '\0':
  817. r->header_end = p;
  818. return NGX_HTTP_PARSE_INVALID_HEADER;
  819. default:
  820. r->header_start = p;
  821. state = sw_value;
  822. break;
  823. }
  824. break;
  825. /* header value */
  826. case sw_value:
  827. switch (ch) {
  828. case ' ':
  829. r->header_end = p;
  830. state = sw_space_after_value;
  831. break;
  832. case CR:
  833. r->header_end = p;
  834. state = sw_almost_done;
  835. break;
  836. case LF:
  837. r->header_end = p;
  838. goto done;
  839. case '\0':
  840. r->header_end = p;
  841. return NGX_HTTP_PARSE_INVALID_HEADER;
  842. }
  843. break;
  844. /* space* before end of header line */
  845. case sw_space_after_value:
  846. switch (ch) {
  847. case ' ':
  848. break;
  849. case CR:
  850. state = sw_almost_done;
  851. break;
  852. case LF:
  853. goto done;
  854. case '\0':
  855. r->header_end = p;
  856. return NGX_HTTP_PARSE_INVALID_HEADER;
  857. default:
  858. state = sw_value;
  859. break;
  860. }
  861. break;
  862. /* ignore header line */
  863. case sw_ignore_line:
  864. switch (ch) {
  865. case LF:
  866. state = sw_start;
  867. break;
  868. default:
  869. break;
  870. }
  871. break;
  872. /* end of header line */
  873. case sw_almost_done:
  874. switch (ch) {
  875. case LF:
  876. goto done;
  877. case CR:
  878. break;
  879. default:
  880. return NGX_HTTP_PARSE_INVALID_HEADER;
  881. }
  882. break;
  883. /* end of header */
  884. case sw_header_almost_done:
  885. switch (ch) {
  886. case LF:
  887. goto header_done;
  888. default:
  889. return NGX_HTTP_PARSE_INVALID_HEADER;
  890. }
  891. }
  892. }
  893. b->pos = p;
  894. r->state = state;
  895. r->header_hash = hash;
  896. r->lowcase_index = i;
  897. return NGX_AGAIN;
  898. done:
  899. b->pos = p + 1;
  900. r->state = sw_start;
  901. r->header_hash = hash;
  902. r->lowcase_index = i;
  903. return NGX_OK;
  904. header_done:
  905. b->pos = p + 1;
  906. r->state = sw_start;
  907. return NGX_HTTP_PARSE_HEADER_DONE;
  908. }
  909. ngx_int_t
  910. ngx_http_parse_uri(ngx_http_request_t *r)
  911. {
  912. u_char *p, ch;
  913. enum {
  914. sw_start = 0,
  915. sw_after_slash_in_uri,
  916. sw_check_uri,
  917. sw_uri
  918. } state;
  919. state = sw_start;
  920. for (p = r->uri_start; p != r->uri_end; p++) {
  921. ch = *p;
  922. switch (state) {
  923. case sw_start:
  924. if (ch != '/') {
  925. return NGX_ERROR;
  926. }
  927. state = sw_after_slash_in_uri;
  928. break;
  929. /* check "/.", "//", "%", and "\" (Win32) in URI */
  930. case sw_after_slash_in_uri:
  931. if (usual[ch >> 5] & (1U << (ch & 0x1f))) {
  932. state = sw_check_uri;
  933. break;
  934. }
  935. switch (ch) {
  936. case '.':
  937. r->complex_uri = 1;
  938. state = sw_uri;
  939. break;
  940. case '%':
  941. r->quoted_uri = 1;
  942. state = sw_uri;
  943. break;
  944. case '/':
  945. r->complex_uri = 1;
  946. state = sw_uri;
  947. break;
  948. #if (NGX_WIN32)
  949. case '\\':
  950. r->complex_uri = 1;
  951. state = sw_uri;
  952. break;
  953. #endif
  954. case '?':
  955. r->args_start = p + 1;
  956. state = sw_uri;
  957. break;
  958. case '#':
  959. r->complex_uri = 1;
  960. state = sw_uri;
  961. break;
  962. case '+':
  963. r->plus_in_uri = 1;
  964. break;
  965. default:
  966. if (ch <= 0x20 || ch == 0x7f) {
  967. return NGX_ERROR;
  968. }
  969. state = sw_check_uri;
  970. break;
  971. }
  972. break;
  973. /* check "/", "%" and "\" (Win32) in URI */
  974. case sw_check_uri:
  975. if (usual[ch >> 5] & (1U << (ch & 0x1f))) {
  976. break;
  977. }
  978. switch (ch) {
  979. case '/':
  980. #if (NGX_WIN32)
  981. if (r->uri_ext == p) {
  982. r->complex_uri = 1;
  983. state = sw_uri;
  984. break;
  985. }
  986. #endif
  987. r->uri_ext = NULL;
  988. state = sw_after_slash_in_uri;
  989. break;
  990. case '.':
  991. r->uri_ext = p + 1;
  992. break;
  993. #if (NGX_WIN32)
  994. case '\\':
  995. r->complex_uri = 1;
  996. state = sw_after_slash_in_uri;
  997. break;
  998. #endif
  999. case '%':
  1000. r->quoted_uri = 1;
  1001. state = sw_uri;
  1002. break;
  1003. case '?':
  1004. r->args_start = p + 1;
  1005. state = sw_uri;
  1006. break;
  1007. case '#':
  1008. r->complex_uri = 1;
  1009. state = sw_uri;
  1010. break;
  1011. case '+':
  1012. r->plus_in_uri = 1;
  1013. break;
  1014. default:
  1015. if (ch <= 0x20 || ch == 0x7f) {
  1016. return NGX_ERROR;
  1017. }
  1018. break;
  1019. }
  1020. break;
  1021. /* URI */
  1022. case sw_uri:
  1023. if (usual[ch >> 5] & (1U << (ch & 0x1f))) {
  1024. break;
  1025. }
  1026. switch (ch) {
  1027. case '#':
  1028. r->complex_uri = 1;
  1029. break;
  1030. default:
  1031. if (ch <= 0x20 || ch == 0x7f) {
  1032. return NGX_ERROR;
  1033. }
  1034. break;
  1035. }
  1036. break;
  1037. }
  1038. }
  1039. return NGX_OK;
  1040. }
  1041. ngx_int_t
  1042. ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
  1043. {
  1044. u_char c, ch, decoded, *p, *u;
  1045. enum {
  1046. sw_usual = 0,
  1047. sw_slash,
  1048. sw_dot,
  1049. sw_dot_dot,
  1050. sw_quoted,
  1051. sw_quoted_second
  1052. } state, quoted_state;
  1053. #if (NGX_SUPPRESS_WARN)
  1054. decoded = '\0';
  1055. quoted_state = sw_usual;
  1056. #endif
  1057. state = sw_usual;
  1058. p = r->uri_start;
  1059. u = r->uri.data;
  1060. r->uri_ext = NULL;
  1061. r->args_start = NULL;
  1062. if (r->empty_path_in_uri) {
  1063. *u++ = '/';
  1064. }
  1065. ch = *p++;
  1066. while (p <= r->uri_end) {
  1067. /*
  1068. * we use "ch = *p++" inside the cycle, but this operation is safe,
  1069. * because after the URI there is always at least one character:
  1070. * the line feed
  1071. */
  1072. ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1073. "s:%d in:'%Xd:%c'", state, ch, ch);
  1074. switch (state) {
  1075. case sw_usual:
  1076. if (usual[ch >> 5] & (1U << (ch & 0x1f))) {
  1077. *u++ = ch;
  1078. ch = *p++;
  1079. break;
  1080. }
  1081. switch (ch) {
  1082. #if (NGX_WIN32)
  1083. case '\\':
  1084. if (u - 2 >= r->uri.data
  1085. && *(u - 1) == '.' && *(u - 2) != '.')
  1086. {
  1087. u--;
  1088. }
  1089. r->uri_ext = NULL;
  1090. if (p == r->uri_start + r->uri.len) {
  1091. /*
  1092. * we omit the last "\" to cause redirect because
  1093. * the browsers do not treat "\" as "/" in relative URL path
  1094. */
  1095. break;
  1096. }
  1097. state = sw_slash;
  1098. *u++ = '/';
  1099. break;
  1100. #endif
  1101. case '/':
  1102. #if (NGX_WIN32)
  1103. if (u - 2 >= r->uri.data
  1104. && *(u - 1) == '.' && *(u - 2) != '.')
  1105. {
  1106. u--;
  1107. }
  1108. #endif
  1109. r->uri_ext = NULL;
  1110. state = sw_slash;
  1111. *u++ = ch;
  1112. break;
  1113. case '%':
  1114. quoted_state = state;
  1115. state = sw_quoted;
  1116. break;
  1117. case '?':
  1118. r->args_start = p;
  1119. goto args;
  1120. case '#':
  1121. goto done;
  1122. case '.':
  1123. r->uri_ext = u + 1;
  1124. *u++ = ch;
  1125. break;
  1126. case '+':
  1127. r->plus_in_uri = 1;
  1128. /* fall through */
  1129. default:
  1130. *u++ = ch;
  1131. break;
  1132. }
  1133. ch = *p++;
  1134. break;
  1135. case sw_slash:
  1136. if (usual[ch >> 5] & (1U << (ch & 0x1f))) {
  1137. state = sw_usual;
  1138. *u++ = ch;
  1139. ch = *p++;
  1140. break;
  1141. }
  1142. switch (ch) {
  1143. #if (NGX_WIN32)
  1144. case '\\':
  1145. break;
  1146. #endif
  1147. case '/':
  1148. if (!merge_slashes) {
  1149. *u++ = ch;
  1150. }
  1151. break;
  1152. case '.':
  1153. state = sw_dot;
  1154. *u++ = ch;
  1155. break;
  1156. case '%':
  1157. quoted_state = state;
  1158. state = sw_quoted;
  1159. break;
  1160. case '?':
  1161. r->args_start = p;
  1162. goto args;
  1163. case '#':
  1164. goto done;
  1165. case '+':
  1166. r->plus_in_uri = 1;
  1167. /* fall through */
  1168. default:
  1169. state = sw_usual;
  1170. *u++ = ch;
  1171. break;
  1172. }
  1173. ch = *p++;
  1174. break;
  1175. case sw_dot:
  1176. if (usual[ch >> 5] & (1U << (ch & 0x1f))) {
  1177. state = sw_usual;
  1178. *u++ = ch;
  1179. ch = *p++;
  1180. break;
  1181. }
  1182. switch (ch) {
  1183. #if (NGX_WIN32)
  1184. case '\\':
  1185. #endif
  1186. case '/':
  1187. state = sw_slash;
  1188. u--;
  1189. break;
  1190. case '.':
  1191. state = sw_dot_dot;
  1192. *u++ = ch;
  1193. break;
  1194. case '%':
  1195. quoted_state = state;
  1196. state = sw_quoted;
  1197. break;
  1198. case '?':
  1199. u--;
  1200. r->args_start = p;
  1201. goto args;
  1202. case '#':
  1203. u--;
  1204. goto done;
  1205. case '+':
  1206. r->plus_in_uri = 1;
  1207. /* fall through */
  1208. default:
  1209. state = sw_usual;
  1210. *u++ = ch;
  1211. break;
  1212. }
  1213. ch = *p++;
  1214. break;
  1215. case sw_dot_dot:
  1216. if (usual[ch >> 5] & (1U << (ch & 0x1f))) {
  1217. state = sw_usual;
  1218. *u++ = ch;
  1219. ch = *p++;
  1220. break;
  1221. }
  1222. switch (ch) {
  1223. #if (NGX_WIN32)
  1224. case '\\':
  1225. #endif
  1226. case '/':
  1227. case '?':
  1228. case '#':
  1229. u -= 4;
  1230. for ( ;; ) {
  1231. if (u < r->uri.data) {
  1232. return NGX_HTTP_PARSE_INVALID_REQUEST;
  1233. }
  1234. if (*u == '/') {
  1235. u++;
  1236. break;
  1237. }
  1238. u--;
  1239. }
  1240. if (ch == '?') {
  1241. r->args_start = p;
  1242. goto args;
  1243. }
  1244. if (ch == '#') {
  1245. goto done;
  1246. }
  1247. state = sw_slash;
  1248. break;
  1249. case '%':
  1250. quoted_state = state;
  1251. state = sw_quoted;
  1252. break;
  1253. case '+':
  1254. r->plus_in_uri = 1;
  1255. /* fall through */
  1256. default:
  1257. state = sw_usual;
  1258. *u++ = ch;
  1259. break;
  1260. }
  1261. ch = *p++;
  1262. break;
  1263. case sw_quoted:
  1264. r->quoted_uri = 1;
  1265. if (ch >= '0' && ch <= '9') {
  1266. decoded = (u_char) (ch - '0');
  1267. state = sw_quoted_second;
  1268. ch = *p++;
  1269. break;
  1270. }
  1271. c = (u_char) (ch | 0x20);
  1272. if (c >= 'a' && c <= 'f') {
  1273. decoded = (u_char) (c - 'a' + 10);
  1274. state = sw_quoted_second;
  1275. ch = *p++;
  1276. break;
  1277. }
  1278. return NGX_HTTP_PARSE_INVALID_REQUEST;
  1279. case sw_quoted_second:
  1280. if (ch >= '0' && ch <= '9') {
  1281. ch = (u_char) ((decoded << 4) + (ch - '0'));
  1282. if (ch == '%' || ch == '#') {
  1283. state = sw_usual;
  1284. *u++ = ch;
  1285. ch = *p++;
  1286. break;
  1287. } else if (ch == '\0') {
  1288. return NGX_HTTP_PARSE_INVALID_REQUEST;
  1289. }
  1290. state = quoted_state;
  1291. break;
  1292. }
  1293. c = (u_char) (ch | 0x20);
  1294. if (c >= 'a' && c <= 'f') {
  1295. ch = (u_char) ((decoded << 4) + (c - 'a') + 10);
  1296. if (ch == '?') {
  1297. state = sw_usual;
  1298. *u++ = ch;
  1299. ch = *p++;
  1300. break;
  1301. } else if (ch == '+') {
  1302. r->plus_in_uri = 1;
  1303. }
  1304. state = quoted_state;
  1305. break;
  1306. }
  1307. return NGX_HTTP_PARSE_INVALID_REQUEST;
  1308. }
  1309. }
  1310. if (state == sw_quoted || state == sw_quoted_second) {
  1311. return NGX_HTTP_PARSE_INVALID_REQUEST;
  1312. }
  1313. if (state == sw_dot) {
  1314. u--;
  1315. } else if (state == sw_dot_dot) {
  1316. u -= 4;
  1317. for ( ;; ) {
  1318. if (u < r->uri.data) {
  1319. return NGX_HTTP_PARSE_INVALID_REQUEST;
  1320. }
  1321. if (*u == '/') {
  1322. u++;
  1323. break;
  1324. }
  1325. u--;
  1326. }
  1327. }
  1328. done:
  1329. r->uri.len = u - r->uri.data;
  1330. if (r->uri_ext) {
  1331. r->exten.len = u - r->uri_ext;
  1332. r->exten.data = r->uri_ext;
  1333. }
  1334. r->uri_ext = NULL;
  1335. return NGX_OK;
  1336. args:
  1337. while (p < r->uri_end) {
  1338. if (*p++ != '#') {
  1339. continue;
  1340. }
  1341. r->args.len = p - 1 - r->args_start;
  1342. r->args.data = r->args_start;
  1343. r->args_start = NULL;
  1344. break;
  1345. }
  1346. r->uri.len = u - r->uri.data;
  1347. if (r->uri_ext) {
  1348. r->exten.len = u - r->uri_ext;
  1349. r->exten.data = r->uri_ext;
  1350. }
  1351. r->uri_ext = NULL;
  1352. return NGX_OK;
  1353. }
  1354. ngx_int_t
  1355. ngx_http_parse_status_line(ngx_http_request_t *r, ngx_buf_t *b,
  1356. ngx_http_status_t *status)
  1357. {
  1358. u_char ch;
  1359. u_char *p;
  1360. enum {
  1361. sw_start = 0,
  1362. sw_H,
  1363. sw_HT,
  1364. sw_HTT,
  1365. sw_HTTP,
  1366. sw_first_major_digit,
  1367. sw_major_digit,
  1368. sw_first_minor_digit,
  1369. sw_minor_digit,
  1370. sw_status,
  1371. sw_space_after_status,
  1372. sw_status_text,
  1373. sw_almost_done
  1374. } state;
  1375. state = r->state;
  1376. for (p = b->pos; p < b->last; p++) {
  1377. ch = *p;
  1378. switch (state) {
  1379. /* "HTTP/" */
  1380. case sw_start:
  1381. switch (ch) {
  1382. case 'H':
  1383. state = sw_H;
  1384. break;
  1385. default:
  1386. return NGX_ERROR;
  1387. }
  1388. break;
  1389. case sw_H:
  1390. switch (ch) {
  1391. case 'T':
  1392. state = sw_HT;
  1393. break;
  1394. default:
  1395. return NGX_ERROR;
  1396. }
  1397. break;
  1398. case sw_HT:
  1399. switch (ch) {
  1400. case 'T':
  1401. state = sw_HTT;
  1402. break;
  1403. default:
  1404. return NGX_ERROR;
  1405. }
  1406. break;
  1407. case sw_HTT:
  1408. switch (ch) {
  1409. case 'P':
  1410. state = sw_HTTP;
  1411. break;
  1412. default:
  1413. return NGX_ERROR;
  1414. }
  1415. break;
  1416. case sw_HTTP:
  1417. switch (ch) {
  1418. case '/':
  1419. state = sw_first_major_digit;
  1420. break;
  1421. default:
  1422. return NGX_ERROR;
  1423. }
  1424. break;
  1425. /* the first digit of major HTTP version */
  1426. case sw_first_major_digit:
  1427. if (ch < '1' || ch > '9') {
  1428. return NGX_ERROR;
  1429. }
  1430. r->http_major = ch - '0';
  1431. state = sw_major_digit;
  1432. break;
  1433. /* the major HTTP version or dot */
  1434. case sw_major_digit:
  1435. if (ch == '.') {
  1436. state = sw_first_minor_digit;
  1437. break;
  1438. }
  1439. if (ch < '0' || ch > '9') {
  1440. return NGX_ERROR;
  1441. }
  1442. if (r->http_major > 99) {
  1443. return NGX_ERROR;
  1444. }
  1445. r->http_major = r->http_major * 10 + (ch - '0');
  1446. break;
  1447. /* the first digit of minor HTTP version */
  1448. case sw_first_minor_digit:
  1449. if (ch < '0' || ch > '9') {
  1450. return NGX_ERROR;
  1451. }
  1452. r->http_minor = ch - '0';
  1453. state = sw_minor_digit;
  1454. break;
  1455. /* the minor HTTP version or the end of the request line */
  1456. case sw_minor_digit:
  1457. if (ch == ' ') {
  1458. state = sw_status;
  1459. break;
  1460. }
  1461. if (ch < '0' || ch > '9') {
  1462. return NGX_ERROR;
  1463. }
  1464. if (r->http_minor > 99) {
  1465. return NGX_ERROR;
  1466. }
  1467. r->http_minor = r->http_minor * 10 + (ch - '0');
  1468. break;
  1469. /* HTTP status code */
  1470. case sw_status:
  1471. if (ch == ' ') {
  1472. break;
  1473. }
  1474. if (ch < '0' || ch > '9') {
  1475. return NGX_ERROR;
  1476. }
  1477. status->code = status->code * 10 + (ch - '0');
  1478. if (++status->count == 3) {
  1479. state = sw_space_after_status;
  1480. status->start = p - 2;
  1481. }
  1482. break;
  1483. /* space or end of line */
  1484. case sw_space_after_status:
  1485. switch (ch) {
  1486. case ' ':
  1487. state = sw_status_text;
  1488. break;
  1489. case '.': /* IIS may send 403.1, 403.2, etc */
  1490. state = sw_status_text;
  1491. break;
  1492. case CR:
  1493. state = sw_almost_done;
  1494. break;
  1495. case LF:
  1496. goto done;
  1497. default:
  1498. return NGX_ERROR;
  1499. }
  1500. break;
  1501. /* any text until end of line */
  1502. case sw_status_text:
  1503. switch (ch) {
  1504. case CR:
  1505. state = sw_almost_done;
  1506. break;
  1507. case LF:
  1508. goto done;
  1509. }
  1510. break;
  1511. /* end of status line */
  1512. case sw_almost_done:
  1513. status->end = p - 1;
  1514. switch (ch) {
  1515. case LF:
  1516. goto done;
  1517. default:
  1518. return NGX_ERROR;
  1519. }
  1520. }
  1521. }
  1522. b->pos = p;
  1523. r->state = state;
  1524. return NGX_AGAIN;
  1525. done:
  1526. b->pos = p + 1;
  1527. if (status->end == NULL) {
  1528. status->end = p;
  1529. }
  1530. status->http_version = r->http_major * 1000 + r->http_minor;
  1531. r->state = sw_start;
  1532. return NGX_OK;
  1533. }
  1534. ngx_int_t
  1535. ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri,
  1536. ngx_str_t *args, ngx_uint_t *flags)
  1537. {
  1538. u_char ch, *p, *src, *dst;
  1539. size_t len;
  1540. ngx_uint_t quoted;
  1541. len = uri->len;
  1542. p = uri->data;
  1543. quoted = 0;
  1544. if (len == 0 || p[0] == '?') {
  1545. goto unsafe;
  1546. }
  1547. if (p[0] == '.' && len > 1 && p[1] == '.'
  1548. && (len == 2 || ngx_path_separator(p[2])))
  1549. {
  1550. goto unsafe;
  1551. }
  1552. for ( /* void */ ; len; len--) {
  1553. ch = *p++;
  1554. if (ch == '%') {
  1555. quoted = 1;
  1556. continue;
  1557. }
  1558. if (usual[ch >> 5] & (1U << (ch & 0x1f))) {
  1559. continue;
  1560. }
  1561. if (ch == '?') {
  1562. args->len = len - 1;
  1563. args->data = p;
  1564. uri->len -= len;
  1565. break;
  1566. }
  1567. if (ch == '\0') {
  1568. goto unsafe;
  1569. }
  1570. if (ngx_path_separator(ch) && len > 2) {
  1571. /* detect "/../" and "/.." */
  1572. if (p[0] == '.' && p[1] == '.'
  1573. && (len == 3 || ngx_path_separator(p[2])))
  1574. {
  1575. goto unsafe;
  1576. }
  1577. }
  1578. }
  1579. if (quoted) {
  1580. ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1581. "escaped URI: \"%V\"", uri);
  1582. src = uri->data;
  1583. dst = ngx_pnalloc(r->pool, uri->len);
  1584. if (dst == NULL) {
  1585. return NGX_ERROR;
  1586. }
  1587. uri->data = dst;
  1588. ngx_unescape_uri(&dst, &src, uri->len, 0);
  1589. uri->len = dst - uri->data;
  1590. ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1591. "unescaped URI: \"%V\"", uri);
  1592. len = uri->len;
  1593. p = uri->data;
  1594. if (p[0] == '.' && len > 1 && p[1] == '.'
  1595. && (len == 2 || ngx_path_separator(p[2])))
  1596. {
  1597. goto unsafe;
  1598. }
  1599. for ( /* void */ ; len; len--) {
  1600. ch = *p++;
  1601. if (ch == '\0') {
  1602. goto unsafe;
  1603. }
  1604. if (ngx_path_separator(ch) && len > 2) {
  1605. /* detect "/../" and "/.." */
  1606. if (p[0] == '.' && p[1] == '.'
  1607. && (len == 3 || ngx_path_separator(p[2])))
  1608. {
  1609. goto unsafe;
  1610. }
  1611. }
  1612. }
  1613. }
  1614. return NGX_OK;
  1615. unsafe:
  1616. if (*flags & NGX_HTTP_LOG_UNSAFE) {
  1617. ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1618. "unsafe URI \"%V\" was detected", uri);
  1619. }
  1620. return NGX_ERROR;
  1621. }
  1622. ngx_table_elt_t *
  1623. ngx_http_parse_multi_header_lines(ngx_http_request_t *r,
  1624. ngx_table_elt_t *headers, ngx_str_t *name, ngx_str_t *value)
  1625. {
  1626. u_char *start, *last, *end, ch;
  1627. ngx_table_elt_t *h;
  1628. for (h = headers; h; h = h->next) {
  1629. ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1630. "parse header: \"%V: %V\"", &h->key, &h->value);
  1631. if (name->len > h->value.len) {
  1632. continue;
  1633. }
  1634. start = h->value.data;
  1635. end = h->value.data + h->value.len;
  1636. while (start < end) {
  1637. if (ngx_strncasecmp(start, name->data, name->len) != 0) {
  1638. goto skip;
  1639. }
  1640. for (start += name->len; start < end && *start == ' '; start++) {
  1641. /* void */
  1642. }
  1643. if (value == NULL) {
  1644. if (start == end || *start == ',') {
  1645. return h;
  1646. }
  1647. goto skip;
  1648. }
  1649. if (start == end || *start++ != '=') {
  1650. /* the invalid header value */
  1651. goto skip;
  1652. }
  1653. while (start < end && *start == ' ') { start++; }
  1654. for (last = start; last < end && *last != ';'; last++) {
  1655. /* void */
  1656. }
  1657. value->len = last - start;
  1658. value->data = start;
  1659. return h;
  1660. skip:
  1661. while (start < end) {
  1662. ch = *start++;
  1663. if (ch == ';' || ch == ',') {
  1664. break;
  1665. }
  1666. }
  1667. while (start < end && *start == ' ') { start++; }
  1668. }
  1669. }
  1670. return NULL;
  1671. }
  1672. ngx_table_elt_t *
  1673. ngx_http_parse_set_cookie_lines(ngx_http_request_t *r,
  1674. ngx_table_elt_t *headers, ngx_str_t *name, ngx_str_t *value)
  1675. {
  1676. u_char *start, *last, *end;
  1677. ngx_table_elt_t *h;
  1678. for (h = headers; h; h = h->next) {
  1679. ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1680. "parse header: \"%V: %V\"", &h->key, &h->value);
  1681. if (name->len >= h->value.len) {
  1682. continue;
  1683. }
  1684. start = h->value.data;
  1685. end = h->value.data + h->value.len;
  1686. if (ngx_strncasecmp(start, name->data, name->len) != 0) {
  1687. continue;
  1688. }
  1689. for (start += name->len; start < end && *start == ' '; start++) {
  1690. /* void */
  1691. }
  1692. if (start == end || *start++ != '=') {
  1693. /* the invalid header value */
  1694. continue;
  1695. }
  1696. while (start < end && *start == ' ') { start++; }
  1697. for (last = start; last < end && *last != ';'; last++) {
  1698. /* void */
  1699. }
  1700. value->len = last - start;
  1701. value->data = start;
  1702. return h;
  1703. }
  1704. return NULL;
  1705. }
  1706. ngx_int_t
  1707. ngx_http_arg(ngx_http_request_t *r, u_char *name, size_t len, ngx_str_t *value)
  1708. {
  1709. u_char *p, *last;
  1710. if (r->args.len == 0) {
  1711. return NGX_DECLINED;
  1712. }
  1713. p = r->args.data;
  1714. last = p + r->args.len;
  1715. for ( /* void */ ; p < last; p++) {
  1716. /* we need '=' after name, so drop one char from last */
  1717. p = ngx_strlcasestrn(p, last - 1, name, len - 1);
  1718. if (p == NULL) {
  1719. return NGX_DECLINED;
  1720. }
  1721. if ((p == r->args.data || *(p - 1) == '&') && *(p + len) == '=') {
  1722. value->data = p + len + 1;
  1723. p = ngx_strlchr(p, last, '&');
  1724. if (p == NULL) {
  1725. p = r->args.data + r->args.len;
  1726. }
  1727. value->len = p - value->data;
  1728. return NGX_OK;
  1729. }
  1730. }
  1731. return NGX_DECLINED;
  1732. }
  1733. void
  1734. ngx_http_split_args(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args)
  1735. {
  1736. u_char *p, *last;
  1737. last = uri->data + uri->len;
  1738. p = ngx_strlchr(uri->data, last, '?');
  1739. if (p) {
  1740. uri->len = p - uri->data;
  1741. p++;
  1742. args->len = last - p;
  1743. args->data = p;
  1744. } else {
  1745. args->len = 0;
  1746. }
  1747. }
  1748. ngx_int_t
  1749. ngx_http_parse_chunked(ngx_http_request_t *r, ngx_buf_t *b,
  1750. ngx_http_chunked_t *ctx, ngx_uint_t keep_trailers)
  1751. {
  1752. u_char *pos, ch, c;
  1753. ngx_int_t rc;
  1754. enum {
  1755. sw_chunk_start = 0,
  1756. sw_chunk_size,
  1757. sw_chunk_extension,
  1758. sw_chunk_extension_almost_done,
  1759. sw_chunk_data,
  1760. sw_after_data,
  1761. sw_after_data_almost_done,
  1762. sw_last_chunk_extension,
  1763. sw_last_chunk_extension_almost_done,
  1764. sw_trailer,
  1765. sw_trailer_almost_done,
  1766. sw_trailer_header,
  1767. sw_trailer_header_almost_done
  1768. } state;
  1769. state = ctx->state;
  1770. if (state == sw_chunk_data && ctx->size == 0) {
  1771. state = sw_after_data;
  1772. }
  1773. rc = NGX_AGAIN;
  1774. for (pos = b->pos; pos < b->last; pos++) {
  1775. ch = *pos;
  1776. ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1777. "http chunked byte: %02Xd s:%d", ch, state);
  1778. switch (state) {
  1779. case sw_chunk_start:
  1780. if (ch >= '0' && ch <= '9') {
  1781. state = sw_chunk_size;
  1782. ctx->size = ch - '0';
  1783. break;
  1784. }
  1785. c = (u_char) (ch | 0x20);
  1786. if (c >= 'a' && c <= 'f') {
  1787. state = sw_chunk_size;
  1788. ctx->size = c - 'a' + 10;
  1789. break;
  1790. }
  1791. goto invalid;
  1792. case sw_chunk_size:
  1793. if (ctx->size > NGX_MAX_OFF_T_VALUE / 16) {
  1794. goto invalid;
  1795. }
  1796. if (ch >= '0' && ch <= '9') {
  1797. ctx->size = ctx->size * 16 + (ch - '0');
  1798. break;
  1799. }
  1800. c = (u_char) (ch | 0x20);
  1801. if (c >= 'a' && c <= 'f') {
  1802. ctx->size = ctx->size * 16 + (c - 'a' + 10);
  1803. break;
  1804. }
  1805. if (ctx->size == 0) {
  1806. switch (ch) {
  1807. case CR:
  1808. state = sw_last_chunk_extension_almost_done;
  1809. break;
  1810. case LF:
  1811. if (keep_trailers) {
  1812. goto done;
  1813. }
  1814. state = sw_trailer;
  1815. break;
  1816. case ';':
  1817. case ' ':
  1818. case '\t':
  1819. state = sw_last_chunk_extension;
  1820. break;
  1821. default:
  1822. goto invalid;
  1823. }
  1824. break;
  1825. }
  1826. switch (ch) {
  1827. case CR:
  1828. state = sw_chunk_extension_almost_done;
  1829. break;
  1830. case LF:
  1831. state = sw_chunk_data;
  1832. break;
  1833. case ';':
  1834. case ' ':
  1835. case '\t':
  1836. state = sw_chunk_extension;
  1837. break;
  1838. default:
  1839. goto invalid;
  1840. }
  1841. break;
  1842. case sw_chunk_extension:
  1843. switch (ch) {
  1844. case CR:
  1845. state = sw_chunk_extension_almost_done;
  1846. break;
  1847. case LF:
  1848. state = sw_chunk_data;
  1849. }
  1850. break;
  1851. case sw_chunk_extension_almost_done:
  1852. if (ch == LF) {
  1853. state = sw_chunk_data;
  1854. break;
  1855. }
  1856. goto invalid;
  1857. case sw_chunk_data:
  1858. rc = NGX_OK;
  1859. goto data;
  1860. case sw_after_data:
  1861. switch (ch) {
  1862. case CR:
  1863. state = sw_after_data_almost_done;
  1864. break;
  1865. case LF:
  1866. state = sw_chunk_start;
  1867. break;
  1868. default:
  1869. goto invalid;
  1870. }
  1871. break;
  1872. case sw_after_data_almost_done:
  1873. if (ch == LF) {
  1874. state = sw_chunk_start;
  1875. break;
  1876. }
  1877. goto invalid;
  1878. case sw_last_chunk_extension:
  1879. switch (ch) {
  1880. case CR:
  1881. state = sw_last_chunk_extension_almost_done;
  1882. break;
  1883. case LF:
  1884. if (keep_trailers) {
  1885. goto done;
  1886. }
  1887. state = sw_trailer;
  1888. }
  1889. break;
  1890. case sw_last_chunk_extension_almost_done:
  1891. if (ch == LF) {
  1892. if (keep_trailers) {
  1893. goto done;
  1894. }
  1895. state = sw_trailer;
  1896. break;
  1897. }
  1898. goto invalid;
  1899. case sw_trailer:
  1900. switch (ch) {
  1901. case CR:
  1902. state = sw_trailer_almost_done;
  1903. break;
  1904. case LF:
  1905. goto done;
  1906. default:
  1907. state = sw_trailer_header;
  1908. }
  1909. break;
  1910. case sw_trailer_almost_done:
  1911. if (ch == LF) {
  1912. goto done;
  1913. }
  1914. goto invalid;
  1915. case sw_trailer_header:
  1916. switch (ch) {
  1917. case CR:
  1918. state = sw_trailer_header_almost_done;
  1919. break;
  1920. case LF:
  1921. state = sw_trailer;
  1922. }
  1923. break;
  1924. case sw_trailer_header_almost_done:
  1925. if (ch == LF) {
  1926. state = sw_trailer;
  1927. break;
  1928. }
  1929. goto invalid;
  1930. }
  1931. }
  1932. data:
  1933. ctx->state = state;
  1934. b->pos = pos;
  1935. if (ctx->size > NGX_MAX_OFF_T_VALUE - 5) {
  1936. goto invalid;
  1937. }
  1938. switch (state) {
  1939. case sw_chunk_start:
  1940. ctx->length = 3 /* "0" LF LF */;
  1941. break;
  1942. case sw_chunk_size:
  1943. ctx->length = 1 /* LF */
  1944. + (ctx->size ? ctx->size + 4 /* LF "0" LF LF */
  1945. : 1 /* LF */);
  1946. break;
  1947. case sw_chunk_extension:
  1948. case sw_chunk_extension_almost_done:
  1949. ctx->length = 1 /* LF */ + ctx->size + 4 /* LF "0" LF LF */;
  1950. break;
  1951. case sw_chunk_data:
  1952. ctx->length = ctx->size + 4 /* LF "0" LF LF */;
  1953. break;
  1954. case sw_after_data:
  1955. case sw_after_data_almost_done:
  1956. ctx->length = 4 /* LF "0" LF LF */;
  1957. break;
  1958. case sw_last_chunk_extension:
  1959. case sw_last_chunk_extension_almost_done:
  1960. ctx->length = 2 /* LF LF */;
  1961. break;
  1962. case sw_trailer:
  1963. case sw_trailer_almost_done:
  1964. ctx->length = 1 /* LF */;
  1965. break;
  1966. case sw_trailer_header:
  1967. case sw_trailer_header_almost_done:
  1968. ctx->length = 2 /* LF LF */;
  1969. break;
  1970. }
  1971. return rc;
  1972. done:
  1973. ctx->state = 0;
  1974. b->pos = pos + 1;
  1975. return NGX_DONE;
  1976. invalid:
  1977. return NGX_ERROR;
  1978. }