Fossil

Changes On Branch rptview-submenu-paralink
Login

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

Changes In Branch rptview-submenu-paralink Excluding Merge-Ins

This is equivalent to a diff from a004b1729c to 59010c7c09

2021-08-17
15:41
Improvements to the /urllist page → the sync URLs and Git mirrors are combined into a single section. Add the url_unparse() interface for freeing memory from a url_parse_local(). ... (check-in: 9bdbcd39cb user: drh tags: trunk)
2021-08-16
00:11
Relax <tt>isSnippetMark()</tt> so that almost arbitrary search terms are highlighted. This change is preliminary and [forum:/forumpost/042e179e0c25b8|needs further analysis]. ... (Leaf check-in: 6b37b55f75 user: george tags: search-terms-highlighting)
2021-08-15
23:49
Merge from trunk ... (Leaf check-in: 59010c7c09 user: george tags: rptview-submenu-paralink)
23:27
Merge from trunk ... (Leaf check-in: 282c6f956f user: george tags: wcontent-subsets)
23:13
Merge from trunk ... (Leaf check-in: 5b67899db0 user: george tags: th1-doc-vars)
18:38
Remove a harmless unused variable. ... (check-in: a004b1729c user: drh tags: trunk)
00:43
Improve the /urllist page so that it shows all servers with which the repository has synced. ... (check-in: 89e5c03a32 user: drh tags: trunk)
2021-06-15
22:31
Do not allow links with "../" substring or <tt>'<'</tt> character. The former enforces that the link maps into a repo-local page; the later enforces defense against injection of malicious HTML elements. ... (check-in: 6261c94b1e user: george tags: rptview-submenu-paralink)

Changes to src/report.c.

999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009








1010
1011
1012
1013
1014
1015
1016
  fossil_free((void *)azVals);
  return rc;
}

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








*/
void rptview_page(void){
  rptview_page_content(0, 1, 1);
}

/*
** Render a report.







|
|


>
>
>
>
>
>
>
>







999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
  fossil_free((void *)azVals);
  return rc;
}

/*
** 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 the wiki page "branch/rptview-submenu-paralink".
*/
void rptview_page(void){
  rptview_page_content(0, 1, 1);
}

/*
** Render a report.
1090
1091
1092
1093
1094
1095
1096


1097
1098
1099
1100
1101
1102
1103
      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");
      }


      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 ){
        style_submenu_element("SQL", "rptsql?rn=%d",rn);
      }







>
>







1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
      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 ){
        style_submenu_element("SQL", "rptsql?rn=%d",rn);
      }

Changes to src/style.c.

30
31
32
33
34
35
36

37
38
39
40
41
42
43
**
**      style_submenu_element()
**      style_submenu_entry()
**      style_submenu_checkbox()
**      style_submenu_binary()
**      style_submenu_multichoice()
**      style_submenu_sql()

**
** prior to calling style_finish_page().  The style_finish_page() routine
** will generate the appropriate HTML text just below the main
** menu.
*/
static struct Submenu {
  const char *zLabel;        /* Button label */







>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
**
**      style_submenu_element()
**      style_submenu_entry()
**      style_submenu_checkbox()
**      style_submenu_binary()
**      style_submenu_multichoice()
**      style_submenu_sql()
**      style_submenu_parametric()
**
** prior to calling style_finish_page().  The style_finish_page() routine
** will generate the appropriate HTML text just below the main
** menu.
*/
static struct Submenu {
  const char *zLabel;        /* Button label */
364
365
366
367
368
369
370





































































































371
372
373
374
375
376
377
    aSubmenuCtrl[nSubmenuCtrl].iSize = n/2;
    aSubmenuCtrl[nSubmenuCtrl].azChoice = (const char *const *)az;
    aSubmenuCtrl[nSubmenuCtrl].eVisible = STYLE_NORMAL;
    aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
    nSubmenuCtrl++;
  }
}






































































































/*
** Disable or enable the submenu
*/
void style_submenu_enable(int onOff){
  submenuEnable = onOff;
}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
    aSubmenuCtrl[nSubmenuCtrl].iSize = n/2;
    aSubmenuCtrl[nSubmenuCtrl].azChoice = (const char *const *)az;
    aSubmenuCtrl[nSubmenuCtrl].eVisible = STYLE_NORMAL;
    aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
    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.
**  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    */
  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] == '/' ){
        /* values may not contain "../" or "<"  */
        if( strstr(z,"../")!=NULL || strstr(z,"<")!=NULL ){
          continue;
        }
      }
      else if( z[0] != 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){
  submenuEnable = onOff;
}
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
    @ <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
        */
        if( p->zLink==0 ){
          @ <span class="label">%h(p->zLabel)</span>
        }else{
          @ <a class="label" href="%h(p->zLink)">%h(p->zLabel)</a>
        }
      }







|







1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
    @ <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>
        }
      }

Changes to src/wiki.c.

591
592
593
594
595
596
597

598
599
600
601
602
603
604
    ){
      style_submenu_element("Edit", "%R/wikiedit?name=%T", zPageName);
    }else if( rid && g.perm.ApndWiki ){
      style_submenu_element("Edit", "%R/wikiappend?name=%T", zPageName);
    }
    if( g.perm.Hyperlink ){
      style_submenu_element("History", "%R/whistory?name=%T", zPageName);

    }
  }
  if( !isPopup ){
    style_set_current_page("%T?name=%T", g.zPath, zPageName);
    wiki_page_header(WIKITYPE_UNKNOWN, zPageName, "");
    if( !noSubmenu ){
      wiki_standard_submenu(submenuFlags);







>







591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
    ){
      style_submenu_element("Edit", "%R/wikiedit?name=%T", zPageName);
    }else if( rid && g.perm.ApndWiki ){
      style_submenu_element("Edit", "%R/wikiappend?name=%T", zPageName);
    }
    if( g.perm.Hyperlink ){
      style_submenu_element("History", "%R/whistory?name=%T", zPageName);
      style_submenu_parametric("wiki");
    }
  }
  if( !isPopup ){
    style_set_current_page("%T?name=%T", g.zPath, zPageName);
    wiki_page_header(WIKITYPE_UNKNOWN, zPageName, "");
    if( !noSubmenu ){
      wiki_standard_submenu(submenuFlags);

Changes to www/changes.wiki.

21
22
23
24
25
26
27



28
29
30
31
32
33
34
  *  Print total payload bytes on a [/help?cmd=sync|fossil sync] when using
     the --verbose option.
  *  Add the <tt>close</tt>, <tt>reopen</tt>, <tt>hide</tt>, and
     </tt>unhide</tt> subcommands to [/help?cmd=branch|the branch command].
  *  The [/mdrules|Markdown formatter] now interprets the content of
     block HTML markup (such as &lt;table&gt;) in most cases.  Only content
     of &lt;pre&gt; and &lt;script&gt; is passed through verbatim.




<a name='v2_16'></a>
<h2>Changes for Version 2.16 (2021-07-02)</h2>
  *  <b>Security:</b> Fix the client-side TLS so that it verifies that the
     server hostname matches its certificate.
  *  The default "ssh" command on Windows is changed to "ssh" instead of the
     legacy "plink", as ssh is now generally available on Windows systems.







>
>
>







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  *  Print total payload bytes on a [/help?cmd=sync|fossil sync] when using
     the --verbose option.
  *  Add the <tt>close</tt>, <tt>reopen</tt>, <tt>hide</tt>, and
     </tt>unhide</tt> subcommands to [/help?cmd=branch|the branch command].
  *  The [/mdrules|Markdown formatter] now interprets the content of
     block HTML markup (such as &lt;table&gt;) in most cases.  Only content
     of &lt;pre&gt; and &lt;script&gt; is passed through verbatim.
  *  Submenu of the [/help?cmd=/rptview|/rptview] and
     [/help?cmd=/wiki|/wiki] pages may be
     [branch/rptview-submenu-paralink|extended with auxiliary hyperlinks].

<a name='v2_16'></a>
<h2>Changes for Version 2.16 (2021-07-02)</h2>
  *  <b>Security:</b> Fix the client-side TLS so that it verifies that the
     server hostname matches its certificate.
  *  The default "ssh" command on Windows is changed to "ssh" instead of the
     legacy "plink", as ssh is now generally available on Windows systems.