Index: src/branch.c
==================================================================
--- src/branch.c
+++ src/branch.c
@@ -683,11 +683,10 @@
style_set_current_feature("branch");
style_header("Branches");
style_submenu_element("List", "brlist");
login_anonymous_available();
timeline_ss_submenu();
- cookie_render();
@
The initial check-in for each branch:
blob_append(&sql, timeline_query_for_www(), -1);
blob_append_sql(&sql,
"AND blob.rid IN (SELECT rid FROM tagxref"
" WHERE tagtype>0 AND tagid=%d AND srcid!=0)", TAG_BRANCH);
Index: src/cgi.c
==================================================================
--- src/cgi.c
+++ src/cgi.c
@@ -1159,16 +1159,28 @@
#endif
z = (char*)P("HTTP_COOKIE");
if( z ){
z = fossil_strdup(z);
add_param_list(z, ';');
+ z = (char*)cookie_value("skin",0);
+ if(z){
+ skin_use_alternative(z, 2);
+ }
}
z = (char*)P("QUERY_STRING");
if( z ){
z = fossil_strdup(z);
add_param_list(z, '&');
+ z = (char*)P("skin");
+ if(z){
+ char *zErr = skin_use_alternative(z, 2);
+ if(!zErr){
+ cookie_write_parameter("skin","skin",z);
+ }
+ fossil_free(zErr);
+ }
}
z = (char*)P("REMOTE_ADDR");
if( z ){
g.zIpAddr = fossil_strdup(z);
Index: src/cookies.c
==================================================================
--- src/cookies.c
+++ src/cookies.c
@@ -173,15 +173,16 @@
const char *zDflt /* Default value for the parameter */
){
cookie_readwrite(zQP, zPName, zDflt, COOKIE_READ|COOKIE_WRITE);
}
-/* Update the user preferences cookie, if necessary, and shut down this
-** module
+/* Update the user preferences cookie, if necessary, and shut down
+** this module. The cookie is only emitted if its value has actually
+** changed since the request started.
*/
void cookie_render(void){
- if( cookies.bChanged && P("udc")!=0 ){
+ if( cookies.bChanged ){
Blob new;
int i;
blob_init(&new, 0, 0);
for(i=0;i0 ) blob_append(&new, ",", 1);
Index: src/descendants.c
==================================================================
--- src/descendants.c
+++ src/descendants.c
@@ -565,11 +565,10 @@
url_reset(&url);
style_set_current_feature("leaves");
style_header("Leaves");
login_anonymous_available();
timeline_ss_submenu();
- cookie_render();
#if 0
style_sidebox_begin("Nomenclature:", "33%");
@
@ - A
leaf
@ is a check-in with no descendants in the same branch.
Index: src/finfo.c
==================================================================
--- src/finfo.c
+++ src/finfo.c
@@ -364,11 +364,10 @@
url_initialize(&url, "finfo");
if( brBg ) url_add_parameter(&url, "brbg", 0);
if( uBg ) url_add_parameter(&url, "ubg", 0);
ridFrom = name_to_rid_www("from");
zPrevDate[0] = 0;
- cookie_render();
if( fnid==0 ){
@ No such file: %h(zFilename)
style_finish_page();
return;
}
Index: src/info.c
==================================================================
--- src/info.c
+++ src/info.c
@@ -939,11 +939,10 @@
append_file_change_line(zUuid, zName, zOld, zNew, zOldName,
diffFlags,pRe,mperm);
}
db_finalize(&q3);
append_diff_javascript(diffType==2);
- cookie_render();
style_finish_page();
}
/*
** WEBPAGE: winfo
@@ -1185,11 +1184,10 @@
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
login_anonymous_available();
load_control();
diffType = preferred_diff_type();
- cookie_render();
zRe = P("regex");
if( zRe ) re_compile(&pRe, zRe, 0);
zBranch = P("branch");
if( zBranch && zBranch[0]==0 ) zBranch = 0;
if( zBranch ){
@@ -1706,11 +1704,10 @@
int verbose = PB("verbose");
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
diffType = preferred_diff_type();
- cookie_render();
if( P("from") && P("to") ){
v1 = artifact_from_ci_and_filename("from");
v2 = artifact_from_ci_and_filename("to");
}else{
Stmt q;
Index: src/main.c
==================================================================
--- src/main.c
+++ src/main.c
@@ -1838,33 +1838,11 @@
zPathInfo += 7;
g.nExtraURL += 7;
cgi_replace_parameter("PATH_INFO", zPathInfo);
cgi_replace_parameter("SCRIPT_NAME", zNewScript);
etag_cancel();
- }else if( zPathInfo && strncmp(zPathInfo, "/skn_", 5)==0 ){
- int i;
- char *zAlt;
- char *zErr;
- char *z;
- while( (z = strstr(zPathInfo+1,"/skn_"))!=0 ) zPathInfo = z;
- for(i=5; zPathInfo[i] && zPathInfo[i]!='/'; i++){}
- zAlt = mprintf("%.*s", i-5, zPathInfo+5);
- zErr = skin_use_alternative(zAlt);
- if( zErr ){
- fossil_free(zErr);
- }else{
- char *zNewScript;
- zNewScript = mprintf("%T/skn_%s", P("SCRIPT_NAME"), zAlt);
- if( g.zTop ) g.zTop = mprintf("%R/skn_%s", zAlt);
- if( g.zBaseURL ) g.zBaseURL = mprintf("%s/skn_%s", g.zBaseURL, zAlt);
- zPathInfo += i;
- g.nExtraURL += i;
- cgi_replace_parameter("PATH_INFO", zPathInfo);
- cgi_replace_parameter("SCRIPT_NAME", zNewScript);
- }
- fossil_free(zAlt);
- }
+ }
/* If the content type is application/x-fossil or
** application/x-fossil-debug, then a sync/push/pull/clone is
** desired, so default the PATH_INFO to /xfer
*/
@@ -2378,11 +2356,11 @@
** Use one of the built-in skins defined by LABEL. LABEL is the
** name of the subdirectory under the skins/ directory that holds
** the elements of the built-in skin. If LABEL does not match,
** this directive is a silent no-op.
*/
- skin_use_alternative(blob_str(&value));
+ fossil_free(skin_use_alternative(blob_str(&value), 1));
blob_reset(&value);
continue;
}
if( blob_eq(&key, "jsmode:") && blob_token(&line, &value) ){
/* jsmode: MODE
Index: src/skins.c
==================================================================
--- src/skins.c
+++ src/skins.c
@@ -104,21 +104,61 @@
**
** If the alternative skin name contains one or more '/' characters, then
** it is assumed to be a directory on disk that holds override css.txt,
** footer.txt, and header.txt. This mode can be used for interactive
** development of new skins.
+**
+** The 2nd parameter is a ranking of how important this alternative
+** skin declaration is, and lower values trump higher ones. If a call
+** to this function passes a higher-valued rank than a previous call,
+** the subsequent call becomes a no-op. Only calls with the same or
+** lower rank (i.e. higher priority) will overwrite a previous
+** setting. This approach is used because the CGI/server-time
+** initialization happens in an order which is incompatible with our
+** preferred ranking, making it otherwise more invasive to tell the
+** internals "the --skin flag ranks higher than a URL parameter" (the
+** former gets initialized before both URL parameters and the /draft
+** path determination).
+**
+** The rankings were initially defined in
+** https://fossil-scm.org/forum/forumpost/caf8c9a8bb
+** and are:
+**
+** 0) A skin name matching the glob draft[1-9] trumps everything else.
+**
+** 1) The --skin flag or skin: CGI config setting.
+**
+** 2) The "skin" display setting cookie or URL argument, in that
+** order. If the "skin" URL argument is provided and refers to a legal
+** skin then that will update the display cookie. If the skin name is
+** illegal it is silently ignored.
+**
+** 3) Skin properties from the CONFIG db table
+**
+** 4) Default skin.
+**
+** As a special case, the name "_repo" resets zAltSkinDir and
+** pAltSkin to 0 to indicate that the current config-side skin should
+** be used (rank 3, above), then returns 0.
*/
-char *skin_use_alternative(const char *zName){
+char *skin_use_alternative(const char *zName, int rank){
+ static int currentRank = 5;
int i;
Blob err = BLOB_INITIALIZER;
- if( strchr(zName, '/')!=0 ){
+ if(rank > currentRank) return 0;
+ if( 1==rank && strchr(zName, '/')!=0 ){
zAltSkinDir = fossil_strdup(zName);
return 0;
}
if( sqlite3_strglob("draft[1-9]", zName)==0 ){
skin_use_draft(zName[5] - '0');
return 0;
+ }
+ if(zName && 0==strcmp("_repo",zName)){
+ pAltSkin = 0;
+ zAltSkinDir = 0;
+ return 0;
}
for(i=0; iWarning: this fossil instance was started with
+ @ a hard-coded skin value which trumps any option selected below.
+ @ A skins selected below will be recorded in your prefere cookie
+ @ but will not be used until/unless the site administrator
+ @ configures the site to run without a forced hard-coded skin.
+ @
+ }
@ The following skins are available for this repository:
@
if( pAltSkin==0 && zAltSkinDir==0 && iDraftSkin==0 ){
@ - Standard skin for this repository ← Currently in use
}else{
- @
- %z(href("%s/skins",zBase))Standard skin for this repository
+ @
- %z(href("%R/skins?skin=_repo"))Standard skin for this repository
}
for(i=0; i %h(aBuiltinSkin[i].zDesc) ← Currently in use
}else{
- char *zUrl = href("%s/skn_%s/skins", zBase, aBuiltinSkin[i].zLabel);
+ char *zUrl = href("%R/skins?skin=%T", aBuiltinSkin[i].zLabel);
@
- %z(zUrl)%h(aBuiltinSkin[i].zDesc)
}
}
@
style_finish_page();
fossil_free(zBase);
}
Index: src/style.c
==================================================================
--- src/style.c
+++ src/style.c
@@ -1011,10 +1011,14 @@
if( sqlite3_strlike("%