Hello Everyone,<br><br>I found something unusual while using SSI echo command.<br><br>Let&#39;s say a ssi html file like this:<br><br>&lt;!--#set var=&quot;x&quot; value=&quot;%20&quot; --&gt;<br>&lt;!--#echo var=&quot;x&quot; encoding=&quot;url&quot; --&gt;<br>
&lt;!--#echo var=&quot;x&quot; encoding=&quot;url&quot; --&gt;<br>&lt;!--#echo var=&quot;x&quot; encoding=&quot;url&quot; --&gt;<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&#39;s source code, I realized that this is because the original value &quot;x&quot; 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-&gt;data, value-&gt;len,<br>                                 NGX_ESCAPE_HTML);<br>        if (len) {<br>            p = ngx_palloc(r-&gt;pool, value-&gt;len + len);<br>
            if (p == NULL) {<br>                return NGX_HTTP_SSI_ERROR;<br>            }<br>            (void) ngx_escape_uri(p, value-&gt;data, value-&gt;len, NGX_ESCAPE_HTML);<br>            value-&gt;len += len; //*That&#39;s it!*<br>
            value-&gt;data = p;<br>        }<br><br>I don&#39;t think setting value-&gt;len and value-&gt;data is a right thing here. People use SSI to echo some variables with encoding, but they don&#39;t expect those original variables are changed after that.<br>
<br>This happens if encoding is set to &quot;entity&quot; as well. I think this is a bug. Although not too many people use SSI in such a way like me, it&#39;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&#39;s my bugfix:<br>    key = 0; //not a good name, but can use it as a flag<br>    switch(ctx-&gt;encoding) {<br>    //...<br>    case NGX_HTTP_SSI_URL_ENCODING:<br>           
//...<br>            key = 1;<br>
            len += value-&gt;len;<br>
        }<br>     //..<br>    b-&gt;memory = 1;<br>    if(key) {<br>        b-&gt;pos = p;<br>        b-&gt;last = p+len;<br>    } else {<br>        b-&gt;pos = value-&gt;data;<br>        b-&gt;last = value-&gt;data + value-&gt;len;<br>
    }<br><br>That&#39;s the main part of code change. After that, problem solved. Then nginx will output what we expected, however many times we do &quot;echo&quot;:<br><br>
%20
%2520
%2520
%2520<br><br><br>And also I want to suggest another feature: add a new parameter value to the &quot;encoding&quot; parameter of SSI echo command, let&#39;s say it &quot;cookie&quot;. For example, some people may want to output a variable &quot;foo&quot;:<br>
<br>&lt;!--#set var=&quot;foo&quot; value=&quot;a%20b&quot; --&gt;<br>&lt;!--#echo var=&quot;foo&quot; --&gt;<br><br>(<br>Setting variable &quot;foo&quot; is just for example. Actually, in production envrionment &quot;foo&quot; might be from cookie. For example, in nginx.conf, we can set &quot;foo&quot; like this:<br>
<br>if ($http_cookie ~* &quot;foo=([^;]+)(?:;|$)&quot; ) {<br>    set  $foo  $1;<br>}<br>)<br><br>The output is &quot;a%20b&quot;. But I want nginx to output &quot;a b&quot;, not &quot;a%20b&quot;. Too bad there&#39;s no way of doing it. So I added those code to ngx_http_ssi_filter_module.c, here&#39;s main part of it:<br>
<br>    //have to set ctx-&gt;encoding first<br>    //NGX_HTTP_SSI_COOKIE_ENCODING defines somewhere else.<br>    case NGX_HTTP_SSI_COOKIE_ENCODING: <br>        if(!value-&gt;len) break;<br><br>        p = ngx_palloc(r-&gt;pool, value-&gt;len);<br>
        if (p == NULL) {<br>            return NGX_HTTP_SSI_ERROR;<br>        }<br><br>        dst = p;<br>        src = value-&gt;data;<br><br>        ngx_unescape_uri(&amp;dst, &amp;src, value-&gt;len, NGX_UNESCAPE_URI);<br>
<br>        len = (value-&gt;data + value-&gt;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 &quot;entity&quot; encoding take effect<br>
   case NGX_HTTP_SSI_ENTITY_ENCODING:<br>       //...there&#39;re also some changes in this part, but here I didn&#39;t post them<br><br>Then, nginx will output variable foo as &quot;a b&quot;. For example,<br><br>&lt;!--#set var=&quot;foo&quot; value=&quot;&lt;b&gt;a%20b&lt;/b&gt;&quot; --&gt;<br>

&lt;!--#echo var=&quot;foo&quot; encoding=&quot;none&quot;--&gt;<br>&lt;!--#echo var=&quot;foo&quot; encoding=&quot;entity&quot;--&gt;<br>
&lt;!--#echo var=&quot;foo&quot; encoding=&quot;cookie&quot;--&gt;<br>
&lt;!--#echo var=&quot;foo&quot; encoding=&quot;url&quot;--&gt;<br>

&lt;!--#echo var=&quot;foo&quot; encoding=&quot;url&quot;--&gt;<br>


&lt;!--#echo var=&quot;foo&quot; encoding=&quot;url&quot;--&gt;<br>

...<br><br>The new compiled Nginx outputs:<br><br>a%20b<br>&amp;<span class="entity">lt;</span>b&amp;<span class="entity">gt;</span>a%20b&amp;<span class="entity">lt;</span>/b&amp;<span class="entity">gt;     (&quot;entity&quot;, In browser, it&#39;s &quot;a%20b&quot; in bold font)<br>
</span>&amp;<span class="entity">lt;</span>b&amp;<span class="entity">gt;</span>a b&amp;<span class="entity">lt;</span>/b&amp;<span class="entity">gt;</span>           (&quot;cookie&quot;, In browser, it&#39;s &quot;a b&quot; 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 &quot;url&quot; encoding the output of variable foo won&#39;t be &quot;a%25%25%25...20b&quot;)<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&#39;t support attachment, please let me know). It&#39;s the full source code that modified by me. It&#39;s a little ugly because I just wanted to get my idea work as soon as possible and didn&#39;t pay much attention to code style and something else. If Igor or someone else put my bugfix to nginx&#39;s code trunk I will be very happy to see a little line &quot;Thanks to goudou&quot; in CHANGELOG. :-)<br>
<br>Wish you all best,<br>goudou @ Shanghai, China<br><br>