Fossil

Check-in [b75ee4f28e]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment: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.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | rptview-submenu-paralink
Files: files | file ages | folders
SHA3-256: b75ee4f28efd8ad8ab95d79af6d7e8fd46a46eca5932314eaf2c3227f174c213
User & Date: george 2021-04-14 18:48:07.192
Context
2021-05-25
16:14
Split recognizable names of query parameters into three groups: 1) "...smplX" for the common use within user content 2) "...smplXa" that is provisioned to be used in aliases; 3) "...smplXs" that is provisioned to be used in custom skins. In all three groups X is a digit from {1,2,3,4,5}. ... (check-in: 588b376560 user: george tags: rptview-submenu-paralink)
2021-04-14
18:48
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. ... (check-in: b75ee4f28e user: george tags: rptview-submenu-paralink)
2021-04-09
04:21
Remove [forum:/forumpost/2f375863dbc6|useless] 'nMaxDigit' parameter from the signature of the <tt>style_submenu_parametric()</tt>. Also edit a corresponding comment. ... (check-in: d1651e7e17 user: george tags: rptview-submenu-paralink)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/report.c.
1035
1036
1037
1038
1039
1040
1041

1042
1043
1044
1045
1046
1047
1048
  count = 0;
  if( !tabs ){
    struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    const char *zQS = PD("QUERY_STRING","");

    db_multi_exec("PRAGMA empty_result_callbacks=ON");
    style_set_current_feature("report");

    if( zQS[0] ){
      style_submenu_element("Raw","%R/%s?tablist=1&%s",g.zPath,zQS);
      style_submenu_element("Reports","%R/reportlist?%s",zQS);
    } else {
      style_submenu_element("Raw","%R/%s?tablist=1",g.zPath);
      style_submenu_element("Reports","%R/reportlist");
    }







>







1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
  count = 0;
  if( !tabs ){
    struct GenerateHTML sState = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    const char *zQS = PD("QUERY_STRING","");

    db_multi_exec("PRAGMA empty_result_callbacks=ON");
    style_set_current_feature("report");
    /* style_finish_page() should provide escaping via %h formatting */
    if( zQS[0] ){
      style_submenu_element("Raw","%R/%s?tablist=1&%s",g.zPath,zQS);
      style_submenu_element("Reports","%R/reportlist?%s",zQS);
    } else {
      style_submenu_element("Raw","%R/%s?tablist=1",g.zPath);
      style_submenu_element("Reports","%R/reportlist");
    }
Changes to src/style.c.
337
338
339
340
341
342
343
344
345
346
347



348







349
350
351
352
353
354
355
** 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
** 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.







*/
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 */







|

|
|
>
>
>
|
>
>
>
>
>
>
>







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 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.
**  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
  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] == '/' ){
      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;
    }







|







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] == '/' || 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
      ** 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++ ){
        if( z[0]=='_' ) z[0] = ' ';




      }
    }
    if( zQS[0] ){
      aSubmenu[nSubmenu].zLink  = mprintf("%R/%s?%s",zV,zQS);
    }else{
      aSubmenu[nSubmenu].zLink  = mprintf("%R/%s",zV);
    }







|

>
>
>
>







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++ ){
        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
      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];




        if( p->zLink==0 ){
          @ <span class="label">%h(p->zLabel)</span>
        }else{
          @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a>
        }
      }
    }







>
>
>
>







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>
        }
      }
    }