I'm Zuwen Shi from China,I find a unescape uri bug in your program.<br><div class="gmail_quote">The source code location is src\core\ngx_string.c->ngx_unescape_uri<br>If I put a string "%%s%elect",it convert the string to "%slect",and %% to %,%el to l,actually the right convert is "%%s%elect".<br>
So,I patch the ngx_unescape_uri like below,the red part is which I modified.<div>Nginx is a really nice project.</div><div><br><div>void</div><div>ngx_unescape_uri(u_char **dst, u_char **src, size_t size, ngx_uint_t type)</div>
<div>{</div><div> u_char *d, *s, ch, c, decoded;</div><div> enum {</div><div> sw_usual = 0,</div><div> sw_quoted,</div><div> sw_quoted_second</div><div> } state;</div><div><br></div><div> d = *dst;</div>
<div> s = *src;</div><div><br></div><div> state = 0;</div><div> decoded = 0;</div><div><br></div><div> while (size--) {</div><div><br></div><div> ch = *s++;</div><div><br></div><div> switch (state) {</div>
<div> case sw_usual:</div><div> if (ch == '?'</div><div> && (type & (NGX_UNESCAPE_URI|NGX_UNESCAPE_REDIRECT)))</div><div> {</div><div> *d++ = ch;</div>
<div> goto done;</div><div> }</div><div><br></div><div><font color="#ff0000"> if (ch == '%'&&size>1) {</font></div><div><font color="#ff0000"> ch=*s;</font></div>
<div><font color="#ff0000"> c = (u_char) (ch | 0x20);</font></div><div><font color="#ff0000"> if ((ch >= '0' && ch <= '9')||(c >= 'a' && c <= 'f')) {</font></div>
<div><font color="#ff0000"> ch=*(s+1);</font></div><div><font color="#ff0000"> c = (u_char) (ch | 0x20);</font></div><div><font color="#ff0000"> if ((ch >= '0' && ch <= '9')||(c >= 'a' && c <= 'f')) {</font></div>
<div><font color="#ff0000"> state = sw_quoted;</font></div><div><font color="#ff0000"> break;</font></div><div><font color="#ff0000"> }</font></div>
<div><font color="#ff0000"> }</font></div><div><font color="#ff0000"> *d++ = '%';</font></div><div><font color="#ff0000"> break;</font></div>
<div><font color="#ff0000"> }</font></div><div><font color="#ff0000"><br></font></div><div><font color="#ff0000"> if (ch == '+') {</font></div>
<div><font color="#ff0000"> *d++ = ' ';</font></div><div><font color="#ff0000"> break;</font></div><div><font color="#ff0000"> }</font></div>
<div><br></div><div> *d++ = ch;</div><div> break;</div><div><br></div><div> case sw_quoted:</div><div><br></div><div> if (ch >= '0' && ch <= '9') {</div>
<div> decoded = (u_char) (ch - '0');</div><div> state = sw_quoted_second;</div><div> break;</div><div> }</div><div><br></div><div> c = (u_char) (ch | 0x20);</div>
<div> if (c >= 'a' && c <= 'f') {</div><div> decoded = (u_char) (c - 'a' + 10);</div><div> state = sw_quoted_second;</div><div> break;</div>
<div> }</div><div><br></div><div> /* the invalid quoted character */</div><div><br></div><div> state = sw_usual;</div><div><br></div><div> *d++ = ch;</div><div><br></div><div> break;</div>
<div><br></div><div> case sw_quoted_second:</div><div><br></div><div> state = sw_usual;</div><div><br></div><div> if (ch >= '0' && ch <= '9') {</div><div> ch = (u_char) ((decoded << 4) + ch - '0');</div>
<div><br></div><div> if (type & NGX_UNESCAPE_REDIRECT) {</div><div> if (ch > '%' && ch < 0x7f) {</div><div> *d++ = ch;</div><div> break;</div>
<div> }</div><div><br></div><div> *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1);</div><div><br></div><div> break;</div><div> }</div><div><br>
</div>
<div> *d++ = ch;</div><div><br></div><div> break;</div><div> }</div><div><br></div><div> c = (u_char) (ch | 0x20);</div><div> if (c >= 'a' && c <= 'f') {</div>
<div> ch = (u_char) ((decoded << 4) + c - 'a' + 10);</div><div><br></div><div> if (type & NGX_UNESCAPE_URI) {</div><div> if (ch == '?') {</div><div>
*d++ = ch;</div><div> goto done;</div><div> }</div><div><br></div><div> *d++ = ch;</div><div> break;</div><div> }</div>
<div><br></div><div> if (type & NGX_UNESCAPE_REDIRECT) {</div><div> if (ch == '?') {</div><div> *d++ = ch;</div><div> goto done;</div>
<div> }</div><div><br></div><div> if (ch > '%' && ch < 0x7f) {</div><div> *d++ = ch;</div><div> break;</div><div> }</div>
<div><br></div><div> *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1);</div><div> break;</div><div> }</div><div><br></div><div> *d++ = ch;</div><div>
<br></div><div> break;</div><div> }</div><div><br></div><div> /* the invalid quoted character */</div><div><br></div><div> break;</div><div> }</div><div> }</div><div>
<br></div><div>done:</div><div><br></div><div> *dst = d;</div><div> *src = s;</div><div>}</div><div><br></div><div><br></div></div>
</div><br>