Fossil SCM

Alternative skins can be determined by the "skin" field of the display preferences cookie. The "skn_X" mechanism is removed.

drh 2021-03-02 13:55 trunk merge
Commit 3339420778776126eb80c9ef23d98e964dc5411d1d0ed920240d0bf418696eea
--- src/branch.c
+++ src/branch.c
@@ -683,11 +683,10 @@
683683
style_set_current_feature("branch");
684684
style_header("Branches");
685685
style_submenu_element("List", "brlist");
686686
login_anonymous_available();
687687
timeline_ss_submenu();
688
- cookie_render();
689688
@ <h2>The initial check-in for each branch:</h2>
690689
blob_append(&sql, timeline_query_for_www(), -1);
691690
blob_append_sql(&sql,
692691
"AND blob.rid IN (SELECT rid FROM tagxref"
693692
" WHERE tagtype>0 AND tagid=%d AND srcid!=0)", TAG_BRANCH);
694693
--- src/branch.c
+++ src/branch.c
@@ -683,11 +683,10 @@
683 style_set_current_feature("branch");
684 style_header("Branches");
685 style_submenu_element("List", "brlist");
686 login_anonymous_available();
687 timeline_ss_submenu();
688 cookie_render();
689 @ <h2>The initial check-in for each branch:</h2>
690 blob_append(&sql, timeline_query_for_www(), -1);
691 blob_append_sql(&sql,
692 "AND blob.rid IN (SELECT rid FROM tagxref"
693 " WHERE tagtype>0 AND tagid=%d AND srcid!=0)", TAG_BRANCH);
694
--- src/branch.c
+++ src/branch.c
@@ -683,11 +683,10 @@
683 style_set_current_feature("branch");
684 style_header("Branches");
685 style_submenu_element("List", "brlist");
686 login_anonymous_available();
687 timeline_ss_submenu();
 
688 @ <h2>The initial check-in for each branch:</h2>
689 blob_append(&sql, timeline_query_for_www(), -1);
690 blob_append_sql(&sql,
691 "AND blob.rid IN (SELECT rid FROM tagxref"
692 " WHERE tagtype>0 AND tagid=%d AND srcid!=0)", TAG_BRANCH);
693
+12
--- src/cgi.c
+++ src/cgi.c
@@ -1159,16 +1159,28 @@
11591159
#endif
11601160
z = (char*)P("HTTP_COOKIE");
11611161
if( z ){
11621162
z = fossil_strdup(z);
11631163
add_param_list(z, ';');
1164
+ z = (char*)cookie_value("skin",0);
1165
+ if(z){
1166
+ skin_use_alternative(z, 2);
1167
+ }
11641168
}
11651169
11661170
z = (char*)P("QUERY_STRING");
11671171
if( z ){
11681172
z = fossil_strdup(z);
11691173
add_param_list(z, '&');
1174
+ z = (char*)P("skin");
1175
+ if(z){
1176
+ char *zErr = skin_use_alternative(z, 2);
1177
+ if(!zErr){
1178
+ cookie_write_parameter("skin","skin",z);
1179
+ }
1180
+ fossil_free(zErr);
1181
+ }
11701182
}
11711183
11721184
z = (char*)P("REMOTE_ADDR");
11731185
if( z ){
11741186
g.zIpAddr = fossil_strdup(z);
11751187
--- src/cgi.c
+++ src/cgi.c
@@ -1159,16 +1159,28 @@
1159 #endif
1160 z = (char*)P("HTTP_COOKIE");
1161 if( z ){
1162 z = fossil_strdup(z);
1163 add_param_list(z, ';');
 
 
 
 
1164 }
1165
1166 z = (char*)P("QUERY_STRING");
1167 if( z ){
1168 z = fossil_strdup(z);
1169 add_param_list(z, '&');
 
 
 
 
 
 
 
 
1170 }
1171
1172 z = (char*)P("REMOTE_ADDR");
1173 if( z ){
1174 g.zIpAddr = fossil_strdup(z);
1175
--- src/cgi.c
+++ src/cgi.c
@@ -1159,16 +1159,28 @@
1159 #endif
1160 z = (char*)P("HTTP_COOKIE");
1161 if( z ){
1162 z = fossil_strdup(z);
1163 add_param_list(z, ';');
1164 z = (char*)cookie_value("skin",0);
1165 if(z){
1166 skin_use_alternative(z, 2);
1167 }
1168 }
1169
1170 z = (char*)P("QUERY_STRING");
1171 if( z ){
1172 z = fossil_strdup(z);
1173 add_param_list(z, '&');
1174 z = (char*)P("skin");
1175 if(z){
1176 char *zErr = skin_use_alternative(z, 2);
1177 if(!zErr){
1178 cookie_write_parameter("skin","skin",z);
1179 }
1180 fossil_free(zErr);
1181 }
1182 }
1183
1184 z = (char*)P("REMOTE_ADDR");
1185 if( z ){
1186 g.zIpAddr = fossil_strdup(z);
1187
+4 -3
--- src/cookies.c
+++ src/cookies.c
@@ -173,15 +173,16 @@
173173
const char *zDflt /* Default value for the parameter */
174174
){
175175
cookie_readwrite(zQP, zPName, zDflt, COOKIE_READ|COOKIE_WRITE);
176176
}
177177
178
-/* Update the user preferences cookie, if necessary, and shut down this
179
-** module
178
+/* Update the user preferences cookie, if necessary, and shut down
179
+** this module. The cookie is only emitted if its value has actually
180
+** changed since the request started.
180181
*/
181182
void cookie_render(void){
182
- if( cookies.bChanged && P("udc")!=0 ){
183
+ if( cookies.bChanged ){
183184
Blob new;
184185
int i;
185186
blob_init(&new, 0, 0);
186187
for(i=0;i<cookies.nParam;i++){
187188
if( i>0 ) blob_append(&new, ",", 1);
188189
--- src/cookies.c
+++ src/cookies.c
@@ -173,15 +173,16 @@
173 const char *zDflt /* Default value for the parameter */
174 ){
175 cookie_readwrite(zQP, zPName, zDflt, COOKIE_READ|COOKIE_WRITE);
176 }
177
178 /* Update the user preferences cookie, if necessary, and shut down this
179 ** module
 
180 */
181 void cookie_render(void){
182 if( cookies.bChanged && P("udc")!=0 ){
183 Blob new;
184 int i;
185 blob_init(&new, 0, 0);
186 for(i=0;i<cookies.nParam;i++){
187 if( i>0 ) blob_append(&new, ",", 1);
188
--- src/cookies.c
+++ src/cookies.c
@@ -173,15 +173,16 @@
173 const char *zDflt /* Default value for the parameter */
174 ){
175 cookie_readwrite(zQP, zPName, zDflt, COOKIE_READ|COOKIE_WRITE);
176 }
177
178 /* Update the user preferences cookie, if necessary, and shut down
179 ** this module. The cookie is only emitted if its value has actually
180 ** changed since the request started.
181 */
182 void cookie_render(void){
183 if( cookies.bChanged ){
184 Blob new;
185 int i;
186 blob_init(&new, 0, 0);
187 for(i=0;i<cookies.nParam;i++){
188 if( i>0 ) blob_append(&new, ",", 1);
189
--- src/descendants.c
+++ src/descendants.c
@@ -565,11 +565,10 @@
565565
url_reset(&url);
566566
style_set_current_feature("leaves");
567567
style_header("Leaves");
568568
login_anonymous_available();
569569
timeline_ss_submenu();
570
- cookie_render();
571570
#if 0
572571
style_sidebox_begin("Nomenclature:", "33%");
573572
@ <ol>
574573
@ <li> A <div class="sideboxDescribed">leaf</div>
575574
@ is a check-in with no descendants in the same branch.</li>
576575
--- src/descendants.c
+++ src/descendants.c
@@ -565,11 +565,10 @@
565 url_reset(&url);
566 style_set_current_feature("leaves");
567 style_header("Leaves");
568 login_anonymous_available();
569 timeline_ss_submenu();
570 cookie_render();
571 #if 0
572 style_sidebox_begin("Nomenclature:", "33%");
573 @ <ol>
574 @ <li> A <div class="sideboxDescribed">leaf</div>
575 @ is a check-in with no descendants in the same branch.</li>
576
--- src/descendants.c
+++ src/descendants.c
@@ -565,11 +565,10 @@
565 url_reset(&url);
566 style_set_current_feature("leaves");
567 style_header("Leaves");
568 login_anonymous_available();
569 timeline_ss_submenu();
 
570 #if 0
571 style_sidebox_begin("Nomenclature:", "33%");
572 @ <ol>
573 @ <li> A <div class="sideboxDescribed">leaf</div>
574 @ is a check-in with no descendants in the same branch.</li>
575
--- src/finfo.c
+++ src/finfo.c
@@ -364,11 +364,10 @@
364364
url_initialize(&url, "finfo");
365365
if( brBg ) url_add_parameter(&url, "brbg", 0);
366366
if( uBg ) url_add_parameter(&url, "ubg", 0);
367367
ridFrom = name_to_rid_www("from");
368368
zPrevDate[0] = 0;
369
- cookie_render();
370369
if( fnid==0 ){
371370
@ No such file: %h(zFilename)
372371
style_finish_page();
373372
return;
374373
}
375374
--- src/finfo.c
+++ src/finfo.c
@@ -364,11 +364,10 @@
364 url_initialize(&url, "finfo");
365 if( brBg ) url_add_parameter(&url, "brbg", 0);
366 if( uBg ) url_add_parameter(&url, "ubg", 0);
367 ridFrom = name_to_rid_www("from");
368 zPrevDate[0] = 0;
369 cookie_render();
370 if( fnid==0 ){
371 @ No such file: %h(zFilename)
372 style_finish_page();
373 return;
374 }
375
--- src/finfo.c
+++ src/finfo.c
@@ -364,11 +364,10 @@
364 url_initialize(&url, "finfo");
365 if( brBg ) url_add_parameter(&url, "brbg", 0);
366 if( uBg ) url_add_parameter(&url, "ubg", 0);
367 ridFrom = name_to_rid_www("from");
368 zPrevDate[0] = 0;
 
369 if( fnid==0 ){
370 @ No such file: %h(zFilename)
371 style_finish_page();
372 return;
373 }
374
-3
--- src/info.c
+++ src/info.c
@@ -939,11 +939,10 @@
939939
append_file_change_line(zUuid, zName, zOld, zNew, zOldName,
940940
diffFlags,pRe,mperm);
941941
}
942942
db_finalize(&q3);
943943
append_diff_javascript(diffType==2);
944
- cookie_render();
945944
style_finish_page();
946945
}
947946
948947
/*
949948
** WEBPAGE: winfo
@@ -1185,11 +1184,10 @@
11851184
login_check_credentials();
11861185
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
11871186
login_anonymous_available();
11881187
load_control();
11891188
diffType = preferred_diff_type();
1190
- cookie_render();
11911189
zRe = P("regex");
11921190
if( zRe ) re_compile(&pRe, zRe, 0);
11931191
zBranch = P("branch");
11941192
if( zBranch && zBranch[0]==0 ) zBranch = 0;
11951193
if( zBranch ){
@@ -1706,11 +1704,10 @@
17061704
int verbose = PB("verbose");
17071705
17081706
login_check_credentials();
17091707
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
17101708
diffType = preferred_diff_type();
1711
- cookie_render();
17121709
if( P("from") && P("to") ){
17131710
v1 = artifact_from_ci_and_filename("from");
17141711
v2 = artifact_from_ci_and_filename("to");
17151712
}else{
17161713
Stmt q;
17171714
--- src/info.c
+++ src/info.c
@@ -939,11 +939,10 @@
939 append_file_change_line(zUuid, zName, zOld, zNew, zOldName,
940 diffFlags,pRe,mperm);
941 }
942 db_finalize(&q3);
943 append_diff_javascript(diffType==2);
944 cookie_render();
945 style_finish_page();
946 }
947
948 /*
949 ** WEBPAGE: winfo
@@ -1185,11 +1184,10 @@
1185 login_check_credentials();
1186 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1187 login_anonymous_available();
1188 load_control();
1189 diffType = preferred_diff_type();
1190 cookie_render();
1191 zRe = P("regex");
1192 if( zRe ) re_compile(&pRe, zRe, 0);
1193 zBranch = P("branch");
1194 if( zBranch && zBranch[0]==0 ) zBranch = 0;
1195 if( zBranch ){
@@ -1706,11 +1704,10 @@
1706 int verbose = PB("verbose");
1707
1708 login_check_credentials();
1709 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1710 diffType = preferred_diff_type();
1711 cookie_render();
1712 if( P("from") && P("to") ){
1713 v1 = artifact_from_ci_and_filename("from");
1714 v2 = artifact_from_ci_and_filename("to");
1715 }else{
1716 Stmt q;
1717
--- src/info.c
+++ src/info.c
@@ -939,11 +939,10 @@
939 append_file_change_line(zUuid, zName, zOld, zNew, zOldName,
940 diffFlags,pRe,mperm);
941 }
942 db_finalize(&q3);
943 append_diff_javascript(diffType==2);
 
944 style_finish_page();
945 }
946
947 /*
948 ** WEBPAGE: winfo
@@ -1185,11 +1184,10 @@
1184 login_check_credentials();
1185 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1186 login_anonymous_available();
1187 load_control();
1188 diffType = preferred_diff_type();
 
1189 zRe = P("regex");
1190 if( zRe ) re_compile(&pRe, zRe, 0);
1191 zBranch = P("branch");
1192 if( zBranch && zBranch[0]==0 ) zBranch = 0;
1193 if( zBranch ){
@@ -1706,11 +1704,10 @@
1704 int verbose = PB("verbose");
1705
1706 login_check_credentials();
1707 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1708 diffType = preferred_diff_type();
 
1709 if( P("from") && P("to") ){
1710 v1 = artifact_from_ci_and_filename("from");
1711 v2 = artifact_from_ci_and_filename("to");
1712 }else{
1713 Stmt q;
1714
+2 -24
--- src/main.c
+++ src/main.c
@@ -1838,33 +1838,11 @@
18381838
zPathInfo += 7;
18391839
g.nExtraURL += 7;
18401840
cgi_replace_parameter("PATH_INFO", zPathInfo);
18411841
cgi_replace_parameter("SCRIPT_NAME", zNewScript);
18421842
etag_cancel();
1843
- }else if( zPathInfo && strncmp(zPathInfo, "/skn_", 5)==0 ){
1844
- int i;
1845
- char *zAlt;
1846
- char *zErr;
1847
- char *z;
1848
- while( (z = strstr(zPathInfo+1,"/skn_"))!=0 ) zPathInfo = z;
1849
- for(i=5; zPathInfo[i] && zPathInfo[i]!='/'; i++){}
1850
- zAlt = mprintf("%.*s", i-5, zPathInfo+5);
1851
- zErr = skin_use_alternative(zAlt);
1852
- if( zErr ){
1853
- fossil_free(zErr);
1854
- }else{
1855
- char *zNewScript;
1856
- zNewScript = mprintf("%T/skn_%s", P("SCRIPT_NAME"), zAlt);
1857
- if( g.zTop ) g.zTop = mprintf("%R/skn_%s", zAlt);
1858
- if( g.zBaseURL ) g.zBaseURL = mprintf("%s/skn_%s", g.zBaseURL, zAlt);
1859
- zPathInfo += i;
1860
- g.nExtraURL += i;
1861
- cgi_replace_parameter("PATH_INFO", zPathInfo);
1862
- cgi_replace_parameter("SCRIPT_NAME", zNewScript);
1863
- }
1864
- fossil_free(zAlt);
1865
- }
1843
+ }
18661844
18671845
/* If the content type is application/x-fossil or
18681846
** application/x-fossil-debug, then a sync/push/pull/clone is
18691847
** desired, so default the PATH_INFO to /xfer
18701848
*/
@@ -2378,11 +2356,11 @@
23782356
** Use one of the built-in skins defined by LABEL. LABEL is the
23792357
** name of the subdirectory under the skins/ directory that holds
23802358
** the elements of the built-in skin. If LABEL does not match,
23812359
** this directive is a silent no-op.
23822360
*/
2383
- skin_use_alternative(blob_str(&value));
2361
+ fossil_free(skin_use_alternative(blob_str(&value), 1));
23842362
blob_reset(&value);
23852363
continue;
23862364
}
23872365
if( blob_eq(&key, "jsmode:") && blob_token(&line, &value) ){
23882366
/* jsmode: MODE
23892367
--- src/main.c
+++ src/main.c
@@ -1838,33 +1838,11 @@
1838 zPathInfo += 7;
1839 g.nExtraURL += 7;
1840 cgi_replace_parameter("PATH_INFO", zPathInfo);
1841 cgi_replace_parameter("SCRIPT_NAME", zNewScript);
1842 etag_cancel();
1843 }else if( zPathInfo && strncmp(zPathInfo, "/skn_", 5)==0 ){
1844 int i;
1845 char *zAlt;
1846 char *zErr;
1847 char *z;
1848 while( (z = strstr(zPathInfo+1,"/skn_"))!=0 ) zPathInfo = z;
1849 for(i=5; zPathInfo[i] && zPathInfo[i]!='/'; i++){}
1850 zAlt = mprintf("%.*s", i-5, zPathInfo+5);
1851 zErr = skin_use_alternative(zAlt);
1852 if( zErr ){
1853 fossil_free(zErr);
1854 }else{
1855 char *zNewScript;
1856 zNewScript = mprintf("%T/skn_%s", P("SCRIPT_NAME"), zAlt);
1857 if( g.zTop ) g.zTop = mprintf("%R/skn_%s", zAlt);
1858 if( g.zBaseURL ) g.zBaseURL = mprintf("%s/skn_%s", g.zBaseURL, zAlt);
1859 zPathInfo += i;
1860 g.nExtraURL += i;
1861 cgi_replace_parameter("PATH_INFO", zPathInfo);
1862 cgi_replace_parameter("SCRIPT_NAME", zNewScript);
1863 }
1864 fossil_free(zAlt);
1865 }
1866
1867 /* If the content type is application/x-fossil or
1868 ** application/x-fossil-debug, then a sync/push/pull/clone is
1869 ** desired, so default the PATH_INFO to /xfer
1870 */
@@ -2378,11 +2356,11 @@
2378 ** Use one of the built-in skins defined by LABEL. LABEL is the
2379 ** name of the subdirectory under the skins/ directory that holds
2380 ** the elements of the built-in skin. If LABEL does not match,
2381 ** this directive is a silent no-op.
2382 */
2383 skin_use_alternative(blob_str(&value));
2384 blob_reset(&value);
2385 continue;
2386 }
2387 if( blob_eq(&key, "jsmode:") && blob_token(&line, &value) ){
2388 /* jsmode: MODE
2389
--- src/main.c
+++ src/main.c
@@ -1838,33 +1838,11 @@
1838 zPathInfo += 7;
1839 g.nExtraURL += 7;
1840 cgi_replace_parameter("PATH_INFO", zPathInfo);
1841 cgi_replace_parameter("SCRIPT_NAME", zNewScript);
1842 etag_cancel();
1843 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1844
1845 /* If the content type is application/x-fossil or
1846 ** application/x-fossil-debug, then a sync/push/pull/clone is
1847 ** desired, so default the PATH_INFO to /xfer
1848 */
@@ -2378,11 +2356,11 @@
2356 ** Use one of the built-in skins defined by LABEL. LABEL is the
2357 ** name of the subdirectory under the skins/ directory that holds
2358 ** the elements of the built-in skin. If LABEL does not match,
2359 ** this directive is a silent no-op.
2360 */
2361 fossil_free(skin_use_alternative(blob_str(&value), 1));
2362 blob_reset(&value);
2363 continue;
2364 }
2365 if( blob_eq(&key, "jsmode:") && blob_token(&line, &value) ){
2366 /* jsmode: MODE
2367
+53 -5
--- src/skins.c
+++ src/skins.c
@@ -104,21 +104,61 @@
104104
**
105105
** If the alternative skin name contains one or more '/' characters, then
106106
** it is assumed to be a directory on disk that holds override css.txt,
107107
** footer.txt, and header.txt. This mode can be used for interactive
108108
** development of new skins.
109
+**
110
+** The 2nd parameter is a ranking of how important this alternative
111
+** skin declaration is, and lower values trump higher ones. If a call
112
+** to this function passes a higher-valued rank than a previous call,
113
+** the subsequent call becomes a no-op. Only calls with the same or
114
+** lower rank (i.e. higher priority) will overwrite a previous
115
+** setting. This approach is used because the CGI/server-time
116
+** initialization happens in an order which is incompatible with our
117
+** preferred ranking, making it otherwise more invasive to tell the
118
+** internals "the --skin flag ranks higher than a URL parameter" (the
119
+** former gets initialized before both URL parameters and the /draft
120
+** path determination).
121
+**
122
+** The rankings were initially defined in
123
+** https://fossil-scm.org/forum/forumpost/caf8c9a8bb
124
+** and are:
125
+**
126
+** 0) A skin name matching the glob draft[1-9] trumps everything else.
127
+**
128
+** 1) The --skin flag or skin: CGI config setting.
129
+**
130
+** 2) The "skin" display setting cookie or URL argument, in that
131
+** order. If the "skin" URL argument is provided and refers to a legal
132
+** skin then that will update the display cookie. If the skin name is
133
+** illegal it is silently ignored.
134
+**
135
+** 3) Skin properties from the CONFIG db table
136
+**
137
+** 4) Default skin.
138
+**
139
+** As a special case, the name "_repo" resets zAltSkinDir and
140
+** pAltSkin to 0 to indicate that the current config-side skin should
141
+** be used (rank 3, above), then returns 0.
109142
*/
110
-char *skin_use_alternative(const char *zName){
143
+char *skin_use_alternative(const char *zName, int rank){
144
+ static int currentRank = 5;
111145
int i;
112146
Blob err = BLOB_INITIALIZER;
113
- if( strchr(zName, '/')!=0 ){
147
+ if(rank > currentRank) return 0;
148
+ if( 1==rank && strchr(zName, '/')!=0 ){
114149
zAltSkinDir = fossil_strdup(zName);
115150
return 0;
116151
}
117152
if( sqlite3_strglob("draft[1-9]", zName)==0 ){
118153
skin_use_draft(zName[5] - '0');
119154
return 0;
155
+ }
156
+ if(zName && 0==strcmp("_repo",zName)){
157
+ pAltSkin = 0;
158
+ zAltSkinDir = 0;
159
+ return 0;
120160
}
121161
for(i=0; i<count(aBuiltinSkin); i++){
122162
if( fossil_strcmp(aBuiltinSkin[i].zLabel, zName)==0 ){
123163
pAltSkin = &aBuiltinSkin[i];
124164
return 0;
@@ -137,11 +177,11 @@
137177
** call fossil_fatal() if an unknown skin is specified.
138178
*/
139179
void skin_override(void){
140180
const char *zSkin = find_option("skin",0,1);
141181
if( zSkin ){
142
- char *zErr = skin_use_alternative(zSkin);
182
+ char *zErr = skin_use_alternative(zSkin, 1);
143183
if( zErr ) fossil_fatal("%s", zErr);
144184
}
145185
}
146186
147187
/*
@@ -1154,24 +1194,32 @@
11541194
}
11551195
fossil_free(zPattern);
11561196
}
11571197
login_check_credentials();
11581198
style_header("Skins");
1199
+ if(zAltSkinDir && zAltSkinDir[0]){
1200
+ @ <p class="warning">Warning: this fossil instance was started with
1201
+ @ a hard-coded skin value which trumps any option selected below.
1202
+ @ A skins selected below will be recorded in your prefere cookie
1203
+ @ but will not be used until/unless the site administrator
1204
+ @ configures the site to run without a forced hard-coded skin.
1205
+ @ </p>
1206
+ }
11591207
@ <p>The following skins are available for this repository:</p>
11601208
@ <ul>
11611209
if( pAltSkin==0 && zAltSkinDir==0 && iDraftSkin==0 ){
11621210
@ <li> Standard skin for this repository &larr; <i>Currently in use</i>
11631211
}else{
1164
- @ <li> %z(href("%s/skins",zBase))Standard skin for this repository</a>
1212
+ @ <li> %z(href("%R/skins?skin=_repo"))Standard skin for this repository</a>
11651213
}
11661214
for(i=0; i<count(aBuiltinSkin); i++){
11671215
if( pAltSkin==&aBuiltinSkin[i] ){
11681216
@ <li> %h(aBuiltinSkin[i].zDesc) &larr; <i>Currently in use</i>
11691217
}else{
1170
- char *zUrl = href("%s/skn_%s/skins", zBase, aBuiltinSkin[i].zLabel);
1218
+ char *zUrl = href("%R/skins?skin=%T", aBuiltinSkin[i].zLabel);
11711219
@ <li> %z(zUrl)%h(aBuiltinSkin[i].zDesc)</a>
11721220
}
11731221
}
11741222
@ </ul>
11751223
style_finish_page();
11761224
fossil_free(zBase);
11771225
}
11781226
--- src/skins.c
+++ src/skins.c
@@ -104,21 +104,61 @@
104 **
105 ** If the alternative skin name contains one or more '/' characters, then
106 ** it is assumed to be a directory on disk that holds override css.txt,
107 ** footer.txt, and header.txt. This mode can be used for interactive
108 ** development of new skins.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109 */
110 char *skin_use_alternative(const char *zName){
 
111 int i;
112 Blob err = BLOB_INITIALIZER;
113 if( strchr(zName, '/')!=0 ){
 
114 zAltSkinDir = fossil_strdup(zName);
115 return 0;
116 }
117 if( sqlite3_strglob("draft[1-9]", zName)==0 ){
118 skin_use_draft(zName[5] - '0');
119 return 0;
 
 
 
 
 
120 }
121 for(i=0; i<count(aBuiltinSkin); i++){
122 if( fossil_strcmp(aBuiltinSkin[i].zLabel, zName)==0 ){
123 pAltSkin = &aBuiltinSkin[i];
124 return 0;
@@ -137,11 +177,11 @@
137 ** call fossil_fatal() if an unknown skin is specified.
138 */
139 void skin_override(void){
140 const char *zSkin = find_option("skin",0,1);
141 if( zSkin ){
142 char *zErr = skin_use_alternative(zSkin);
143 if( zErr ) fossil_fatal("%s", zErr);
144 }
145 }
146
147 /*
@@ -1154,24 +1194,32 @@
1154 }
1155 fossil_free(zPattern);
1156 }
1157 login_check_credentials();
1158 style_header("Skins");
 
 
 
 
 
 
 
 
1159 @ <p>The following skins are available for this repository:</p>
1160 @ <ul>
1161 if( pAltSkin==0 && zAltSkinDir==0 && iDraftSkin==0 ){
1162 @ <li> Standard skin for this repository &larr; <i>Currently in use</i>
1163 }else{
1164 @ <li> %z(href("%s/skins",zBase))Standard skin for this repository</a>
1165 }
1166 for(i=0; i<count(aBuiltinSkin); i++){
1167 if( pAltSkin==&aBuiltinSkin[i] ){
1168 @ <li> %h(aBuiltinSkin[i].zDesc) &larr; <i>Currently in use</i>
1169 }else{
1170 char *zUrl = href("%s/skn_%s/skins", zBase, aBuiltinSkin[i].zLabel);
1171 @ <li> %z(zUrl)%h(aBuiltinSkin[i].zDesc)</a>
1172 }
1173 }
1174 @ </ul>
1175 style_finish_page();
1176 fossil_free(zBase);
1177 }
1178
--- src/skins.c
+++ src/skins.c
@@ -104,21 +104,61 @@
104 **
105 ** If the alternative skin name contains one or more '/' characters, then
106 ** it is assumed to be a directory on disk that holds override css.txt,
107 ** footer.txt, and header.txt. This mode can be used for interactive
108 ** development of new skins.
109 **
110 ** The 2nd parameter is a ranking of how important this alternative
111 ** skin declaration is, and lower values trump higher ones. If a call
112 ** to this function passes a higher-valued rank than a previous call,
113 ** the subsequent call becomes a no-op. Only calls with the same or
114 ** lower rank (i.e. higher priority) will overwrite a previous
115 ** setting. This approach is used because the CGI/server-time
116 ** initialization happens in an order which is incompatible with our
117 ** preferred ranking, making it otherwise more invasive to tell the
118 ** internals "the --skin flag ranks higher than a URL parameter" (the
119 ** former gets initialized before both URL parameters and the /draft
120 ** path determination).
121 **
122 ** The rankings were initially defined in
123 ** https://fossil-scm.org/forum/forumpost/caf8c9a8bb
124 ** and are:
125 **
126 ** 0) A skin name matching the glob draft[1-9] trumps everything else.
127 **
128 ** 1) The --skin flag or skin: CGI config setting.
129 **
130 ** 2) The "skin" display setting cookie or URL argument, in that
131 ** order. If the "skin" URL argument is provided and refers to a legal
132 ** skin then that will update the display cookie. If the skin name is
133 ** illegal it is silently ignored.
134 **
135 ** 3) Skin properties from the CONFIG db table
136 **
137 ** 4) Default skin.
138 **
139 ** As a special case, the name "_repo" resets zAltSkinDir and
140 ** pAltSkin to 0 to indicate that the current config-side skin should
141 ** be used (rank 3, above), then returns 0.
142 */
143 char *skin_use_alternative(const char *zName, int rank){
144 static int currentRank = 5;
145 int i;
146 Blob err = BLOB_INITIALIZER;
147 if(rank > currentRank) return 0;
148 if( 1==rank && strchr(zName, '/')!=0 ){
149 zAltSkinDir = fossil_strdup(zName);
150 return 0;
151 }
152 if( sqlite3_strglob("draft[1-9]", zName)==0 ){
153 skin_use_draft(zName[5] - '0');
154 return 0;
155 }
156 if(zName && 0==strcmp("_repo",zName)){
157 pAltSkin = 0;
158 zAltSkinDir = 0;
159 return 0;
160 }
161 for(i=0; i<count(aBuiltinSkin); i++){
162 if( fossil_strcmp(aBuiltinSkin[i].zLabel, zName)==0 ){
163 pAltSkin = &aBuiltinSkin[i];
164 return 0;
@@ -137,11 +177,11 @@
177 ** call fossil_fatal() if an unknown skin is specified.
178 */
179 void skin_override(void){
180 const char *zSkin = find_option("skin",0,1);
181 if( zSkin ){
182 char *zErr = skin_use_alternative(zSkin, 1);
183 if( zErr ) fossil_fatal("%s", zErr);
184 }
185 }
186
187 /*
@@ -1154,24 +1194,32 @@
1194 }
1195 fossil_free(zPattern);
1196 }
1197 login_check_credentials();
1198 style_header("Skins");
1199 if(zAltSkinDir && zAltSkinDir[0]){
1200 @ <p class="warning">Warning: this fossil instance was started with
1201 @ a hard-coded skin value which trumps any option selected below.
1202 @ A skins selected below will be recorded in your prefere cookie
1203 @ but will not be used until/unless the site administrator
1204 @ configures the site to run without a forced hard-coded skin.
1205 @ </p>
1206 }
1207 @ <p>The following skins are available for this repository:</p>
1208 @ <ul>
1209 if( pAltSkin==0 && zAltSkinDir==0 && iDraftSkin==0 ){
1210 @ <li> Standard skin for this repository &larr; <i>Currently in use</i>
1211 }else{
1212 @ <li> %z(href("%R/skins?skin=_repo"))Standard skin for this repository</a>
1213 }
1214 for(i=0; i<count(aBuiltinSkin); i++){
1215 if( pAltSkin==&aBuiltinSkin[i] ){
1216 @ <li> %h(aBuiltinSkin[i].zDesc) &larr; <i>Currently in use</i>
1217 }else{
1218 char *zUrl = href("%R/skins?skin=%T", aBuiltinSkin[i].zLabel);
1219 @ <li> %z(zUrl)%h(aBuiltinSkin[i].zDesc)</a>
1220 }
1221 }
1222 @ </ul>
1223 style_finish_page();
1224 fossil_free(zBase);
1225 }
1226
--- src/style.c
+++ src/style.c
@@ -1011,10 +1011,14 @@
10111011
if( sqlite3_strlike("%</body>%", zFooter, 0)!=0 ){
10121012
style_load_all_js_files();
10131013
@ </body>
10141014
@ </html>
10151015
}
1016
+ /* Update the user display prefs cookie if it was modified during
1017
+ ** this request.
1018
+ */
1019
+ cookie_render();
10161020
}
10171021
10181022
/*
10191023
** Begin a side-box on the right-hand side of a page. The title and
10201024
** the width of the box are given as arguments. The width is usually
10211025
--- src/style.c
+++ src/style.c
@@ -1011,10 +1011,14 @@
1011 if( sqlite3_strlike("%</body>%", zFooter, 0)!=0 ){
1012 style_load_all_js_files();
1013 @ </body>
1014 @ </html>
1015 }
 
 
 
 
1016 }
1017
1018 /*
1019 ** Begin a side-box on the right-hand side of a page. The title and
1020 ** the width of the box are given as arguments. The width is usually
1021
--- src/style.c
+++ src/style.c
@@ -1011,10 +1011,14 @@
1011 if( sqlite3_strlike("%</body>%", zFooter, 0)!=0 ){
1012 style_load_all_js_files();
1013 @ </body>
1014 @ </html>
1015 }
1016 /* Update the user display prefs cookie if it was modified during
1017 ** this request.
1018 */
1019 cookie_render();
1020 }
1021
1022 /*
1023 ** Begin a side-box on the right-hand side of a page. The title and
1024 ** the width of the box are given as arguments. The width is usually
1025
-1
--- src/tag.c
+++ src/tag.c
@@ -755,11 +755,10 @@
755755
756756
style_header("Tagged Check-ins");
757757
style_submenu_element("List", "taglist");
758758
login_anonymous_available();
759759
timeline_ss_submenu();
760
- cookie_render();
761760
@ <h2>Check-ins with non-propagating tags:</h2>
762761
blob_append(&sql, timeline_query_for_www(), -1);
763762
blob_append_sql(&sql,
764763
"AND blob.rid IN (SELECT rid FROM tagxref"
765764
" WHERE tagtype=1 AND srcid>0"
766765
--- src/tag.c
+++ src/tag.c
@@ -755,11 +755,10 @@
755
756 style_header("Tagged Check-ins");
757 style_submenu_element("List", "taglist");
758 login_anonymous_available();
759 timeline_ss_submenu();
760 cookie_render();
761 @ <h2>Check-ins with non-propagating tags:</h2>
762 blob_append(&sql, timeline_query_for_www(), -1);
763 blob_append_sql(&sql,
764 "AND blob.rid IN (SELECT rid FROM tagxref"
765 " WHERE tagtype=1 AND srcid>0"
766
--- src/tag.c
+++ src/tag.c
@@ -755,11 +755,10 @@
755
756 style_header("Tagged Check-ins");
757 style_submenu_element("List", "taglist");
758 login_anonymous_available();
759 timeline_ss_submenu();
 
760 @ <h2>Check-ins with non-propagating tags:</h2>
761 blob_append(&sql, timeline_query_for_www(), -1);
762 blob_append_sql(&sql,
763 "AND blob.rid IN (SELECT rid FROM tagxref"
764 " WHERE tagtype=1 AND srcid>0"
765
--- src/timeline.c
+++ src/timeline.c
@@ -1754,11 +1754,10 @@
17541754
cgi_set_parameter("y", zType);
17551755
}
17561756
if( zType[0]=='a' || zType[0]=='c' ){
17571757
cookie_write_parameter("y","y",zType);
17581758
}
1759
- cookie_render();
17601759
17611760
/* Convert the cf=FILEHASH query parameter into a c=CHECKINHASH value */
17621761
if( P("cf")!=0 ){
17631762
zCirca = db_text(0,
17641763
"SELECT (SELECT uuid FROM blob WHERE rid=mlink.mid)"
17651764
--- src/timeline.c
+++ src/timeline.c
@@ -1754,11 +1754,10 @@
1754 cgi_set_parameter("y", zType);
1755 }
1756 if( zType[0]=='a' || zType[0]=='c' ){
1757 cookie_write_parameter("y","y",zType);
1758 }
1759 cookie_render();
1760
1761 /* Convert the cf=FILEHASH query parameter into a c=CHECKINHASH value */
1762 if( P("cf")!=0 ){
1763 zCirca = db_text(0,
1764 "SELECT (SELECT uuid FROM blob WHERE rid=mlink.mid)"
1765
--- src/timeline.c
+++ src/timeline.c
@@ -1754,11 +1754,10 @@
1754 cgi_set_parameter("y", zType);
1755 }
1756 if( zType[0]=='a' || zType[0]=='c' ){
1757 cookie_write_parameter("y","y",zType);
1758 }
 
1759
1760 /* Convert the cf=FILEHASH query parameter into a c=CHECKINHASH value */
1761 if( P("cf")!=0 ){
1762 zCirca = db_text(0,
1763 "SELECT (SELECT uuid FROM blob WHERE rid=mlink.mid)"
1764
--- www/changes.wiki
+++ www/changes.wiki
@@ -21,24 +21,25 @@
2121
check-in.
2222
* The "pikchr-background" settings is now available in
2323
"detail.txt" skin files, for better control of Pikchr
2424
colors in inverted color schemes.
2525
* The hamburger menu is now available on the built-in
26
- "[/skn_ardoise/doc/trunk/www/changes.wiki#v2_15|ardoise]" and
27
- "[/skn_plain_gray/doc/trunk/www/changes.wiki#v2_15|plain_gray]"
26
+ "[/doc/trunk/www/changes.wiki?skin=ardoise#v2_15|ardoise]" and
27
+ "[/doc/trunk/www/changes.wiki?skin=plain_gray#v2_15|plain_gray]"
2828
skins.
29
- * Add the --list option to the
29
+ * Add the <tt>--list</tt> option to the
3030
[/help?cmd=tarball|tarball],
3131
[/help?cmd=zip|zip], and [/help?cmd=sqlar|sqlar]
3232
commands.
3333
* The javascript used to implement the hamburger menu on the
3434
default built-in skin has been made generic so that it is usable
3535
by a variety of skins, and promoted to an ordinary built-in
3636
javascript file.
3737
* Any built-in skin named "X" can be used instead of the standard
38
- repository skin by including the term "skn_X" at the beginning
39
- of the URL path.
38
+ repository skin by adding the URL parameter <tt>skin=X</tt> to the
39
+ request, and that selection is persistent using a cookie. The
40
+ [/skins] page may be used to select a skin.
4041
* New TH1 commands: "builtin_request_js", "capexpr",
4142
"foreach", "string match"
4243
4344
<a name='v2_14'></a>
4445
<h2>Changes for Version 2.14 (2021-01-20)</h2>
4546
--- www/changes.wiki
+++ www/changes.wiki
@@ -21,24 +21,25 @@
21 check-in.
22 * The "pikchr-background" settings is now available in
23 "detail.txt" skin files, for better control of Pikchr
24 colors in inverted color schemes.
25 * The hamburger menu is now available on the built-in
26 "[/skn_ardoise/doc/trunk/www/changes.wiki#v2_15|ardoise]" and
27 "[/skn_plain_gray/doc/trunk/www/changes.wiki#v2_15|plain_gray]"
28 skins.
29 * Add the --list option to the
30 [/help?cmd=tarball|tarball],
31 [/help?cmd=zip|zip], and [/help?cmd=sqlar|sqlar]
32 commands.
33 * The javascript used to implement the hamburger menu on the
34 default built-in skin has been made generic so that it is usable
35 by a variety of skins, and promoted to an ordinary built-in
36 javascript file.
37 * Any built-in skin named "X" can be used instead of the standard
38 repository skin by including the term "skn_X" at the beginning
39 of the URL path.
 
40 * New TH1 commands: "builtin_request_js", "capexpr",
41 "foreach", "string match"
42
43 <a name='v2_14'></a>
44 <h2>Changes for Version 2.14 (2021-01-20)</h2>
45
--- www/changes.wiki
+++ www/changes.wiki
@@ -21,24 +21,25 @@
21 check-in.
22 * The "pikchr-background" settings is now available in
23 "detail.txt" skin files, for better control of Pikchr
24 colors in inverted color schemes.
25 * The hamburger menu is now available on the built-in
26 "[/doc/trunk/www/changes.wiki?skin=ardoise#v2_15|ardoise]" and
27 "[/doc/trunk/www/changes.wiki?skin=plain_gray#v2_15|plain_gray]"
28 skins.
29 * Add the <tt>--list</tt> option to the
30 [/help?cmd=tarball|tarball],
31 [/help?cmd=zip|zip], and [/help?cmd=sqlar|sqlar]
32 commands.
33 * The javascript used to implement the hamburger menu on the
34 default built-in skin has been made generic so that it is usable
35 by a variety of skins, and promoted to an ordinary built-in
36 javascript file.
37 * Any built-in skin named "X" can be used instead of the standard
38 repository skin by adding the URL parameter <tt>skin=X</tt> to the
39 request, and that selection is persistent using a cookie. The
40 [/skins] page may be used to select a skin.
41 * New TH1 commands: "builtin_request_js", "capexpr",
42 "foreach", "string match"
43
44 <a name='v2_14'></a>
45 <h2>Changes for Version 2.14 (2021-01-20)</h2>
46

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button