Fossil

Check-in [588b376560]
Login

Check-in [588b376560]

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

Overview
Comment: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}.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | rptview-submenu-paralink
Files: files | file ages | folders
SHA3-256: 588b37656058c6b5f26ae0f8cebdd25d59b192974fae7959282cb5e73d615c5f
User & Date: george 2021-05-25 16:14:35.871
Context
2021-06-08
01:04
Merge from trunk ... (check-in: 9712d59d9e user: george tags: rptview-submenu-paralink)
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)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/report.c.
969
970
971
972
973
974
975
976


977

978

979
980


981
982
983
984
985
986
987

/*
** WEBPAGE: rptview
**
** Generate a report.  The "rn" query parameter is the report number
** corresponding to REPORTFMT.RN.  If the "tablist" query parameter exists,
** then the output consists of lines of tab-separated fields instead of
** an HTML table.  If the "rvsmpl" query parameter is set then report's


** submenu will contain an extra hyperlink that have a value-driven

** label and target.

**
** "rvsmpl" stands for Report View SubMenu's Parametric Link.


*/
void rptview_page(void){
  int count = 0;
  int rn, rc;
  char *zSql;
  char *zTitle;
  char *zOwner;







|
>
>
|
>
|
>

<
>
>







969
970
971
972
973
974
975
976
977
978
979
980
981
982
983

984
985
986
987
988
989
990
991
992

/*
** WEBPAGE: rptview
**
** Generate a report.  The "rn" query parameter is the report number
** corresponding to REPORTFMT.RN.  If the "tablist" query parameter exists,
** then the output consists of lines of tab-separated fields instead of
** an HTML table.
**
** Submenu of the /rptview page can be extended with additional
** hyperlinks by providing query parameter(s) of the form rvsmplXY=Z.
** Optional ending XY consists of a digit X from the set {1,2,3,4,5}
** and an optional letter Y that (if present) must be either 'a' or 's'.
** Mandatory Z is a repo-local hyperlink's target (wihout leading '/').
**

** For details see function style_submenu_parametric() in src/style.c
** on branch "rptview-submenu-paralink".
*/
void rptview_page(void){
  int count = 0;
  int rn, rc;
  char *zSql;
  char *zTitle;
  char *zOwner;
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
    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");
    }
    style_submenu_parametric("rptview_");
    style_submenu_parametric("rv");

    if( g.perm.Admin
       || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
      style_submenu_element("Edit", "rptedit?rn=%d", rn);
    }
    if( g.perm.TktFmt ){







<







1048
1049
1050
1051
1052
1053
1054

1055
1056
1057
1058
1059
1060
1061
    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");
    }

    style_submenu_parametric("rv");

    if( g.perm.Admin
       || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
      style_submenu_element("Edit", "rptedit?rn=%d", rn);
    }
    if( g.perm.TktFmt ){
Changes to src/style.c.
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){