Fossil SCM

If a parameter's value starts with an uppercase letter then truncate resulting label to just the first path segment. This check-in also adds a few code-comments related to %s formatting.

george 2021-04-14 18:48 rptview-submenu-paralink
Commit b75ee4f28efd8ad8ab95d79af6d7e8fd46a46eca5932314eaf2c3227f174c213
2 files changed +1 +24 -6
--- src/report.c
+++ src/report.c
@@ -1037,10 +1037,11 @@
10371037
struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
10381038
const char *zQS = PD("QUERY_STRING","");
10391039
10401040
db_multi_exec("PRAGMA empty_result_callbacks=ON");
10411041
style_set_current_feature("report");
1042
+ /* style_finish_page() should provide escaping via %h formatting */
10421043
if( zQS[0] ){
10431044
style_submenu_element("Raw","%R/%s?tablist=1&%s",g.zPath,zQS);
10441045
style_submenu_element("Reports","%R/reportlist?%s",zQS);
10451046
} else {
10461047
style_submenu_element("Raw","%R/%s?tablist=1",g.zPath);
10471048
--- src/report.c
+++ src/report.c
@@ -1037,10 +1037,11 @@
1037 struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1038 const char *zQS = PD("QUERY_STRING","");
1039
1040 db_multi_exec("PRAGMA empty_result_callbacks=ON");
1041 style_set_current_feature("report");
 
1042 if( zQS[0] ){
1043 style_submenu_element("Raw","%R/%s?tablist=1&%s",g.zPath,zQS);
1044 style_submenu_element("Reports","%R/reportlist?%s",zQS);
1045 } else {
1046 style_submenu_element("Raw","%R/%s?tablist=1",g.zPath);
1047
--- src/report.c
+++ src/report.c
@@ -1037,10 +1037,11 @@
1037 struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1038 const char *zQS = PD("QUERY_STRING","");
1039
1040 db_multi_exec("PRAGMA empty_result_callbacks=ON");
1041 style_set_current_feature("report");
1042 /* style_finish_page() should provide escaping via %h formatting */
1043 if( zQS[0] ){
1044 style_submenu_element("Raw","%R/%s?tablist=1&%s",g.zPath,zQS);
1045 style_submenu_element("Reports","%R/reportlist?%s",zQS);
1046 } else {
1047 style_submenu_element("Raw","%R/%s?tablist=1",g.zPath);
1048
+24 -6
--- src/style.c
+++ src/style.c
@@ -339,15 +339,25 @@
339339
** nothing or a positive digit. zPrefix must start with a lowercase
340340
** letter, be short and have no strange characters. Parameter's value
341341
** is well-formed if its first filepath segment (separated by '/')
342342
** has no strange characters. Malformed values are silently ignored.
343343
**
344
-** The text for the resulting submenu item equals to the value of the
344
+** The text for the resulting submenu label equals to the value of the
345345
** parameter modulus some prettification for better UX:
346
-** "✧" symbol is prepended unless parameter's value starts with a
347
-** lowercase letter or contains '/', also underscores in the first
348
-** path segment are replaced with spaces.
346
+** 1) If a parameter's value starts with a lowercase letter and
347
+** contains '/' then it goes unchanged into the user-visible label.
348
+** 2a) If the first letter is uppercase then the label is
349
+** truncated at the first '/' (if any),
350
+** 2b) otherwise the first letter is capitalized.
351
+** 3) Underscores in the first path segment are replaced with spaces.
352
+** 4) If the resulting label starts with an uppercase letter
353
+** then it is prepended with "✧" symbol for explicit distinction
354
+** from the built-in labels
355
+**
356
+** Important security-related note:
357
+** zLabel and zLink are formatted using %s because it is expected that
358
+** style_finish_page() provides propper escaping via %h format.
349359
*/
350360
void style_submenu_parametric(
351361
const char *zPrefix /* common prefix of the query parameters names */
352362
){
353363
static const char *suffix = "smpl"; /* common suffix for param names */
@@ -369,11 +379,11 @@
369379
zQS = PD("QUERY_STRING","");
370380
for( i = 0; i <= 9; i++ ){
371381
const char *zV, *z;
372382
zN[l] = ( i == 0 ? 0 : '0' + i ); /* ...smpl instead of ...smpl0 */
373383
zV = PD(zN,"");
374
- if( zV[0] == 0 || zV[0] == '/' ){
384
+ if( zV[0] == 0 || zV[0] == '/' || zV[0] == '_' || zV[0] == '-' ){
375385
continue;
376386
}
377387
/* require the first path segment to be unfancy ASCII string */
378388
for( z = zV; z[0] && z[0] != '/' ;){
379389
if( fossil_isalnum(z[0]) || z[0]=='_' || z[0]=='-' ) z++;
@@ -391,12 +401,16 @@
391401
char *z = mprintf("%s%s",mark,zV);
392402
aSubmenu[nSubmenu].zLabel = z;
393403
/* also prettify the first segment */
394404
z += strlen(mark);
395405
z[0] = fossil_toupper(z[0]);
396
- for(; z[0]!=0 && z[0]!='/'; z++ ){
406
+ for(; z[0]!=0; z++ ){
397407
if( z[0]=='_' ) z[0] = ' ';
408
+ else if( z[0] == '/' ){ /* show just the first segment */
409
+ z[0] = 0;
410
+ break;
411
+ }
398412
}
399413
}
400414
if( zQS[0] ){
401415
aSubmenu[nSubmenu].zLink = mprintf("%R/%s?%s",zV,zQS);
402416
}else{
@@ -979,10 +993,14 @@
979993
@ <div class="submenu">
980994
if( nSubmenu>0 ){
981995
qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare);
982996
for(i=0; i<nSubmenu; i++){
983997
struct Submenu *p = &aSubmenu[i];
998
+ /* switching away from the %h formatting below might be dangerous
999
+ ** because some places use %s to compose zLabel and zLink;
1000
+ ** e.g. /rptview page and the style_submenu_parametic() function
1001
+ */
9841002
if( p->zLink==0 ){
9851003
@ <span class="label">%h(p->zLabel)</span>
9861004
}else{
9871005
@ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a>
9881006
}
9891007
--- src/style.c
+++ src/style.c
@@ -339,15 +339,25 @@
339 ** nothing or a positive digit. zPrefix must start with a lowercase
340 ** letter, be short and have no strange characters. Parameter's value
341 ** is well-formed if its first filepath segment (separated by '/')
342 ** has no strange characters. Malformed values are silently ignored.
343 **
344 ** The text for the resulting submenu item equals to the value of the
345 ** parameter modulus some prettification for better UX:
346 ** "✧" symbol is prepended unless parameter's value starts with a
347 ** lowercase letter or contains '/', also underscores in the first
348 ** path segment are replaced with spaces.
 
 
 
 
 
 
 
 
 
 
349 */
350 void style_submenu_parametric(
351 const char *zPrefix /* common prefix of the query parameters names */
352 ){
353 static const char *suffix = "smpl"; /* common suffix for param names */
@@ -369,11 +379,11 @@
369 zQS = PD("QUERY_STRING","");
370 for( i = 0; i <= 9; i++ ){
371 const char *zV, *z;
372 zN[l] = ( i == 0 ? 0 : '0' + i ); /* ...smpl instead of ...smpl0 */
373 zV = PD(zN,"");
374 if( zV[0] == 0 || zV[0] == '/' ){
375 continue;
376 }
377 /* require the first path segment to be unfancy ASCII string */
378 for( z = zV; z[0] && z[0] != '/' ;){
379 if( fossil_isalnum(z[0]) || z[0]=='_' || z[0]=='-' ) z++;
@@ -391,12 +401,16 @@
391 char *z = mprintf("%s%s",mark,zV);
392 aSubmenu[nSubmenu].zLabel = z;
393 /* also prettify the first segment */
394 z += strlen(mark);
395 z[0] = fossil_toupper(z[0]);
396 for(; z[0]!=0 && z[0]!='/'; z++ ){
397 if( z[0]=='_' ) z[0] = ' ';
 
 
 
 
398 }
399 }
400 if( zQS[0] ){
401 aSubmenu[nSubmenu].zLink = mprintf("%R/%s?%s",zV,zQS);
402 }else{
@@ -979,10 +993,14 @@
979 @ <div class="submenu">
980 if( nSubmenu>0 ){
981 qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare);
982 for(i=0; i<nSubmenu; i++){
983 struct Submenu *p = &aSubmenu[i];
 
 
 
 
984 if( p->zLink==0 ){
985 @ <span class="label">%h(p->zLabel)</span>
986 }else{
987 @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a>
988 }
989
--- src/style.c
+++ src/style.c
@@ -339,15 +339,25 @@
339 ** nothing or a positive digit. zPrefix must start with a lowercase
340 ** letter, be short and have no strange characters. Parameter's value
341 ** is well-formed if its first filepath segment (separated by '/')
342 ** has no strange characters. Malformed values are silently ignored.
343 **
344 ** The text for the resulting submenu label equals to the value of the
345 ** parameter modulus some prettification for better UX:
346 ** 1) If a parameter's value starts with a lowercase letter and
347 ** contains '/' then it goes unchanged into the user-visible label.
348 ** 2a) If the first letter is uppercase then the label is
349 ** truncated at the first '/' (if any),
350 ** 2b) otherwise the first letter is capitalized.
351 ** 3) Underscores in the first path segment are replaced with spaces.
352 ** 4) If the resulting label starts with an uppercase letter
353 ** then it is prepended with "✧" symbol for explicit distinction
354 ** from the built-in labels
355 **
356 ** Important security-related note:
357 ** zLabel and zLink are formatted using %s because it is expected that
358 ** style_finish_page() provides propper escaping via %h format.
359 */
360 void style_submenu_parametric(
361 const char *zPrefix /* common prefix of the query parameters names */
362 ){
363 static const char *suffix = "smpl"; /* common suffix for param names */
@@ -369,11 +379,11 @@
379 zQS = PD("QUERY_STRING","");
380 for( i = 0; i <= 9; i++ ){
381 const char *zV, *z;
382 zN[l] = ( i == 0 ? 0 : '0' + i ); /* ...smpl instead of ...smpl0 */
383 zV = PD(zN,"");
384 if( zV[0] == 0 || zV[0] == '/' || zV[0] == '_' || zV[0] == '-' ){
385 continue;
386 }
387 /* require the first path segment to be unfancy ASCII string */
388 for( z = zV; z[0] && z[0] != '/' ;){
389 if( fossil_isalnum(z[0]) || z[0]=='_' || z[0]=='-' ) z++;
@@ -391,12 +401,16 @@
401 char *z = mprintf("%s%s",mark,zV);
402 aSubmenu[nSubmenu].zLabel = z;
403 /* also prettify the first segment */
404 z += strlen(mark);
405 z[0] = fossil_toupper(z[0]);
406 for(; z[0]!=0; z++ ){
407 if( z[0]=='_' ) z[0] = ' ';
408 else if( z[0] == '/' ){ /* show just the first segment */
409 z[0] = 0;
410 break;
411 }
412 }
413 }
414 if( zQS[0] ){
415 aSubmenu[nSubmenu].zLink = mprintf("%R/%s?%s",zV,zQS);
416 }else{
@@ -979,10 +993,14 @@
993 @ <div class="submenu">
994 if( nSubmenu>0 ){
995 qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare);
996 for(i=0; i<nSubmenu; i++){
997 struct Submenu *p = &aSubmenu[i];
998 /* switching away from the %h formatting below might be dangerous
999 ** because some places use %s to compose zLabel and zLink;
1000 ** e.g. /rptview page and the style_submenu_parametic() function
1001 */
1002 if( p->zLink==0 ){
1003 @ <span class="label">%h(p->zLabel)</span>
1004 }else{
1005 @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a>
1006 }
1007

Keyboard Shortcuts

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