Fossil SCM
Further changes trying to get ETags to work well. But as I type this, I feel like this design is not working out well and I am about ready to start over from scratch. This check-in is just to preserve work in case I want to come back to it later.
Commit
02740c2c47ae7c35922e3333c4f63863835f28f06fde01664bfa7ced3da9138a
Parent
43a66b58db29aab…
5 files changed
+6
-16
+2
-4
+8
-3
+2
+11
-5
+6
-16
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -258,12 +258,16 @@ | ||
| 258 | 258 | fprintf(g.httpOut, "Connection: close\r\n"); |
| 259 | 259 | fprintf(g.httpOut, "X-UA-Compatible: IE=edge\r\n"); |
| 260 | 260 | }else{ |
| 261 | 261 | fprintf(g.httpOut, "Status: %d %s\r\n", iReplyStatus, zReplyStatus); |
| 262 | 262 | } |
| 263 | - zETag = etag_generate(-1); | |
| 264 | - if( zETag ){ | |
| 263 | + if( g.isConst ){ | |
| 264 | + /* The g.isConst flag means that the result is immutable, even for | |
| 265 | + ** after configuration changes and/or rebuilds of the Fossil binary. | |
| 266 | + */ | |
| 267 | + fprintf(g.httpOut, "Cache-Control: max-age=31536000\r\n"); | |
| 268 | + }else if( (zETag = etag_generate(-1))!=0 ){ | |
| 265 | 269 | fprintf(g.httpOut, "ETag: %s\r\n", zETag); |
| 266 | 270 | fprintf(g.httpOut, "Cache-Control: max-age=%d\r\n", etag_maxage()); |
| 267 | 271 | } |
| 268 | 272 | |
| 269 | 273 | if( blob_size(&extraHeader)>0 ){ |
| @@ -286,24 +290,10 @@ | ||
| 286 | 290 | ** |
| 287 | 291 | ** These headers are probably best added by the web server hosting fossil as |
| 288 | 292 | ** a CGI script. |
| 289 | 293 | */ |
| 290 | 294 | |
| 291 | - if( g.isConst ){ | |
| 292 | - /* constant means that the input URL will _never_ generate anything | |
| 293 | - ** else. In the case of attachments, the contents won't change because | |
| 294 | - ** an attempt to change them generates a new attachment number. In the | |
| 295 | - ** case of most /getfile calls for specific versions, the only way the | |
| 296 | - ** content changes is if someone breaks the SCM. And if that happens, a | |
| 297 | - ** stale cache is the least of the problem. So we provide an Expires | |
| 298 | - ** header set to a reasonable period (default: one week). | |
| 299 | - */ | |
| 300 | - fprintf(g.httpOut, "Cache-control: max-age=28800\r\n"); | |
| 301 | - }else{ | |
| 302 | - fprintf(g.httpOut, "Cache-control: no-cache\r\n"); | |
| 303 | - } | |
| 304 | - | |
| 305 | 295 | /* Content intended for logged in users should only be cached in |
| 306 | 296 | ** the browser, not some shared location. |
| 307 | 297 | */ |
| 308 | 298 | fprintf(g.httpOut, "Content-Type: %s; charset=utf-8\r\n", zContentType); |
| 309 | 299 | if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){ |
| 310 | 300 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -258,12 +258,16 @@ | |
| 258 | fprintf(g.httpOut, "Connection: close\r\n"); |
| 259 | fprintf(g.httpOut, "X-UA-Compatible: IE=edge\r\n"); |
| 260 | }else{ |
| 261 | fprintf(g.httpOut, "Status: %d %s\r\n", iReplyStatus, zReplyStatus); |
| 262 | } |
| 263 | zETag = etag_generate(-1); |
| 264 | if( zETag ){ |
| 265 | fprintf(g.httpOut, "ETag: %s\r\n", zETag); |
| 266 | fprintf(g.httpOut, "Cache-Control: max-age=%d\r\n", etag_maxage()); |
| 267 | } |
| 268 | |
| 269 | if( blob_size(&extraHeader)>0 ){ |
| @@ -286,24 +290,10 @@ | |
| 286 | ** |
| 287 | ** These headers are probably best added by the web server hosting fossil as |
| 288 | ** a CGI script. |
| 289 | */ |
| 290 | |
| 291 | if( g.isConst ){ |
| 292 | /* constant means that the input URL will _never_ generate anything |
| 293 | ** else. In the case of attachments, the contents won't change because |
| 294 | ** an attempt to change them generates a new attachment number. In the |
| 295 | ** case of most /getfile calls for specific versions, the only way the |
| 296 | ** content changes is if someone breaks the SCM. And if that happens, a |
| 297 | ** stale cache is the least of the problem. So we provide an Expires |
| 298 | ** header set to a reasonable period (default: one week). |
| 299 | */ |
| 300 | fprintf(g.httpOut, "Cache-control: max-age=28800\r\n"); |
| 301 | }else{ |
| 302 | fprintf(g.httpOut, "Cache-control: no-cache\r\n"); |
| 303 | } |
| 304 | |
| 305 | /* Content intended for logged in users should only be cached in |
| 306 | ** the browser, not some shared location. |
| 307 | */ |
| 308 | fprintf(g.httpOut, "Content-Type: %s; charset=utf-8\r\n", zContentType); |
| 309 | if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){ |
| 310 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -258,12 +258,16 @@ | |
| 258 | fprintf(g.httpOut, "Connection: close\r\n"); |
| 259 | fprintf(g.httpOut, "X-UA-Compatible: IE=edge\r\n"); |
| 260 | }else{ |
| 261 | fprintf(g.httpOut, "Status: %d %s\r\n", iReplyStatus, zReplyStatus); |
| 262 | } |
| 263 | if( g.isConst ){ |
| 264 | /* The g.isConst flag means that the result is immutable, even for |
| 265 | ** after configuration changes and/or rebuilds of the Fossil binary. |
| 266 | */ |
| 267 | fprintf(g.httpOut, "Cache-Control: max-age=31536000\r\n"); |
| 268 | }else if( (zETag = etag_generate(-1))!=0 ){ |
| 269 | fprintf(g.httpOut, "ETag: %s\r\n", zETag); |
| 270 | fprintf(g.httpOut, "Cache-Control: max-age=%d\r\n", etag_maxage()); |
| 271 | } |
| 272 | |
| 273 | if( blob_size(&extraHeader)>0 ){ |
| @@ -286,24 +290,10 @@ | |
| 290 | ** |
| 291 | ** These headers are probably best added by the web server hosting fossil as |
| 292 | ** a CGI script. |
| 293 | */ |
| 294 | |
| 295 | /* Content intended for logged in users should only be cached in |
| 296 | ** the browser, not some shared location. |
| 297 | */ |
| 298 | fprintf(g.httpOut, "Content-Type: %s; charset=utf-8\r\n", zContentType); |
| 299 | if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){ |
| 300 |
+2
-4
| --- src/doc.c | ||
| +++ src/doc.c | ||
| @@ -832,11 +832,11 @@ | ||
| 832 | 832 | 214, 163, 146, 117, 238, 213, 154, 128, 151, 109, 84, 64, 217, 13, |
| 833 | 833 | 27, 10, 228, 39, 2, 235, 164, 168, 74, 8, 0, 59, |
| 834 | 834 | }; |
| 835 | 835 | |
| 836 | 836 | /* |
| 837 | -** WEBPAGE: logo | |
| 837 | +** WEBPAGE: logo config | |
| 838 | 838 | ** |
| 839 | 839 | ** Return the logo image. This image is available to anybody who can see |
| 840 | 840 | ** the login page. It is designed for use in the upper left-hand corner |
| 841 | 841 | ** of the header. |
| 842 | 842 | */ |
| @@ -850,11 +850,10 @@ | ||
| 850 | 850 | if( blob_size(&logo)==0 ){ |
| 851 | 851 | blob_init(&logo, (char*)aLogo, sizeof(aLogo)); |
| 852 | 852 | } |
| 853 | 853 | cgi_set_content_type(zMime); |
| 854 | 854 | cgi_set_content(&logo); |
| 855 | - g.isConst = 1; | |
| 856 | 855 | } |
| 857 | 856 | |
| 858 | 857 | /* |
| 859 | 858 | ** The default background image: a 16x16 white GIF |
| 860 | 859 | */ |
| @@ -867,11 +866,11 @@ | ||
| 867 | 866 | 179, 62, 5, 0, 59, |
| 868 | 867 | }; |
| 869 | 868 | |
| 870 | 869 | |
| 871 | 870 | /* |
| 872 | -** WEBPAGE: background | |
| 871 | +** WEBPAGE: background const | |
| 873 | 872 | ** |
| 874 | 873 | ** Return the background image. If no background image is defined, a |
| 875 | 874 | ** built-in 16x16 pixel white GIF is returned. |
| 876 | 875 | */ |
| 877 | 876 | void background_page(void){ |
| @@ -884,11 +883,10 @@ | ||
| 884 | 883 | if( blob_size(&bgimg)==0 ){ |
| 885 | 884 | blob_init(&bgimg, (char*)aBackground, sizeof(aBackground)); |
| 886 | 885 | } |
| 887 | 886 | cgi_set_content_type(zMime); |
| 888 | 887 | cgi_set_content(&bgimg); |
| 889 | - g.isConst = 1; | |
| 890 | 888 | } |
| 891 | 889 | |
| 892 | 890 | |
| 893 | 891 | /* |
| 894 | 892 | ** WEBPAGE: docsrch |
| 895 | 893 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -832,11 +832,11 @@ | |
| 832 | 214, 163, 146, 117, 238, 213, 154, 128, 151, 109, 84, 64, 217, 13, |
| 833 | 27, 10, 228, 39, 2, 235, 164, 168, 74, 8, 0, 59, |
| 834 | }; |
| 835 | |
| 836 | /* |
| 837 | ** WEBPAGE: logo |
| 838 | ** |
| 839 | ** Return the logo image. This image is available to anybody who can see |
| 840 | ** the login page. It is designed for use in the upper left-hand corner |
| 841 | ** of the header. |
| 842 | */ |
| @@ -850,11 +850,10 @@ | |
| 850 | if( blob_size(&logo)==0 ){ |
| 851 | blob_init(&logo, (char*)aLogo, sizeof(aLogo)); |
| 852 | } |
| 853 | cgi_set_content_type(zMime); |
| 854 | cgi_set_content(&logo); |
| 855 | g.isConst = 1; |
| 856 | } |
| 857 | |
| 858 | /* |
| 859 | ** The default background image: a 16x16 white GIF |
| 860 | */ |
| @@ -867,11 +866,11 @@ | |
| 867 | 179, 62, 5, 0, 59, |
| 868 | }; |
| 869 | |
| 870 | |
| 871 | /* |
| 872 | ** WEBPAGE: background |
| 873 | ** |
| 874 | ** Return the background image. If no background image is defined, a |
| 875 | ** built-in 16x16 pixel white GIF is returned. |
| 876 | */ |
| 877 | void background_page(void){ |
| @@ -884,11 +883,10 @@ | |
| 884 | if( blob_size(&bgimg)==0 ){ |
| 885 | blob_init(&bgimg, (char*)aBackground, sizeof(aBackground)); |
| 886 | } |
| 887 | cgi_set_content_type(zMime); |
| 888 | cgi_set_content(&bgimg); |
| 889 | g.isConst = 1; |
| 890 | } |
| 891 | |
| 892 | |
| 893 | /* |
| 894 | ** WEBPAGE: docsrch |
| 895 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -832,11 +832,11 @@ | |
| 832 | 214, 163, 146, 117, 238, 213, 154, 128, 151, 109, 84, 64, 217, 13, |
| 833 | 27, 10, 228, 39, 2, 235, 164, 168, 74, 8, 0, 59, |
| 834 | }; |
| 835 | |
| 836 | /* |
| 837 | ** WEBPAGE: logo config |
| 838 | ** |
| 839 | ** Return the logo image. This image is available to anybody who can see |
| 840 | ** the login page. It is designed for use in the upper left-hand corner |
| 841 | ** of the header. |
| 842 | */ |
| @@ -850,11 +850,10 @@ | |
| 850 | if( blob_size(&logo)==0 ){ |
| 851 | blob_init(&logo, (char*)aLogo, sizeof(aLogo)); |
| 852 | } |
| 853 | cgi_set_content_type(zMime); |
| 854 | cgi_set_content(&logo); |
| 855 | } |
| 856 | |
| 857 | /* |
| 858 | ** The default background image: a 16x16 white GIF |
| 859 | */ |
| @@ -867,11 +866,11 @@ | |
| 866 | 179, 62, 5, 0, 59, |
| 867 | }; |
| 868 | |
| 869 | |
| 870 | /* |
| 871 | ** WEBPAGE: background const |
| 872 | ** |
| 873 | ** Return the background image. If no background image is defined, a |
| 874 | ** built-in 16x16 pixel white GIF is returned. |
| 875 | */ |
| 876 | void background_page(void){ |
| @@ -884,11 +883,10 @@ | |
| 883 | if( blob_size(&bgimg)==0 ){ |
| 884 | blob_init(&bgimg, (char*)aBackground, sizeof(aBackground)); |
| 885 | } |
| 886 | cgi_set_content_type(zMime); |
| 887 | cgi_set_content(&bgimg); |
| 888 | } |
| 889 | |
| 890 | |
| 891 | /* |
| 892 | ** WEBPAGE: docsrch |
| 893 |
+8
-3
| --- src/etag.c | ||
| +++ src/etag.c | ||
| @@ -129,12 +129,15 @@ | ||
| 129 | 129 | ** is checked, and if it contains a compatible ETag, then a |
| 130 | 130 | ** 304 Not Modified return is generated and execution aborts. This |
| 131 | 131 | ** routine does not return if the 304 is generated. |
| 132 | 132 | */ |
| 133 | 133 | void etag_require(int code){ |
| 134 | - if( (mEtag & code)==code ) return; | |
| 135 | - mEtag |= code; | |
| 134 | + if( code==ETAG_CONST ){ | |
| 135 | + mEtag = code; | |
| 136 | + }else{ | |
| 137 | + mEtag |= code; | |
| 138 | + } | |
| 136 | 139 | etag_check(); |
| 137 | 140 | } |
| 138 | 141 | void etag_require_hash(const char *zHash){ |
| 139 | 142 | if( zHash ){ |
| 140 | 143 | zEHash = zHash; |
| @@ -144,11 +147,13 @@ | ||
| 144 | 147 | } |
| 145 | 148 | |
| 146 | 149 | /* Return an appropriate max-age. |
| 147 | 150 | */ |
| 148 | 151 | int etag_maxage(void){ |
| 149 | - if( mEtag ) return 1; | |
| 152 | + if( mEtag & (ETAG_DYNAMIC|ETAG_COOKIE) ) return 0; | |
| 153 | + if( mEtag & (ETAG_DATA|ETAG_HASH) ) return 60; | |
| 154 | + if( mEtag & (ETAG_CONFIG) ) return 300; | |
| 150 | 155 | return 3600*24; |
| 151 | 156 | } |
| 152 | 157 | |
| 153 | 158 | /* Generate an appropriate ETags value that captures all requirements. |
| 154 | 159 | ** Space is obtained from fossil_malloc(). |
| 155 | 160 |
| --- src/etag.c | |
| +++ src/etag.c | |
| @@ -129,12 +129,15 @@ | |
| 129 | ** is checked, and if it contains a compatible ETag, then a |
| 130 | ** 304 Not Modified return is generated and execution aborts. This |
| 131 | ** routine does not return if the 304 is generated. |
| 132 | */ |
| 133 | void etag_require(int code){ |
| 134 | if( (mEtag & code)==code ) return; |
| 135 | mEtag |= code; |
| 136 | etag_check(); |
| 137 | } |
| 138 | void etag_require_hash(const char *zHash){ |
| 139 | if( zHash ){ |
| 140 | zEHash = zHash; |
| @@ -144,11 +147,13 @@ | |
| 144 | } |
| 145 | |
| 146 | /* Return an appropriate max-age. |
| 147 | */ |
| 148 | int etag_maxage(void){ |
| 149 | if( mEtag ) return 1; |
| 150 | return 3600*24; |
| 151 | } |
| 152 | |
| 153 | /* Generate an appropriate ETags value that captures all requirements. |
| 154 | ** Space is obtained from fossil_malloc(). |
| 155 |
| --- src/etag.c | |
| +++ src/etag.c | |
| @@ -129,12 +129,15 @@ | |
| 129 | ** is checked, and if it contains a compatible ETag, then a |
| 130 | ** 304 Not Modified return is generated and execution aborts. This |
| 131 | ** routine does not return if the 304 is generated. |
| 132 | */ |
| 133 | void etag_require(int code){ |
| 134 | if( code==ETAG_CONST ){ |
| 135 | mEtag = code; |
| 136 | }else{ |
| 137 | mEtag |= code; |
| 138 | } |
| 139 | etag_check(); |
| 140 | } |
| 141 | void etag_require_hash(const char *zHash){ |
| 142 | if( zHash ){ |
| 143 | zEHash = zHash; |
| @@ -144,11 +147,13 @@ | |
| 147 | } |
| 148 | |
| 149 | /* Return an appropriate max-age. |
| 150 | */ |
| 151 | int etag_maxage(void){ |
| 152 | if( mEtag & (ETAG_DYNAMIC|ETAG_COOKIE) ) return 0; |
| 153 | if( mEtag & (ETAG_DATA|ETAG_HASH) ) return 60; |
| 154 | if( mEtag & (ETAG_CONFIG) ) return 300; |
| 155 | return 3600*24; |
| 156 | } |
| 157 | |
| 158 | /* Generate an appropriate ETags value that captures all requirements. |
| 159 | ** Space is obtained from fossil_malloc(). |
| 160 |
+2
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -1688,13 +1688,15 @@ | ||
| 1688 | 1688 | } |
| 1689 | 1689 | login_check_credentials(); |
| 1690 | 1690 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1691 | 1691 | if( rid==0 ) fossil_redirect_home(); |
| 1692 | 1692 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1693 | +#if 0 | |
| 1693 | 1694 | if( fossil_strcmp(P("name"), zUuid)==0 && login_is_nobody() ){ |
| 1694 | 1695 | g.isConst = 1; |
| 1695 | 1696 | } |
| 1697 | +#endif | |
| 1696 | 1698 | free(zUuid); |
| 1697 | 1699 | zMime = P("m"); |
| 1698 | 1700 | if( zMime==0 ){ |
| 1699 | 1701 | char *zFName = db_text(0, "SELECT filename.name FROM mlink, filename" |
| 1700 | 1702 | " WHERE mlink.fid=%d" |
| 1701 | 1703 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1688,13 +1688,15 @@ | |
| 1688 | } |
| 1689 | login_check_credentials(); |
| 1690 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1691 | if( rid==0 ) fossil_redirect_home(); |
| 1692 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1693 | if( fossil_strcmp(P("name"), zUuid)==0 && login_is_nobody() ){ |
| 1694 | g.isConst = 1; |
| 1695 | } |
| 1696 | free(zUuid); |
| 1697 | zMime = P("m"); |
| 1698 | if( zMime==0 ){ |
| 1699 | char *zFName = db_text(0, "SELECT filename.name FROM mlink, filename" |
| 1700 | " WHERE mlink.fid=%d" |
| 1701 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1688,13 +1688,15 @@ | |
| 1688 | } |
| 1689 | login_check_credentials(); |
| 1690 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 1691 | if( rid==0 ) fossil_redirect_home(); |
| 1692 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1693 | #if 0 |
| 1694 | if( fossil_strcmp(P("name"), zUuid)==0 && login_is_nobody() ){ |
| 1695 | g.isConst = 1; |
| 1696 | } |
| 1697 | #endif |
| 1698 | free(zUuid); |
| 1699 | zMime = P("m"); |
| 1700 | if( zMime==0 ){ |
| 1701 | char *zFName = db_text(0, "SELECT filename.name FROM mlink, filename" |
| 1702 | " WHERE mlink.fid=%d" |
| 1703 |
+11
-5
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -780,11 +780,11 @@ | ||
| 780 | 780 | blob_reset(&css); |
| 781 | 781 | } |
| 782 | 782 | |
| 783 | 783 | |
| 784 | 784 | /* |
| 785 | -** WEBPAGE: style.css | |
| 785 | +** WEBPAGE: style.css config | |
| 786 | 786 | ** |
| 787 | 787 | ** Return the style sheet. |
| 788 | 788 | */ |
| 789 | 789 | void page_style_css(void){ |
| 790 | 790 | Blob css; |
| @@ -822,26 +822,28 @@ | ||
| 822 | 822 | Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL); |
| 823 | 823 | Th_Store("home", g.zTop); |
| 824 | 824 | image_url_var("logo"); |
| 825 | 825 | image_url_var("background"); |
| 826 | 826 | Th_Render(blob_str(&css)); |
| 827 | - | |
| 828 | - /* Tell CGI that the content returned by this page is considered cacheable */ | |
| 829 | - g.isConst = 1; | |
| 830 | 827 | } |
| 831 | 828 | |
| 832 | 829 | /* |
| 833 | 830 | ** WEBPAGE: builtin |
| 834 | 831 | ** URL: builtin/FILENAME |
| 835 | 832 | ** |
| 836 | 833 | ** Return the built-in text given by FILENAME. This is used internally |
| 837 | 834 | ** by many Fossil web pages to load built-in javascript files. |
| 835 | +** | |
| 836 | +** If the id= query parameter is present, then Fossil assumes that the | |
| 837 | +** result is immutable and sets a very large cache retention time (1 year). | |
| 838 | 838 | */ |
| 839 | 839 | void page_builtin_text(void){ |
| 840 | 840 | Blob out; |
| 841 | 841 | const char *zName = P("name"); |
| 842 | 842 | const char *zTxt = 0; |
| 843 | + const char *zId = P("id"); | |
| 844 | + int nId; | |
| 843 | 845 | if( zName ) zTxt = builtin_text(zName); |
| 844 | 846 | if( zTxt==0 ){ |
| 845 | 847 | cgi_set_status(404, "Not Found"); |
| 846 | 848 | @ File "%h(zName)" not found |
| 847 | 849 | return; |
| @@ -849,13 +851,17 @@ | ||
| 849 | 851 | if( sqlite3_strglob("*.js", zName)==0 ){ |
| 850 | 852 | cgi_set_content_type("application/javascript"); |
| 851 | 853 | }else{ |
| 852 | 854 | cgi_set_content_type("text/plain"); |
| 853 | 855 | } |
| 856 | + if( zId && (nId = (int)strlen(zId))>=8 && strncmp(zId,MANIFEST_UUID,nId)==0 ){ | |
| 857 | + g.isConst = 1; | |
| 858 | + }else{ | |
| 859 | + etag_require(ETAG_CONST); | |
| 860 | + } | |
| 854 | 861 | blob_init(&out, zTxt, -1); |
| 855 | 862 | cgi_set_content(&out); |
| 856 | - g.isConst = 1; | |
| 857 | 863 | } |
| 858 | 864 | |
| 859 | 865 | |
| 860 | 866 | /* |
| 861 | 867 | ** WEBPAGE: test_env |
| 862 | 868 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -780,11 +780,11 @@ | |
| 780 | blob_reset(&css); |
| 781 | } |
| 782 | |
| 783 | |
| 784 | /* |
| 785 | ** WEBPAGE: style.css |
| 786 | ** |
| 787 | ** Return the style sheet. |
| 788 | */ |
| 789 | void page_style_css(void){ |
| 790 | Blob css; |
| @@ -822,26 +822,28 @@ | |
| 822 | Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL); |
| 823 | Th_Store("home", g.zTop); |
| 824 | image_url_var("logo"); |
| 825 | image_url_var("background"); |
| 826 | Th_Render(blob_str(&css)); |
| 827 | |
| 828 | /* Tell CGI that the content returned by this page is considered cacheable */ |
| 829 | g.isConst = 1; |
| 830 | } |
| 831 | |
| 832 | /* |
| 833 | ** WEBPAGE: builtin |
| 834 | ** URL: builtin/FILENAME |
| 835 | ** |
| 836 | ** Return the built-in text given by FILENAME. This is used internally |
| 837 | ** by many Fossil web pages to load built-in javascript files. |
| 838 | */ |
| 839 | void page_builtin_text(void){ |
| 840 | Blob out; |
| 841 | const char *zName = P("name"); |
| 842 | const char *zTxt = 0; |
| 843 | if( zName ) zTxt = builtin_text(zName); |
| 844 | if( zTxt==0 ){ |
| 845 | cgi_set_status(404, "Not Found"); |
| 846 | @ File "%h(zName)" not found |
| 847 | return; |
| @@ -849,13 +851,17 @@ | |
| 849 | if( sqlite3_strglob("*.js", zName)==0 ){ |
| 850 | cgi_set_content_type("application/javascript"); |
| 851 | }else{ |
| 852 | cgi_set_content_type("text/plain"); |
| 853 | } |
| 854 | blob_init(&out, zTxt, -1); |
| 855 | cgi_set_content(&out); |
| 856 | g.isConst = 1; |
| 857 | } |
| 858 | |
| 859 | |
| 860 | /* |
| 861 | ** WEBPAGE: test_env |
| 862 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -780,11 +780,11 @@ | |
| 780 | blob_reset(&css); |
| 781 | } |
| 782 | |
| 783 | |
| 784 | /* |
| 785 | ** WEBPAGE: style.css config |
| 786 | ** |
| 787 | ** Return the style sheet. |
| 788 | */ |
| 789 | void page_style_css(void){ |
| 790 | Blob css; |
| @@ -822,26 +822,28 @@ | |
| 822 | Th_Store("secureurl", login_wants_https_redirect()? g.zHttpsURL: g.zBaseURL); |
| 823 | Th_Store("home", g.zTop); |
| 824 | image_url_var("logo"); |
| 825 | image_url_var("background"); |
| 826 | Th_Render(blob_str(&css)); |
| 827 | } |
| 828 | |
| 829 | /* |
| 830 | ** WEBPAGE: builtin |
| 831 | ** URL: builtin/FILENAME |
| 832 | ** |
| 833 | ** Return the built-in text given by FILENAME. This is used internally |
| 834 | ** by many Fossil web pages to load built-in javascript files. |
| 835 | ** |
| 836 | ** If the id= query parameter is present, then Fossil assumes that the |
| 837 | ** result is immutable and sets a very large cache retention time (1 year). |
| 838 | */ |
| 839 | void page_builtin_text(void){ |
| 840 | Blob out; |
| 841 | const char *zName = P("name"); |
| 842 | const char *zTxt = 0; |
| 843 | const char *zId = P("id"); |
| 844 | int nId; |
| 845 | if( zName ) zTxt = builtin_text(zName); |
| 846 | if( zTxt==0 ){ |
| 847 | cgi_set_status(404, "Not Found"); |
| 848 | @ File "%h(zName)" not found |
| 849 | return; |
| @@ -849,13 +851,17 @@ | |
| 851 | if( sqlite3_strglob("*.js", zName)==0 ){ |
| 852 | cgi_set_content_type("application/javascript"); |
| 853 | }else{ |
| 854 | cgi_set_content_type("text/plain"); |
| 855 | } |
| 856 | if( zId && (nId = (int)strlen(zId))>=8 && strncmp(zId,MANIFEST_UUID,nId)==0 ){ |
| 857 | g.isConst = 1; |
| 858 | }else{ |
| 859 | etag_require(ETAG_CONST); |
| 860 | } |
| 861 | blob_init(&out, zTxt, -1); |
| 862 | cgi_set_content(&out); |
| 863 | } |
| 864 | |
| 865 | |
| 866 | /* |
| 867 | ** WEBPAGE: test_env |
| 868 |