331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
|
nSubmenuCtrl++;
}
}
/* Add hyperlinks depending on the existence and values of special
** parameters in the request's query string. The names of a query's
** 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 label equals to the value of the
** parameter modulus some prettification for better UX:
** 1) If a parameter's value starts with a lowercase letter and
** contains '/' then it goes unchanged into the user-visible label.
|
|
>
>
|
|
|
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
|
nSubmenuCtrl++;
}
}
/* Add hyperlinks depending on the existence and values of special
** parameters in the request's query string. The names of a query's
** parameters that are investigated are obtainted by concatenation of
** the caller-provided zPrefix with suffix "smplXY", where optional
** ending XY consists of a digit X from the set {1,2,3,4,5} and an
** optional letter Y which (if present) must be either 'a' or 's'.
** 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 label equals to the value of the
** parameter modulus some prettification for better UX:
** 1) If a parameter's value starts with a lowercase letter and
** contains '/' then it goes unchanged into the user-visible label.
|
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
|
** 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 */
char zN[32]; /* buffer for parameter names to probe */
short i,l;
/* zPrefix must be tidy and short; also filter out ENV/CGI variables */
assert( zPrefix != 0 && fossil_islower(zPrefix[0]) );
l = strnlen( zPrefix, sizeof(zN) );
assert( l+sfxlen+2 <= sizeof(zN) );
assert( fossil_no_strange_characters(zPrefix) );
/* concatenate zPrefix and suffix */
strcpy( zN, zPrefix );
strcpy( zN + l, suffix );
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] == '/' || 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;
}
if( z[0] != 0 && z[0] != '/' )
continue;
assert( nSubmenu < count(aSubmenu) );
if(fossil_islower(zV[0]) && z[0]=='/'){
aSubmenu[nSubmenu].zLabel = mprintf( "%s",zV); /* memory leak? */
}else{
/* prepend a label with an unobtrusive symbol that "sorts-last";
** 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++ ){
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);
}
nSubmenu++;
}
}
/*
** Disable or enable the submenu
*/
void style_submenu_enable(int onOff){
|
>
|
|
|
|
<
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
|
** 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 */
static const char sfxext[3] = {'a','s',0}; /* extra suffix ending */
const char *zQS; /* QUERY_STRING */
char zN[32]; /* buffer for parameter names to probe */
short i,j,l;
/* zPrefix must be tidy and short; also filter out ENV/CGI variables */
assert( zPrefix != 0 && fossil_islower(zPrefix[0]) );
l = strnlen( zPrefix, sizeof(zN) );
assert( l+sfxlen+3 <= sizeof(zN) );
assert( fossil_no_strange_characters(zPrefix) );
/* concatenate zPrefix and suffix */
strcpy( zN, zPrefix );
strcpy( zN + l, suffix );
l += sfxlen;
zN[l+2] = 0; /* nul-terminator after ...smplXY suffix */
zQS = PD("QUERY_STRING","");
for( i = 0; i <= 5; i++ ){
zN[l] = ( i == 0 ? 0 : '0' + i ); /* ...smpl instead of ...smpl0 */
for( j = (i ? 0 : sizeof(sfxext)-1); j < sizeof(sfxext); j++ ){
const char *zV, *z;
zN[l+1] = sfxext[j];
zV = PD(zN,"");
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;
}
if( z[0] != 0 && z[0] != '/' )
continue;
assert( nSubmenu < count(aSubmenu) );
if(fossil_islower(zV[0]) && z[0]=='/'){
aSubmenu[nSubmenu].zLabel = mprintf( "%s",zV); /* memory leak? */
}else{
/* prepend a label with an unobtrusive symbol that "sorts-last";
** 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++ ){
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);
}
nSubmenu++;
}
}
}
/*
** Disable or enable the submenu
*/
void style_submenu_enable(int onOff){
|