| ︙ | | |
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
|
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
|
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
|
** parameters that are investigated are obtainted by concatenation of
** the caller-provided zPrefix with suffix "smplX", where X is either
** nothing or a positive digit. zPrefix must start with a lowercase
** letter, be short and have no strange characters. Parameter's value
** is well-formed if its first filepath segment (separated by '/')
** has no strange characters. Malformed values are silently ignored.
**
** The text for the resulting submenu item equals to the value of the
** The text for the resulting submenu label equals to the value of the
** parameter modulus some prettification for better UX:
** "✧" symbol is prepended unless parameter's value starts with a
** lowercase letter or contains '/', also underscores in the first
** path segment are replaced with spaces.
** 1) If a parameter's value starts with a lowercase letter and
** contains '/' then it goes unchanged into the user-visible label.
** 2a) If the first letter is uppercase then the label is
** truncated at the first '/' (if any),
** 2b) otherwise the first letter is capitalized.
** 3) Underscores in the first path segment are replaced with spaces.
** 4) If the resulting label starts with an uppercase letter
** then it is prepended with "✧" symbol for explicit distinction
** from the built-in labels
**
** Important security-related note:
** zLabel and zLink are formatted using %s because it is expected that
** style_finish_page() provides propper escaping via %h format.
*/
void style_submenu_parametric(
const char *zPrefix /* common prefix of the query parameters names */
){
static const char *suffix = "smpl"; /* common suffix for param names */
static const short sfxlen = 4; /* length of the above suffix */
const char *zQS; /* QUERY_STRING */
|
| ︙ | | |
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
|
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
|
-
+
|
l += sfxlen;
zN[l+1] = 0; /* nul-terminator after digit's placeholder (if any) */
zQS = PD("QUERY_STRING","");
for( i = 0; i <= 9; i++ ){
const char *zV, *z;
zN[l] = ( i == 0 ? 0 : '0' + i ); /* ...smpl instead of ...smpl0 */
zV = PD(zN,"");
if( zV[0] == 0 || zV[0] == '/' ){
if( zV[0] == 0 || zV[0] == '/' || zV[0] == '_' || zV[0] == '-' ){
continue;
}
/* require the first path segment to be unfancy ASCII string */
for( z = zV; z[0] && z[0] != '/' ;){
if( fossil_isalnum(z[0]) || z[0]=='_' || z[0]=='-' ) z++;
else break;
}
|
| ︙ | | |
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
|
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
|
-
+
+
+
+
+
|
** this clearly distincts it from the built-in elements */
static const char *mark = "✧";
char *z = mprintf("%s%s",mark,zV);
aSubmenu[nSubmenu].zLabel = z;
/* also prettify the first segment */
z += strlen(mark);
z[0] = fossil_toupper(z[0]);
for(; z[0]!=0 && z[0]!='/'; z++ ){
for(; z[0]!=0; z++ ){
if( z[0]=='_' ) z[0] = ' ';
else if( z[0] == '/' ){ /* show just the first segment */
z[0] = 0;
break;
}
}
}
if( zQS[0] ){
aSubmenu[nSubmenu].zLink = mprintf("%R/%s?%s",zV,zQS);
}else{
aSubmenu[nSubmenu].zLink = mprintf("%R/%s",zV);
}
|
| ︙ | | |
977
978
979
980
981
982
983
984
985
986
987
988
989
990
|
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
|
+
+
+
+
|
cgi_tag_query_parameter("udc");
}
@ <div class="submenu">
if( nSubmenu>0 ){
qsort(aSubmenu, nSubmenu, sizeof(aSubmenu[0]), submenuCompare);
for(i=0; i<nSubmenu; i++){
struct Submenu *p = &aSubmenu[i];
/* switching away from the %h formatting below might be dangerous
** because some places use %s to compose zLabel and zLink;
** e.g. /rptview page and the style_submenu_parametic() function
*/
if( p->zLink==0 ){
@ <span class="label">%h(p->zLabel)</span>
}else{
@ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a>
}
}
}
|
| ︙ | | |