Hello Everyone,<br><br>I found something unusual while using SSI echo command.<br><br>Let's say a ssi html file like this:<br><br><!--#set var="x" value="%20" --><br><!--#echo var="x" encoding="url" --><br>
<!--#echo var="x" encoding="url" --><br><!--#echo var="x" encoding="url" --><br><br>nginx will output:<br>%20
%2520
%252520
%25252520<br><br>not what we expected:<br>%20
%2034
%2034
%2034
<br><br>After digging into nginx's source code, I realized that this is because the original value "x" was changed after the first ngx_escape_uri() call in src/http/modules/ngx_http_ssi_filter_module.c: (version 0.6.35, around line 2200)<br>
<br> case NGX_HTTP_SSI_URL_ENCODING:<br> len = 2 * ngx_escape_uri(NULL, value->data, value->len,<br> NGX_ESCAPE_HTML);<br> if (len) {<br> p = ngx_palloc(r->pool, value->len + len);<br>
if (p == NULL) {<br> return NGX_HTTP_SSI_ERROR;<br> }<br> (void) ngx_escape_uri(p, value->data, value->len, NGX_ESCAPE_HTML);<br> value->len += len; //*That's it!*<br>
value->data = p;<br> }<br><br>I don't think setting value->len and value->data is a right thing here. People use SSI to echo some variables with encoding, but they don't expect those original variables are changed after that.<br>
<br>This happens if encoding is set to "entity" as well. I think this is a bug. Although not too many people use SSI in such a way like me, it's dangerous that seeing a value of variable keeps growing and growing.<br>
<br>Version 0.7.x has the same problem.<br><br>Here's my bugfix:<br> key = 0; //not a good name, but can use it as a flag<br> switch(ctx->encoding) {<br> //...<br> case NGX_HTTP_SSI_URL_ENCODING:<br>
//...<br> key = 1;<br>
len += value->len;<br>
}<br> //..<br> b->memory = 1;<br> if(key) {<br> b->pos = p;<br> b->last = p+len;<br> } else {<br> b->pos = value->data;<br> b->last = value->data + value->len;<br>
}<br><br>That's the main part of code change. After that, problem solved. Then nginx will output what we expected, however many times we do "echo":<br><br>
%20
%2520
%2520
%2520<br><br><br>And also I want to suggest another feature: add a new parameter value to the "encoding" parameter of SSI echo command, let's say it "cookie". For example, some people may want to output a variable "foo":<br>
<br><!--#set var="foo" value="a%20b" --><br><!--#echo var="foo" --><br><br>(<br>Setting variable "foo" is just for example. Actually, in production envrionment "foo" might be from cookie. For example, in nginx.conf, we can set "foo" like this:<br>
<br>if ($http_cookie ~* "foo=([^;]+)(?:;|$)" ) {<br> set $foo $1;<br>}<br>)<br><br>The output is "a%20b". But I want nginx to output "a b", not "a%20b". Too bad there's no way of doing it. So I added those code to ngx_http_ssi_filter_module.c, here's main part of it:<br>
<br> //have to set ctx->encoding first<br> //NGX_HTTP_SSI_COOKIE_ENCODING defines somewhere else.<br> case NGX_HTTP_SSI_COOKIE_ENCODING: <br> if(!value->len) break;<br><br> p = ngx_palloc(r->pool, value->len);<br>
if (p == NULL) {<br> return NGX_HTTP_SSI_ERROR;<br> }<br><br> dst = p;<br> src = value->data;<br><br> ngx_unescape_uri(&dst, &src, value->len, NGX_UNESCAPE_URI);<br>
<br> len = (value->data + value->len) - src;<br> if (len) {<br> dst = ngx_copy(dst, src, len);<br> }<br><br> key = 1;<br> len = dst - p;<br> //fall through, let it "entity" encoding take effect<br>
case NGX_HTTP_SSI_ENTITY_ENCODING:<br> //...there're also some changes in this part, but here I didn't post them<br><br>Then, nginx will output variable foo as "a b". For example,<br><br><!--#set var="foo" value="<b>a%20b</b>" --><br>
<!--#echo var="foo" encoding="none"--><br><!--#echo var="foo" encoding="entity"--><br>
<!--#echo var="foo" encoding="cookie"--><br>
<!--#echo var="foo" encoding="url"--><br>
<!--#echo var="foo" encoding="url"--><br>
<!--#echo var="foo" encoding="url"--><br>
...<br><br>The new compiled Nginx outputs:<br><br>a%20b<br>&<span class="entity">lt;</span>b&<span class="entity">gt;</span>a%20b&<span class="entity">lt;</span>/b&<span class="entity">gt; ("entity", In browser, it's "a%20b" in bold font)<br>
</span>&<span class="entity">lt;</span>b&<span class="entity">gt;</span>a b&<span class="entity">lt;</span>/b&<span class="entity">gt;</span> ("cookie", In browser, it's "a b" in bold font)<br>
a%2520b<br>a%2520b<br>a%2520b<br>... (because the bug I mentioned at the first of email has been fixed so after several times "url" encoding the output of variable foo won't be "a%25%25%25...20b")<br>
<br><br>I attached ngx_http_ssi_filter_module.c and ngx_http_ssi_filter_module.h to this email (If this maillist doesn't support attachment, please let me know). It's the full source code that modified by me. It's a little ugly because I just wanted to get my idea work as soon as possible and didn't pay much attention to code style and something else. If Igor or someone else put my bugfix to nginx's code trunk I will be very happy to see a little line "Thanks to goudou" in CHANGELOG. :-)<br>
<br>Wish you all best,<br>goudou @ Shanghai, China<br><br>