| | @@ -83,25 +83,10 @@ |
| 83 | 83 | /* |
| 84 | 84 | ** Ad-unit styles. |
| 85 | 85 | */ |
| 86 | 86 | static unsigned adUnitFlags = 0; |
| 87 | 87 | |
| 88 | | -/* |
| 89 | | -** Page data JSON |
| 90 | | -*/ |
| 91 | | -static Blob pageDataJson = BLOB_INITIALIZER; |
| 92 | | - |
| 93 | | - |
| 94 | | -/* |
| 95 | | -** List of hyperlinks and forms that need to be resolved by javascript in |
| 96 | | -** the footer. |
| 97 | | -*/ |
| 98 | | -char **aHref = 0; |
| 99 | | -int nHref = 0; |
| 100 | | -int nHrefAlloc = 0; |
| 101 | | -char **aFormAction = 0; |
| 102 | | -int nFormAction = 0; |
| 103 | 88 | |
| 104 | 89 | /* |
| 105 | 90 | ** Generate and return a anchor tag like this: |
| 106 | 91 | ** |
| 107 | 92 | ** <a href="URL"> |
| | @@ -131,12 +116,15 @@ |
| 131 | 116 | ** |
| 132 | 117 | ** Note %z format. The string returned by this function is always |
| 133 | 118 | ** obtained from fossil_malloc() so rendering it with %z will reclaim |
| 134 | 119 | ** that memory space. |
| 135 | 120 | ** |
| 136 | | -** There are two versions of this routine: href() does a plain hyperlink |
| 137 | | -** and xhref() adds extra attribute text. |
| 121 | +** There are three versions of this routine: |
| 122 | +** |
| 123 | +** (1) href() does a plain hyperlink |
| 124 | +** (2) xhref() adds extra attribute text |
| 125 | +** (3) chref() adds a class name |
| 138 | 126 | ** |
| 139 | 127 | ** g.perm.Hyperlink is true if the user has the Hyperlink (h) property. |
| 140 | 128 | ** Most logged in users should have this property, since we can assume |
| 141 | 129 | ** that a logged in user is not a bot. Only "nobody" lacks g.perm.Hyperlink, |
| 142 | 130 | ** typically. |
| | @@ -150,16 +138,26 @@ |
| 150 | 138 | if( g.perm.Hyperlink && !g.javascriptHyperlink ){ |
| 151 | 139 | char *zHUrl = mprintf("<a %s href=\"%h\">", zExtra, zUrl); |
| 152 | 140 | fossil_free(zUrl); |
| 153 | 141 | return zHUrl; |
| 154 | 142 | } |
| 155 | | - if( nHref>=nHrefAlloc ){ |
| 156 | | - nHrefAlloc = nHrefAlloc*2 + 10; |
| 157 | | - aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0])); |
| 143 | + return mprintf("<a %s class='antibot' data-href='%z' href='%R/honeypot'>", |
| 144 | + zExtra, zUrl); |
| 145 | +} |
| 146 | +char *chref(const char *zExtra, const char *zFormat, ...){ |
| 147 | + char *zUrl; |
| 148 | + va_list ap; |
| 149 | + va_start(ap, zFormat); |
| 150 | + zUrl = vmprintf(zFormat, ap); |
| 151 | + va_end(ap); |
| 152 | + if( g.perm.Hyperlink && !g.javascriptHyperlink ){ |
| 153 | + char *zHUrl = mprintf("<a %s href=\"%h\">", zExtra, zUrl); |
| 154 | + fossil_free(zUrl); |
| 155 | + return zHUrl; |
| 158 | 156 | } |
| 159 | | - aHref[nHref++] = zUrl; |
| 160 | | - return mprintf("<a %s id='a%d' href='%R/honeypot'>", zExtra, nHref); |
| 157 | + return mprintf("<a class='antibot %s' data-href='%z' href='%R/honeypot'>", |
| 158 | + zExtra, zUrl); |
| 161 | 159 | } |
| 162 | 160 | char *href(const char *zFormat, ...){ |
| 163 | 161 | char *zUrl; |
| 164 | 162 | va_list ap; |
| 165 | 163 | va_start(ap, zFormat); |
| | @@ -168,16 +166,12 @@ |
| 168 | 166 | if( g.perm.Hyperlink && !g.javascriptHyperlink ){ |
| 169 | 167 | char *zHUrl = mprintf("<a href=\"%h\">", zUrl); |
| 170 | 168 | fossil_free(zUrl); |
| 171 | 169 | return zHUrl; |
| 172 | 170 | } |
| 173 | | - if( nHref>=nHrefAlloc ){ |
| 174 | | - nHrefAlloc = nHrefAlloc*2 + 10; |
| 175 | | - aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0])); |
| 176 | | - } |
| 177 | | - aHref[nHref++] = zUrl; |
| 178 | | - return mprintf("<a id='a%d' href='%R/honeypot'>", nHref); |
| 171 | + return mprintf("<a class='antibot' data-href='%s' href='%R/honeypot'>", |
| 172 | + zUrl); |
| 179 | 173 | } |
| 180 | 174 | |
| 181 | 175 | /* |
| 182 | 176 | ** Generate <form method="post" action=ARG>. The ARG value is inserted |
| 183 | 177 | ** by javascript. |
| | @@ -190,72 +184,13 @@ |
| 190 | 184 | zLink = vmprintf(zAction, ap); |
| 191 | 185 | va_end(ap); |
| 192 | 186 | if( g.perm.Hyperlink && !g.javascriptHyperlink ){ |
| 193 | 187 | @ <form method="POST" action="%z(zLink)" %s(zOtherArgs)> |
| 194 | 188 | }else{ |
| 195 | | - int n; |
| 196 | | - aFormAction = fossil_realloc(aFormAction, (nFormAction+1)*sizeof(char*)); |
| 197 | | - aFormAction[nFormAction++] = zLink; |
| 198 | | - n = nFormAction; |
| 199 | | - @ <form id="form%d(n)" method="POST" action='%R/login' %s(zOtherArgs)> |
| 200 | | - } |
| 201 | | -} |
| 202 | | - |
| 203 | | -/* |
| 204 | | -** Append page-data JSON |
| 205 | | -*/ |
| 206 | | -void style_pagedata_appendf(const char *zFormat, ...){ |
| 207 | | - va_list ap; |
| 208 | | - if( blob_size(&pageDataJson)==0 ){ |
| 209 | | - blob_append(&pageDataJson, "[", 1); |
| 210 | | - } |
| 211 | | - va_start(ap, zFormat); |
| 212 | | - blob_vappendf(&pageDataJson, zFormat, ap); |
| 213 | | - va_end(ap); |
| 214 | | -} |
| 215 | | - |
| 216 | | -/* |
| 217 | | -** Generate javascript that will set the href= attribute on all anchors. |
| 218 | | -*/ |
| 219 | | -void style_resolve_href(void){ |
| 220 | | - int i; |
| 221 | | - int nDelay = db_get_int("auto-hyperlink-delay",10); |
| 222 | | - if( !g.perm.Hyperlink ) return; |
| 223 | | - if( nHref==0 && nFormAction==0 ) return; |
| 224 | | - @ <script> |
| 225 | | - @ function setAllHrefs(){ |
| 226 | | - if( g.javascriptHyperlink ){ |
| 227 | | - for(i=0; i<nHref; i++){ |
| 228 | | - @ gebi("a%d(i+1)").href="%s(aHref[i])"; |
| 229 | | - } |
| 230 | | - } |
| 231 | | - for(i=0; i<nFormAction; i++){ |
| 232 | | - @ gebi("form%d(i+1)").action="%s(aFormAction[i])"; |
| 233 | | - } |
| 234 | | - @ } |
| 235 | | - if( sqlite3_strglob("*Opera Mini/[1-9]*", PD("HTTP_USER_AGENT",""))==0 ){ |
| 236 | | - /* Special case for Opera Mini, which executes JS server-side */ |
| 237 | | - @ var isOperaMini = Object.prototype.toString.call(window.operamini) |
| 238 | | - @ === "[object OperaMini]"; |
| 239 | | - @ if( isOperaMini ){ |
| 240 | | - @ setTimeout("setAllHrefs();",%d(nDelay)); |
| 241 | | - @ } |
| 242 | | - }else if( db_get_boolean("auto-hyperlink-ishuman",0) && g.isHuman ){ |
| 243 | | - /* Active hyperlinks after a delay */ |
| 244 | | - @ setTimeout("setAllHrefs();",%d(nDelay)); |
| 245 | | - }else if( db_get_boolean("auto-hyperlink-mouseover",0) ){ |
| 246 | | - /* Require mouse movement before starting the teim that will |
| 247 | | - ** activating hyperlinks */ |
| 248 | | - @ document.getElementsByTagName("body")[0].onmousemove=function(){ |
| 249 | | - @ setTimeout("setAllHrefs();",%d(nDelay)); |
| 250 | | - @ this.onmousemove = null; |
| 251 | | - @ } |
| 252 | | - }else{ |
| 253 | | - /* Active hyperlinks after a delay */ |
| 254 | | - @ setTimeout("setAllHrefs();",%d(nDelay)); |
| 255 | | - } |
| 256 | | - @ </script> |
| 189 | + @ <form method="POST" data-action='%s(zLink)' action='%R/login' \ |
| 190 | + @ %s(zOtherArgs)> |
| 191 | + } |
| 257 | 192 | } |
| 258 | 193 | |
| 259 | 194 | /* |
| 260 | 195 | ** Add a new element to the submenu |
| 261 | 196 | */ |
| | @@ -576,10 +511,11 @@ |
| 576 | 511 | */ |
| 577 | 512 | void style_footer(void){ |
| 578 | 513 | const char *zFooter; |
| 579 | 514 | const char *zAd = 0; |
| 580 | 515 | unsigned int mAdFlags = 0; |
| 516 | + int bMouseover = 0; /* Active hyperlinks after mouseover */ |
| 581 | 517 | |
| 582 | 518 | if( !headerHasBeenGenerated ) return; |
| 583 | 519 | |
| 584 | 520 | /* Go back and put the submenu at the top of the page. We delay the |
| 585 | 521 | ** creation of the submenu until the end so that we can add elements |
| | @@ -726,15 +662,38 @@ |
| 726 | 662 | */ |
| 727 | 663 | @ <div class="endContent"></div> |
| 728 | 664 | } |
| 729 | 665 | @ </div> |
| 730 | 666 | |
| 667 | +#if 0 |
| 731 | 668 | /* Set the href= field on hyperlinks. Do this before the footer since |
| 732 | 669 | ** the footer will be generating </html> */ |
| 733 | 670 | style_resolve_href(); |
| 671 | +#endif |
| 672 | + |
| 673 | + /* Load up the page data */ |
| 674 | + @ <script id='page-data' type='application/json'> |
| 675 | + if( !g.javascriptHyperlink ){ |
| 676 | + @ {"antibot":{"enable":0}, |
| 677 | + }else{ |
| 678 | + int nDelay = db_get_int("auto-hyperlink-delay",0); |
| 679 | + int bMouseover; |
| 680 | + bMouseover = (!g.isHuman || db_get_boolean("auto-hyperlink-ishuman",0)) |
| 681 | + && db_get_boolean("auto-hyperlink-mouseover",0); |
| 682 | + @ {"antibot": |
| 683 | + @ {"enable":1, |
| 684 | + @ "delay":%d(nDelay), |
| 685 | + @ "mouseover":%d(bMouseover)}, |
| 686 | + } |
| 687 | + @ "noop":0} |
| 688 | + @ </script> |
| 689 | + |
| 734 | 690 | |
| 735 | 691 | zFooter = skin_get("footer"); |
| 692 | + if( sqlite3_strlike("%</body>%", zFooter, 0)==0 ){ |
| 693 | + @ <script src='%s(g.zBaseURL)/main.js' type='application/javascript'>\ |
| 694 | + } |
| 736 | 695 | if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1); |
| 737 | 696 | Th_Render(zFooter); |
| 738 | 697 | if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1); |
| 739 | 698 | |
| 740 | 699 | /* Render trace log if TH1 tracing is enabled. */ |
| | @@ -744,16 +703,12 @@ |
| 744 | 703 | cgi_append_content("</span>\n", -1); |
| 745 | 704 | } |
| 746 | 705 | |
| 747 | 706 | /* Add document end mark if it was not in the footer */ |
| 748 | 707 | if( sqlite3_strlike("%</body>%", zFooter, 0)!=0 ){ |
| 749 | | - style_pagedata_appendf("{'op':'no-op'}]"); |
| 750 | | - @ <script type='application/json' id='page-data'> |
| 751 | | - @ %s(blob_str(&pageDataJson)) |
| 752 | | - @ </script> |
| 753 | 708 | @ <script src='%s(g.zBaseURL)/main.js' type='application/javascript'>\ |
| 754 | | - @ <script> |
| 709 | + @ </script> |
| 755 | 710 | @ </body> |
| 756 | 711 | @ </html> |
| 757 | 712 | } |
| 758 | 713 | } |
| 759 | 714 | |
| 760 | 715 | |