Fossil SCM

style.css now checks for a builtin file named after the first path component of the referer (sic), rather than PD("name"), however, we still have to emit style.css/NAME in order to pick up the the name-specific CSS, otherwise /style.css?id=... is the same for all pages and a page with its own style may pick up a cached copy without its own styles, or with the styles from another page.

stephan 2020-05-18 02:59 style-css-revamp
Commit 5abc0f6e79dfbfc5bd9b57377002805227b02e2d4a01f24c294b2181a1f202c2
3 files changed +36 +2 -2 +20 -1
+36
--- src/cgi.c
+++ src/cgi.c
@@ -447,10 +447,46 @@
447447
zRef = P("HTTP_REFERER");
448448
if( zRef==0 ) zRef = zDefault;
449449
}
450450
return zRef;
451451
}
452
+
453
+/*
454
+** If cgi_referer(0) returns a non-0 AND the referrer is from the same
455
+** fossil app path (i.e. the referrer's path starts with g.zTop), this
456
+** function returns the first path element of the referring page, up
457
+** to, but not including, the first slash. Thus if he refer[r]er is
458
+** https://foo.com/fossil.cgi/foo/bar, this returns "foo". The
459
+** returned memory is malloc'd and needs to be freed by the caller.
460
+*/
461
+char * cgi_referer_fossil_page_name(){
462
+ UrlData url;
463
+ char * zPage = 0;
464
+ const char * zRef = cgi_referer(0);
465
+
466
+ if(zRef==0) return 0;
467
+ memset(&url, 0, sizeof(url));
468
+ url_parse_local(zRef, 0, &url);
469
+ if(url.path==strstr(url.path, g.zTop)){
470
+ /* g.zTop is, e.g., /cgi-bin/fossil.cgi,
471
+ url.path is, e.g., /cgi-bin/fossil.cgi/page/... */
472
+ char * zSlash = 0;
473
+ zPage = url.path + strlen(g.zTop);
474
+ if('/' == zPage[0]){
475
+ *zPage++ = 0;
476
+ if((zSlash = strstr(zPage,"/"))!=0){
477
+ *zSlash = 0;
478
+ }
479
+ zPage = mprintf("%s", zPage);
480
+ }else{ /*unexpected result*/
481
+ zPage = 0;
482
+ }
483
+ }
484
+ url_cleanup(&url);
485
+ return zPage;
486
+}
487
+
452488
453489
/*
454490
** Return true if the current request appears to be safe from a
455491
** Cross-Site Request Forgery (CSRF) attack. Conditions that must
456492
** be met:
457493
--- src/cgi.c
+++ src/cgi.c
@@ -447,10 +447,46 @@
447 zRef = P("HTTP_REFERER");
448 if( zRef==0 ) zRef = zDefault;
449 }
450 return zRef;
451 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
452
453 /*
454 ** Return true if the current request appears to be safe from a
455 ** Cross-Site Request Forgery (CSRF) attack. Conditions that must
456 ** be met:
457
--- src/cgi.c
+++ src/cgi.c
@@ -447,10 +447,46 @@
447 zRef = P("HTTP_REFERER");
448 if( zRef==0 ) zRef = zDefault;
449 }
450 return zRef;
451 }
452
453 /*
454 ** If cgi_referer(0) returns a non-0 AND the referrer is from the same
455 ** fossil app path (i.e. the referrer's path starts with g.zTop), this
456 ** function returns the first path element of the referring page, up
457 ** to, but not including, the first slash. Thus if he refer[r]er is
458 ** https://foo.com/fossil.cgi/foo/bar, this returns "foo". The
459 ** returned memory is malloc'd and needs to be freed by the caller.
460 */
461 char * cgi_referer_fossil_page_name(){
462 UrlData url;
463 char * zPage = 0;
464 const char * zRef = cgi_referer(0);
465
466 if(zRef==0) return 0;
467 memset(&url, 0, sizeof(url));
468 url_parse_local(zRef, 0, &url);
469 if(url.path==strstr(url.path, g.zTop)){
470 /* g.zTop is, e.g., /cgi-bin/fossil.cgi,
471 url.path is, e.g., /cgi-bin/fossil.cgi/page/... */
472 char * zSlash = 0;
473 zPage = url.path + strlen(g.zTop);
474 if('/' == zPage[0]){
475 *zPage++ = 0;
476 if((zSlash = strstr(zPage,"/"))!=0){
477 *zSlash = 0;
478 }
479 zPage = mprintf("%s", zPage);
480 }else{ /*unexpected result*/
481 zPage = 0;
482 }
483 }
484 url_cleanup(&url);
485 return zPage;
486 }
487
488
489 /*
490 ** Return true if the current request appears to be safe from a
491 ** Cross-Site Request Forgery (CSRF) attack. Conditions that must
492 ** be met:
493
+2 -2
--- src/style.c
+++ src/style.c
@@ -1071,20 +1071,19 @@
10711071
}
10721072
style_init_th1_vars(0);
10731073
Th_Render(zScript?zScript:"");
10741074
}
10751075
1076
-
10771076
/*
10781077
** WEBPAGE: style.css
10791078
**
10801079
** Return the style sheet.
10811080
*/
10821081
void page_style_css(void){
10831082
Blob css = empty_blob;
10841083
int i;
1085
- const char *zPage = P("name");
1084
+ char *zPage = cgi_referer_fossil_page_name();
10861085
10871086
cgi_set_content_type("text/css");
10881087
/* Emit all default rules... */
10891088
for(i=1; cssDefaultList[i].elementClass; i++){
10901089
char *z = blob_str(&css);
@@ -1118,10 +1117,11 @@
11181117
"***********************************************************/\n",
11191118
zPage);
11201119
}
11211120
fossil_free(zFile);
11221121
}
1122
+ fossil_free(zPage);
11231123
blob_append(&css,
11241124
"\n/***********************************************************\n"
11251125
"** All CSS which follows is supplied by the repository \"skin\".\n"
11261126
"***********************************************************/\n",
11271127
-1);
11281128
--- src/style.c
+++ src/style.c
@@ -1071,20 +1071,19 @@
1071 }
1072 style_init_th1_vars(0);
1073 Th_Render(zScript?zScript:"");
1074 }
1075
1076
1077 /*
1078 ** WEBPAGE: style.css
1079 **
1080 ** Return the style sheet.
1081 */
1082 void page_style_css(void){
1083 Blob css = empty_blob;
1084 int i;
1085 const char *zPage = P("name");
1086
1087 cgi_set_content_type("text/css");
1088 /* Emit all default rules... */
1089 for(i=1; cssDefaultList[i].elementClass; i++){
1090 char *z = blob_str(&css);
@@ -1118,10 +1117,11 @@
1118 "***********************************************************/\n",
1119 zPage);
1120 }
1121 fossil_free(zFile);
1122 }
 
1123 blob_append(&css,
1124 "\n/***********************************************************\n"
1125 "** All CSS which follows is supplied by the repository \"skin\".\n"
1126 "***********************************************************/\n",
1127 -1);
1128
--- src/style.c
+++ src/style.c
@@ -1071,20 +1071,19 @@
1071 }
1072 style_init_th1_vars(0);
1073 Th_Render(zScript?zScript:"");
1074 }
1075
 
1076 /*
1077 ** WEBPAGE: style.css
1078 **
1079 ** Return the style sheet.
1080 */
1081 void page_style_css(void){
1082 Blob css = empty_blob;
1083 int i;
1084 char *zPage = cgi_referer_fossil_page_name();
1085
1086 cgi_set_content_type("text/css");
1087 /* Emit all default rules... */
1088 for(i=1; cssDefaultList[i].elementClass; i++){
1089 char *z = blob_str(&css);
@@ -1118,10 +1117,11 @@
1117 "***********************************************************/\n",
1118 zPage);
1119 }
1120 fossil_free(zFile);
1121 }
1122 fossil_free(zPage);
1123 blob_append(&css,
1124 "\n/***********************************************************\n"
1125 "** All CSS which follows is supplied by the repository \"skin\".\n"
1126 "***********************************************************/\n",
1127 -1);
1128
+20 -1
--- src/url.c
+++ src/url.c
@@ -49,11 +49,11 @@
4949
int isFile; /* True if a "file:" url */
5050
int isHttps; /* True if a "https:" url */
5151
int isSsh; /* True if an "ssh:" url */
5252
char *name; /* Hostname for http: or filename for file: */
5353
char *hostname; /* The HOST: parameter on http headers */
54
- char *protocol; /* "http" or "https" */
54
+ const char *protocol; /* "http" or "https" or "ssh" */
5555
int port; /* TCP port number for http: or https: */
5656
int dfltPort; /* The default port for the given protocol */
5757
char *path; /* Pathname for http: */
5858
char *user; /* User id for http: */
5959
char *passwd; /* Password for http: */
@@ -65,10 +65,29 @@
6565
char *proxyUrlPath;
6666
int proxyOrigPort; /* Tunneled port number for https through proxy */
6767
};
6868
#endif /* INTERFACE */
6969
70
+/*
71
+** Frees (almost) all (char*) members of pUrlData and zeroes out
72
+** pUrlData. Results are undefined if pUrlData passed an uninitialized
73
+** object.
74
+*/
75
+void url_cleanup(UrlData *pUrlData){
76
+ fossil_free(pUrlData->user);
77
+ fossil_free(pUrlData->passwd);
78
+ if(pUrlData->hostname != pUrlData->name){
79
+ fossil_free(pUrlData->name);
80
+ }
81
+ fossil_free(pUrlData->hostname);
82
+ fossil_free(pUrlData->path);
83
+ fossil_free(pUrlData->canonical);
84
+ /* ??? fossil_free(pUrlData->proxyAuth); */
85
+ /* ??? fossil_free(pUrlData->fossil); */
86
+ /* ??? fossil_free(pUrlData->proxyUrlPath); */
87
+ memset(pUrlData, 0, sizeof(*pUrlData));
88
+}
7089
7190
/*
7291
** Parse the given URL. Populate members of the provided UrlData structure
7392
** as follows:
7493
**
7594
--- src/url.c
+++ src/url.c
@@ -49,11 +49,11 @@
49 int isFile; /* True if a "file:" url */
50 int isHttps; /* True if a "https:" url */
51 int isSsh; /* True if an "ssh:" url */
52 char *name; /* Hostname for http: or filename for file: */
53 char *hostname; /* The HOST: parameter on http headers */
54 char *protocol; /* "http" or "https" */
55 int port; /* TCP port number for http: or https: */
56 int dfltPort; /* The default port for the given protocol */
57 char *path; /* Pathname for http: */
58 char *user; /* User id for http: */
59 char *passwd; /* Password for http: */
@@ -65,10 +65,29 @@
65 char *proxyUrlPath;
66 int proxyOrigPort; /* Tunneled port number for https through proxy */
67 };
68 #endif /* INTERFACE */
69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
71 /*
72 ** Parse the given URL. Populate members of the provided UrlData structure
73 ** as follows:
74 **
75
--- src/url.c
+++ src/url.c
@@ -49,11 +49,11 @@
49 int isFile; /* True if a "file:" url */
50 int isHttps; /* True if a "https:" url */
51 int isSsh; /* True if an "ssh:" url */
52 char *name; /* Hostname for http: or filename for file: */
53 char *hostname; /* The HOST: parameter on http headers */
54 const char *protocol; /* "http" or "https" or "ssh" */
55 int port; /* TCP port number for http: or https: */
56 int dfltPort; /* The default port for the given protocol */
57 char *path; /* Pathname for http: */
58 char *user; /* User id for http: */
59 char *passwd; /* Password for http: */
@@ -65,10 +65,29 @@
65 char *proxyUrlPath;
66 int proxyOrigPort; /* Tunneled port number for https through proxy */
67 };
68 #endif /* INTERFACE */
69
70 /*
71 ** Frees (almost) all (char*) members of pUrlData and zeroes out
72 ** pUrlData. Results are undefined if pUrlData passed an uninitialized
73 ** object.
74 */
75 void url_cleanup(UrlData *pUrlData){
76 fossil_free(pUrlData->user);
77 fossil_free(pUrlData->passwd);
78 if(pUrlData->hostname != pUrlData->name){
79 fossil_free(pUrlData->name);
80 }
81 fossil_free(pUrlData->hostname);
82 fossil_free(pUrlData->path);
83 fossil_free(pUrlData->canonical);
84 /* ??? fossil_free(pUrlData->proxyAuth); */
85 /* ??? fossil_free(pUrlData->fossil); */
86 /* ??? fossil_free(pUrlData->proxyUrlPath); */
87 memset(pUrlData, 0, sizeof(*pUrlData));
88 }
89
90 /*
91 ** Parse the given URL. Populate members of the provided UrlData structure
92 ** as follows:
93 **
94

Keyboard Shortcuts

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