Fossil

Check-in [7dd07b2e01]
Login

Check-in [7dd07b2e01]

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

Overview
Comment:Integrate ARIA suggestions from Peter Laursen.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 7dd07b2e0120156ec84e8e5f6760aaac6f0da23ffb4dea4eb1bc960a2f14ca1f
User & Date: drh 2020-05-16 01:08:18.542
Context
2020-05-17
12:55
Improvements to the skin_id() routine. ... (check-in: 56ad55415f user: drh tags: trunk)
2020-05-16
01:08
Integrate ARIA suggestions from Peter Laursen. ... (check-in: 7dd07b2e01 user: drh tags: trunk)
2020-05-15
13:49
Typo fix on the homepage. ... (check-in: 5f66f28806 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to skins/default/header.txt.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  upvar home home
  if {[string range $url 0 [string length $current]] eq "/$current"} {
    html "<a href='$home$url' class='active $cls'>$name</a>\n"
  } else {
    html "<a href='$home$url' class='$cls'>$name</a>\n"
  }
}
html "<a id='hbbtn' href='$home/sitemap'>&#9776;</a>"
menulink $index_page Home {}
if {[anycap jor]} {
  menulink /timeline Timeline {}
}
if {[hascap oh]} {
  if {![info exists current_checkin]} {set current_checkin tip}
  menulink /dir?ci=$current_checkin Files desktoponly







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  upvar home home
  if {[string range $url 0 [string length $current]] eq "/$current"} {
    html "<a href='$home$url' class='active $cls'>$name</a>\n"
  } else {
    html "<a href='$home$url' class='$cls'>$name</a>\n"
  }
}
html "<a id='hbbtn' href='$home/sitemap' aria-label='Site Map'>&#9776;</a>"
menulink $index_page Home {}
if {[anycap jor]} {
  menulink /timeline Timeline {}
}
if {[hascap oh]} {
  if {![info exists current_checkin]} {set current_checkin tip}
  menulink /dir?ci=$current_checkin Files desktoponly
Changes to src/capabilities.c.
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
  unsigned nUser;         /* Number of users with this capability */
  char *zAbbrev;          /* Abbreviated mnemonic name */
  char *zOneLiner;        /* One-line summary */
} aCap[] = {
  { 'a', CAPCLASS_SUPER, 0,
    "Admin", "Create and delete users" },
  { 'b', CAPCLASS_WIKI|CAPCLASS_TKT, 0,
    "Attach", "Add attchments to wiki or tickets" },
  { 'c', CAPCLASS_TKT, 0,
    "Append-Tkt", "Append to existing tickets" },
  /*
  ** d unused since fork from CVSTrac;
  ** see https://fossil-scm.org/forum/forumpost/43c78f4bef
  */
  { 'e', CAPCLASS_DATA, 0,







|







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
  unsigned nUser;         /* Number of users with this capability */
  char *zAbbrev;          /* Abbreviated mnemonic name */
  char *zOneLiner;        /* One-line summary */
} aCap[] = {
  { 'a', CAPCLASS_SUPER, 0,
    "Admin", "Create and delete users" },
  { 'b', CAPCLASS_WIKI|CAPCLASS_TKT, 0,
    "Attach", "Add attachments to wiki or tickets" },
  { 'c', CAPCLASS_TKT, 0,
    "Append-Tkt", "Append to existing tickets" },
  /*
  ** d unused since fork from CVSTrac;
  ** see https://fossil-scm.org/forum/forumpost/43c78f4bef
  */
  { 'e', CAPCLASS_DATA, 0,
Changes to src/captcha.c.
556
557
558
559
560
561
562
563

564
565
566
567
568
569
570
}

/*
** Add a "Speak the captcha" button.
*/
void captcha_speakit_button(unsigned int uSeed, const char *zMsg){
  if( zMsg==0 ) zMsg = "Speak the text";
  @ <input type="button" value="%h(zMsg)" id="speakthetext">

  @ <script nonce="%h(style_nonce())">
  @ document.getElementById("speakthetext").onclick = function(){
  @   var audio = window.fossilAudioCaptcha \
  @ || new Audio("%R/captcha-audio/%u(uSeed)");
  @   window.fossilAudioCaptcha = audio;
  @   audio.currentTime = 0;
  @   audio.play();







|
>







556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
}

/*
** Add a "Speak the captcha" button.
*/
void captcha_speakit_button(unsigned int uSeed, const char *zMsg){
  if( zMsg==0 ) zMsg = "Speak the text";
  @ <input aria-label="%h(zMsg)" type="button" value="%h(zMsg)" \
  @ id="speakthetext">
  @ <script nonce="%h(style_nonce())">
  @ document.getElementById("speakthetext").onclick = function(){
  @   var audio = window.fossilAudioCaptcha \
  @ || new Audio("%R/captcha-audio/%u(uSeed)");
  @   window.fossilAudioCaptcha = audio;
  @   audio.currentTime = 0;
  @   audio.play();
Changes to src/doc.c.
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
/*
** WEBPAGE: uv
** WEBPAGE: doc
** URL: /uv/FILE
** URL: /doc/CHECKIN/FILE
**
** CHECKIN can be either tag or hash prefix or timestamp identifying a
** particular check, or the name of a branch (meaning the most recent
** check-in on that branch) or one of various magic words:
**
**     "tip"      means the most recent check-in
**
**     "ckout"    means the current check-out, if the server is run from
**                within a check-out, otherwise it is the same as "tip"
**







|







808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
/*
** WEBPAGE: uv
** WEBPAGE: doc
** URL: /uv/FILE
** URL: /doc/CHECKIN/FILE
**
** CHECKIN can be either tag or hash prefix or timestamp identifying a
** particular check-in, or the name of a branch (meaning the most recent
** check-in on that branch) or one of various magic words:
**
**     "tip"      means the most recent check-in
**
**     "ckout"    means the current check-out, if the server is run from
**                within a check-out, otherwise it is the same as "tip"
**
Changes to src/forum.c.
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
){
  if( zTitle ){
    @ Title: <input type="input" name="title" value="%h(zTitle)" size="50"
    @ maxlength="125"><br>
  }
  @ %z(href("%R/markup_help"))Markup style</a>:
  mimetype_option_menu(zMimetype);
  @ <br><textarea name="content" class="wikiedit" cols="80" \
  @ rows="25" wrap="virtual">%h(zContent)</textarea><br>
}

/*
** WEBPAGE: forumnew
** WEBPAGE: forumedit
**
** Start a new thread on the forum or reply to an existing thread.







|
|







1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
){
  if( zTitle ){
    @ Title: <input type="input" name="title" value="%h(zTitle)" size="50"
    @ maxlength="125"><br>
  }
  @ %z(href("%R/markup_help"))Markup style</a>:
  mimetype_option_menu(zMimetype);
  @ <br><textarea aria-label="Content:" name="content" class="wikiedit" \
  @ cols="80" rows="25" wrap="virtual">%h(zContent)</textarea><br>
}

/*
** WEBPAGE: forumnew
** WEBPAGE: forumedit
**
** Start a new thread on the forum or reply to an existing thread.
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
    forum_render(zTitle, zMimetype, zContent,"forumEdit", 1);
    @ <form action="%R/forume2" method="POST">
    @ <input type="hidden" name="fpid" value="%h(P("fpid"))">
    @ <input type="hidden" name="nullout" value="1">
    @ <input type="hidden" name="mimetype" value="%h(zMimetype)">
    @ <input type="hidden" name="content" value="%h(zContent)">
    if( zTitle ){
      @ <input type="hidden" name="title" value="%h(zTitle)">
    }
  }else if( P("edit") ){
    /* Provide an edit to the fpid post */
    zMimetype = P("mimetype");
    zContent = PT("content");
    zTitle = P("title");
    if( zContent==0 ) zContent = fossil_strdup(pPost->zWiki);







|







1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
    forum_render(zTitle, zMimetype, zContent,"forumEdit", 1);
    @ <form action="%R/forume2" method="POST">
    @ <input type="hidden" name="fpid" value="%h(P("fpid"))">
    @ <input type="hidden" name="nullout" value="1">
    @ <input type="hidden" name="mimetype" value="%h(zMimetype)">
    @ <input type="hidden" name="content" value="%h(zContent)">
    if( zTitle ){
      @ <input aria-label="Title" type="hidden" name="title" value="%h(zTitle)">
    }
  }else if( P("edit") ){
    /* Provide an edit to the fpid post */
    zMimetype = P("mimetype");
    zContent = PT("content");
    zTitle = P("title");
    if( zContent==0 ) zContent = fossil_strdup(pPost->zWiki);
Changes to src/info.c.
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
/*
** WEBPAGE: ci_edit
**
** Edit a check-in.  (Check-ins are immutable and do not really change.
** This page really creates supplemental tags that affect the display
** of the check-in.)
**
** Query parmeters:
**
**     rid=INTEGER        Record ID of the check-in to edit (REQUIRED)
**
** POST parameters after pressing "Perview", "Cancel", or "Apply":
**
**     c=TEXT             New check-in comment
**     u=TEXT             New user name
**     newclr             Apply a background color
**     clr=TEXT           New background color (only if newclr)
**     pclr               Propagate new background color (only if newclr)
**     dt=TEXT            New check-in date/time (ISO8610 format)







|



|







2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
/*
** WEBPAGE: ci_edit
**
** Edit a check-in.  (Check-ins are immutable and do not really change.
** This page really creates supplemental tags that affect the display
** of the check-in.)
**
** Query parameters:
**
**     rid=INTEGER        Record ID of the check-in to edit (REQUIRED)
**
** POST parameters after pressing "Preview", "Cancel", or "Apply":
**
**     c=TEXT             New check-in comment
**     u=TEXT             New user name
**     newclr             Apply a background color
**     clr=TEXT           New background color (only if newclr)
**     pclr               Propagate new background color (only if newclr)
**     dt=TEXT            New check-in date/time (ISO8610 format)
Changes to src/login.c.
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691

692
693
694
695
696
697
698
699
                           " WHERE login='anonymous'"
                           "   AND cap!=''");
    }else{
      zAnonPw = 0;
    }
    @ <table class="login_out">
    @ <tr>
    @   <td class="form_label">User ID:</td>
    if( anonFlag ){
      @ <td><input type="text" id="u" name="u" value="anonymous" size="30"></td>
    }else{
      @ <td><input type="text" id="u" name="u" value="" size="30" /></td>
    }
    @ </tr>
    @ <tr>
    @  <td class="form_label">Password:</td>

    @  <td><input type="password" id="p" name="p" value="" size="30" />\
    if( zAnonPw && !noAnon ){
      captcha_speakit_button(uSeed, "Speak password for \"anonymous\"");
    }
    @ </td>
    @ </tr>
    if( P("HTTPS")==0 ){
      @ <tr><td class="form_label">Warning:</td>







|
<
|
<
|
<


|
>
|







676
677
678
679
680
681
682
683

684

685

686
687
688
689
690
691
692
693
694
695
696
697
                           " WHERE login='anonymous'"
                           "   AND cap!=''");
    }else{
      zAnonPw = 0;
    }
    @ <table class="login_out">
    @ <tr>
    @   <td class="form_label" id="userlabel1">User ID:</td>

    @   <td><input type="text" id="u" aria-labelledby="userlabel1" name="u" \

    @ size="30" value="%s(anonFlag?"anonymous":"")"></td>

    @ </tr>
    @ <tr>
    @  <td class="form_label" id="pswdlabel">Password:</td>
    @  <td><input aria-labelledby="pswdlabel" type="password" id="p" \
    @ name="p" value="" size="30" />\
    if( zAnonPw && !noAnon ){
      captcha_speakit_button(uSeed, "Speak password for \"anonymous\"");
    }
    @ </td>
    @ </tr>
    if( P("HTTPS")==0 ){
      @ <tr><td class="form_label">Warning:</td>
748
749
750
751
752
753
754
755

756
757

758
759

760
761
762
763
764
765
766
767
      @ for user <b>%h(g.zLogin)</b></p>
    }
    if( g.perm.Password ){
      @ <hr>
      @ <p>Change Password for user <b>%h(g.zLogin)</b>:</p>
      form_begin(0, "%R/login");
      @ <table>
      @ <tr><td class="form_label">Old Password:</td>

      @ <td><input type="password" name="p" size="30" /></td></tr>
      @ <tr><td class="form_label">New Password:</td>

      @ <td><input type="password" name="n1" size="30" /></td></tr>
      @ <tr><td class="form_label">Repeat New Password:</td>

      @ <td><input type="password" name="n2" size="30" /></td></tr>
      @ <tr><td></td>
      @ <td><input type="submit" value="Change Password" /></td></tr>
      @ </table>
      @ </form>
    }
  }
  style_footer();







|
>
|
|
>
|
|
>
|







746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
      @ for user <b>%h(g.zLogin)</b></p>
    }
    if( g.perm.Password ){
      @ <hr>
      @ <p>Change Password for user <b>%h(g.zLogin)</b>:</p>
      form_begin(0, "%R/login");
      @ <table>
      @ <tr><td class="form_label" id="oldpw">Old Password:</td>
      @ <td><input aria-labelledby="oldpw" type="password" name="p" \
      @ size="30"/></td></tr>
      @ <tr><td class="form_label" id="newpw">New Password:</td>
      @ <td><input aria-labelledby="newpw" type="password" name="n1" \
      @ size="30" /></td></tr>
      @ <tr><td class="form_label" id="reppw">Repeat New Password:</td>
      @ <td><input aria-labledby="reppw" type="password" name="n2" \
      @ size="30" /></td></tr>
      @ <tr><td></td>
      @ <td><input type="submit" value="Change Password" /></td></tr>
      @ </table>
      @ </form>
    }
  }
  style_footer();
1688
1689
1690
1691
1692
1693
1694
1695

1696
1697
1698
1699
1700
1701
1702

1703
1704
1705
1706
1707
1708
1709
1710

1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726

1727
1728
1729
1730
1731
1732
1733

1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
  form_begin(0, "%R/register");
  if( P("g") ){
    @ <input type="hidden" name="g" value="%h(P("g"))" />
  }
  @ <p><input type="hidden" name="captchaseed" value="%u(uSeed)" />
  @ <table class="login_out">
  @ <tr>
  @   <td class="form_label" align="right">User ID:</td>

  @   <td><input type="text" name="u" value="%h(zUserID)" size="30"></td>
  @
  if( iErrLine==1 ){
    @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
  }
  @ <tr>
  @   <td class="form_label" align="right">Display Name:</td>

  @   <td><input type="text" name="dn" value="%h(zDName)" size="30"></td>
  @ </tr>
  if( iErrLine==2 ){
    @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
  }
  @ </tr>
  @ <tr>
  @   <td class="form_label" align="right">Email Address:</td>

  @   <td><input type="text" name="ea" value="%h(zEAddr)" size="30"></td>
  @ </tr>
  if( iErrLine==3 ){
    @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
  }
  if( canDoAlerts ){
    int a = atoi(PD("alerts","1"));
    @ <tr>
    @   <td class="form_label" align="right">Email&nbsp;Alerts?</td>
    @   <td><select size='1' name='alerts'>
    @       <option value="1" %s(a?"selected":"")>Yes</option>
    @       <option value="0" %s(!a?"selected":"")>No</option>
    @   </select></td></tr>
  }
  @ <tr>
  @   <td class="form_label" align="right">Password:</td>

  @   <td><input type="password" name="p" value="%h(zPasswd)" size="30"></td>
  @ <tr>
  if( iErrLine==4 ){
    @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
  }
  @ <tr>
  @   <td class="form_label" align="right">Confirm:</td>

  @   <td><input type="password" name="cp" value="%h(zConfirm)" size="30"></td>
  @ </tr>
  if( iErrLine==5 ){
    @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
  }
  @ <tr>
  @   <td class="form_label" align="right">Captcha:</td>
  @   <td><input type="text" name="captcha" \
  @ value="%h(captchaIsCorrect?zDecoded:"")" size="30">
  captcha_speakit_button(uSeed, "Speak the captcha text");
  @   </td>
  @ </tr>
  if( iErrLine==6 ){
    @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
  }







|
>
|





|
>
|






|
>
|







|
|





|
>
|





|
>
|





|
|







1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
  form_begin(0, "%R/register");
  if( P("g") ){
    @ <input type="hidden" name="g" value="%h(P("g"))" />
  }
  @ <p><input type="hidden" name="captchaseed" value="%u(uSeed)" />
  @ <table class="login_out">
  @ <tr>
  @   <td class="form_label" align="right" id="uid">User ID:</td>
  @   <td><input aria-labelledby="uid" type="text" name="u" \
  @ value="%h(zUserID)" size="30"></td>
  @
  if( iErrLine==1 ){
    @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
  }
  @ <tr>
  @   <td class="form_label" align="right" id="dpyname">Display Name:</td>
  @   <td><input aria-labelledby="dpyname" type="text" name="dn" \
  @ value="%h(zDName)" size="30"></td>
  @ </tr>
  if( iErrLine==2 ){
    @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
  }
  @ </tr>
  @ <tr>
  @   <td class="form_label" align="right" id="emaddr">Email Address:</td>
  @   <td><input aria-labelledby="emaddr" type="text" name="ea" \
  @ value="%h(zEAddr)" size="30"></td>
  @ </tr>
  if( iErrLine==3 ){
    @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
  }
  if( canDoAlerts ){
    int a = atoi(PD("alerts","1"));
    @ <tr>
    @   <td class="form_label" align="right" id="emalrt">Email&nbsp;Alerts?</td>
    @   <td><select aria-labelledby="emalrt" size='1' name='alerts'>
    @       <option value="1" %s(a?"selected":"")>Yes</option>
    @       <option value="0" %s(!a?"selected":"")>No</option>
    @   </select></td></tr>
  }
  @ <tr>
  @   <td class="form_label" align="right" id="pswd">Password:</td>
  @   <td><input aria-labelledby="pswd" type="password" name="p" \
  @ value="%h(zPasswd)" size="30"></td>
  @ <tr>
  if( iErrLine==4 ){
    @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
  }
  @ <tr>
  @   <td class="form_label" align="right" id="pwcfrm">Confirm:</td>
  @   <td><input aria-labelledby="pwcfrm" type="password" name="cp" \
  @ value="%h(zConfirm)" size="30"></td>
  @ </tr>
  if( iErrLine==5 ){
    @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
  }
  @ <tr>
  @   <td class="form_label" align="right" id="cptcha">Captcha:</td>
  @   <td><input type="text" name="captcha" aria-labelledby="cptcha" \
  @ value="%h(captchaIsCorrect?zDecoded:"")" size="30">
  captcha_speakit_button(uSeed, "Speak the captcha text");
  @   </td>
  @ </tr>
  if( iErrLine==6 ){
    @ <tr><td><td><span class='loginError'>&uarr; %h(zErr)</span></td></tr>
  }
Changes to src/setup.c.
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214
215
216
217
218
      login_verify_csrf_secret();
      db_set(zVar, iQ ? "1" : "0", 0);
      admin_log("Set option [%q] to [%q].",
                zVar, iQ ? "on" : "off");
      iVal = iQ;
    }
  }
  @ <label><input type="checkbox" name="%s(zQParm)"

  if( iVal ){
    @ checked="checked"
  }
  if( disabled ){
    @ disabled="disabled"
  }
  @ /> <b>%s(zLabel)</b></label>
}

/*
** Generate an entry box for an attribute.
*/







|
>

|


|







199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
      login_verify_csrf_secret();
      db_set(zVar, iQ ? "1" : "0", 0);
      admin_log("Set option [%q] to [%q].",
                zVar, iQ ? "on" : "off");
      iVal = iQ;
    }
  }
  @ <label><input type="checkbox" name="%s(zQParm)" \
  @ aria-label="%s(zLabel[0]?zLabel:zQParm)" \
  if( iVal ){
    @ checked="checked" \
  }
  if( disabled ){
    @ disabled="disabled" \
  }
  @ /> <b>%s(zLabel)</b></label>
}

/*
** Generate an entry box for an attribute.
*/
230
231
232
233
234
235
236

237
238
239
240
241
242
243
244
245
    const int nZQ = (int)strlen(zQ);
    login_verify_csrf_secret();
    db_set(zVar, zQ, 0);
    admin_log("Set entry_attribute %Q to: %.*s%s",
              zVar, 20, zQ, (nZQ>20 ? "..." : ""));
    zVal = zQ;
  }

  @ <input type="text" id="%s(zQParm)" name="%s(zQParm)" value="%h(zVal)" \
  @ size="%d(width)" \
  if( disabled ){
    @ disabled="disabled" \
  }
  @ /> <b>%s(zLabel)</b>
}

/*







>
|
<







231
232
233
234
235
236
237
238
239

240
241
242
243
244
245
246
    const int nZQ = (int)strlen(zQ);
    login_verify_csrf_secret();
    db_set(zVar, zQ, 0);
    admin_log("Set entry_attribute %Q to: %.*s%s",
              zVar, 20, zQ, (nZQ>20 ? "..." : ""));
    zVal = zQ;
  }
  @ <input aria-label="%h(zLabel[0]?zLabel:zQParm)" type="text" \
  @ id="%s(zQParm)" name="%s(zQParm)" value="%h(zVal)" size="%d(width)" \

  if( disabled ){
    @ disabled="disabled" \
  }
  @ /> <b>%s(zLabel)</b>
}

/*
261
262
263
264
265
266
267
268

269
270
271
272
273
274
275
276
277
278
279
280
    login_verify_csrf_secret();
    db_set(zVar, zQ, 0);
    admin_log("Set textarea_attribute %Q to: %.*s%s",
              zVar, 20, zQ, (nZQ>20 ? "..." : ""));
    z = zQ;
  }
  if( rows>0 && cols>0 ){
    @ <textarea id="id%s(zQP)" name="%s(zQP)" rows="%d(rows)"

    if( disabled ){
      @ disabled="disabled"
    }
    @ cols="%d(cols)">%h(z)</textarea>
    if( zLabel && *zLabel ){
      @ <span class="textareaLabel">%s(zLabel)</span>
    }
  }
  return z;
}

/*







|
>

|


|







262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
    login_verify_csrf_secret();
    db_set(zVar, zQ, 0);
    admin_log("Set textarea_attribute %Q to: %.*s%s",
              zVar, 20, zQ, (nZQ>20 ? "..." : ""));
    z = zQ;
  }
  if( rows>0 && cols>0 ){
    @ <textarea id="id%s(zQP)" name="%s(zQP)" rows="%d(rows)" \
    @ aria-label="%h(zLabel[0]?zLabel:zQP)" \
    if( disabled ){
      @ disabled="disabled" \
    }
    @ cols="%d(cols)">%h(z)</textarea>
    if( *zLabel ){
      @ <span class="textareaLabel">%s(zLabel)</span>
    }
  }
  return z;
}

/*
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
    const int nZQ = (int)strlen(zQ);
    login_verify_csrf_secret();
    db_set(zVar, zQ, 0);
    admin_log("Set multiple_choice_attribute %Q to: %.*s%s",
              zVar, 20, zQ, (nZQ>20 ? "..." : ""));
    z = zQ;
  }
  @ <select size="1" name="%s(zQP)" id="id%s(zQP)">
  for(i=0; i<nChoice*2; i+=2){
    const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
    @ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
  }
  @ </select> <b>%h(zLabel)</b>
}








|







297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
    const int nZQ = (int)strlen(zQ);
    login_verify_csrf_secret();
    db_set(zVar, zQ, 0);
    admin_log("Set multiple_choice_attribute %Q to: %.*s%s",
              zVar, 20, zQ, (nZQ>20 ? "..." : ""));
    z = zQ;
  }
  @ <select aria-label="%h(zLabel)" size="1" name="%s(zQP)" id="id%s(zQP)">
  for(i=0; i<nChoice*2; i+=2){
    const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
    @ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
  }
  @ </select> <b>%h(zLabel)</b>
}

396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
  @ </p>
  @
  @ <hr />
  onoff_attribute("Allow HTTP_AUTHENTICATION authentication",
     "http_authentication_ok", "http_authentication_ok", 0, 0);
  @ <p>When enabled, allow the use of the HTTP_AUTHENTICATION environment
  @ variable or the "Authentication:" HTTP header to find the username and
  @ password. This is another way of supporting Basic Authenitication.
  @ (Property: "http_authentication_ok")
  @ </p>
  @
  @ <hr />
  entry_attribute("Login expiration time", 6, "cookie-expire", "cex",
                  "8766", 0);
  @ <p>The number of hours for which a login is valid.  This must be a







|







398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
  @ </p>
  @
  @ <hr />
  onoff_attribute("Allow HTTP_AUTHENTICATION authentication",
     "http_authentication_ok", "http_authentication_ok", 0, 0);
  @ <p>When enabled, allow the use of the HTTP_AUTHENTICATION environment
  @ variable or the "Authentication:" HTTP header to find the username and
  @ password. This is another way of supporting Basic Authentication.
  @ (Property: "http_authentication_ok")
  @ </p>
  @
  @ <hr />
  entry_attribute("Login expiration time", 6, "cookie-expire", "cex",
                  "8766", 0);
  @ <p>The number of hours for which a login is valid.  This must be a
604
605
606
607
608
609
610

611
612

613
614
615
616

617
618
619
620
621

622
623
624

625
626
627
628
629
630
631
632
    @ is not currently part of any login-group.
    @ To join a login group, fill out the form below.</p>
    @
    @ <form action="%s(g.zTop)/setup_login_group" method="post"><div>
    login_insert_csrf_secret();
    @ <blockquote><table border="0">
    @

    @ <tr><th align="right">Repository filename in group to join:</th>
    @ <td width="5"></td><td>

    @ <input type="text" size="50" value="%h(zRepo)" name="repo"></td></tr>
    @
    @ <tr><th align="right">Login on the above repo:</th>
    @ <td width="5"></td><td>

    @ <input type="text" size="20" value="%h(zLogin)" name="login"></td></tr>
    @
    @ <tr><th align="right">Password:</th>
    @ <td width="5"></td><td>
    @ <input type="password" size="20" name="pw"></td></tr>

    @
    @ <tr><th align="right">Name of login-group:</th>
    @ <td width="5"></td><td>

    @ <input type="text" size="30" value="%h(zNewName)" name="newname">
    @ (only used if creating a new login-group).</td></tr>
    @
    @ <tr><td colspan="3" align="center">
    @ <input type="submit" value="Join" name="join"></td></tr>
    @ </table></blockquote></div></form>
  }else{
    Stmt q;







>
|

>
|

|

>
|

|

|
>

|

>
|







606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
    @ is not currently part of any login-group.
    @ To join a login group, fill out the form below.</p>
    @
    @ <form action="%s(g.zTop)/setup_login_group" method="post"><div>
    login_insert_csrf_secret();
    @ <blockquote><table border="0">
    @
    @ <tr><th align="right" id="rfigtj">Repository filename \
    @ in group to join:</th>
    @ <td width="5"></td><td>
    @ <input aria-labelledby="rfigtj" type="text" size="50" \
    @ value="%h(zRepo)" name="repo"></td></tr>
    @
    @ <tr><th align="right" id="lotar">Login on the above repo:</th>
    @ <td width="5"></td><td>
    @ <input aria-labelledby="lotar" type="text" size="20" \
    @ value="%h(zLogin)" name="login"></td></tr>
    @
    @ <tr><th align="right" id="lgpw">Password:</th>
    @ <td width="5"></td><td>
    @ <input aria-labelledby="lgpw" type="password" size="20" name="pw">\
    @ </td></tr>
    @
    @ <tr><th align="right" id="nolg">Name of login-group:</th>
    @ <td width="5"></td><td>
    @ <input aria-labelledby="nolg" type="text" size="30" \
    @ value="%h(zNewName)" name="newname">
    @ (only used if creating a new login-group).</td></tr>
    @
    @ <tr><td colspan="3" align="center">
    @ <input type="submit" value="Join" name="join"></td></tr>
    @ </table></blockquote></div></form>
  }else{
    Stmt q;
Changes to src/setupuser.c.
532
533
534
535
536
537
538
539
540

541
542
543

544
545
546
547
548
549
550
551

552
553
554
555
556
557
558
559
560
561
562
563
564

565
566
567
568
569
570
571
572
    @ <input type="hidden" name="login" value="%s(zLogin)">
    @ <input type="hidden" name="info" value="">
    @ <input type="hidden" name="pw" value="*">
  }
  @ <input type="hidden" name="referer" value="%h(cgi_referer("setup_ulist"))">
  @ <table width="100%%">
  @ <tr>
  @   <td class="usetupEditLabel">User ID:</td>
  if( uid ){

    @   <td>%d(uid) <input type="hidden" name="id" value="%d(uid)" />\
    @ </td>
  }else{

    @   <td>(new user)<input type="hidden" name="id" value="0" /></td>
  }
  @ </tr>
  @ <tr>
  @   <td class="usetupEditLabel">Login:</td>
  if( login_is_special(zLogin) ){
    @    <td><b>%h(zLogin)</b></td>
  }else{

    @   <td><input type="text" name="login" value="%h(zLogin)" />\
    if( alert_tables_exist() ){
      int sid;
      sid = db_int(0, "SELECT subscriberId FROM subscriber"
                      " WHERE suname=%Q", zLogin);
      if( sid>0 ){
        @ &nbsp;&nbsp;<a href="%R/alerts?sid=%d(sid)">\
        @ (subscription info for %h(zLogin))</a>\
      }
    }
    @ </td></tr>
    @ <tr>
    @   <td class="usetupEditLabel">Contact&nbsp;Info:</td>

    @   <td><textarea name="info" cols="40" rows="2">%h(zInfo)</textarea></td>
  }
  @ </tr>
  @ <tr>
  @   <td class="usetupEditLabel">Capabilities:</td>
  @   <td width="100%%">
#define B(x) inherit[x]
  @ <div class="columns" style="column-width:13em;">







|

>
|


>
|



|



>
|











|
>
|







532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
    @ <input type="hidden" name="login" value="%s(zLogin)">
    @ <input type="hidden" name="info" value="">
    @ <input type="hidden" name="pw" value="*">
  }
  @ <input type="hidden" name="referer" value="%h(cgi_referer("setup_ulist"))">
  @ <table width="100%%">
  @ <tr>
  @   <td class="usetupEditLabel" id="suuid">User ID:</td>
  if( uid ){
    @   <td>%d(uid) <input aria-labelledby="suuid" type="hidden" \
    @   name="id" value="%d(uid)"/>\
    @ </td>
  }else{
    @   <td>(new user)<input aria-labelledby="suuid" type="hidden" name="id" \
    @ value="0" /></td>
  }
  @ </tr>
  @ <tr>
  @   <td class="usetupEditLabel" id="sulgn">Login:</td>
  if( login_is_special(zLogin) ){
    @    <td><b>%h(zLogin)</b></td>
  }else{
    @   <td><input aria-labelledby="sulgn" type="text" name="login" \
    @ value="%h(zLogin)" />
    if( alert_tables_exist() ){
      int sid;
      sid = db_int(0, "SELECT subscriberId FROM subscriber"
                      " WHERE suname=%Q", zLogin);
      if( sid>0 ){
        @ &nbsp;&nbsp;<a href="%R/alerts?sid=%d(sid)">\
        @ (subscription info for %h(zLogin))</a>\
      }
    }
    @ </td></tr>
    @ <tr>
    @   <td class="usetupEditLabel" id="sucnfo">Contact&nbsp;Info:</td>
    @   <td><textarea aria-labelledby="sucnfo" name="info" cols="40" \
    @ rows="2">%h(zInfo)</textarea></td>
  }
  @ </tr>
  @ <tr>
  @   <td class="usetupEditLabel">Capabilities:</td>
  @   <td width="100%%">
#define B(x) inherit[x]
  @ <div class="columns" style="column-width:13em;">
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
  @   <td>
  @     <span id="usetupEditCapability">(missing JS?)</span>
  @     <a href="%R/setup_ucap_list">(key)</a>
  @   </td>
  @ </tr>
  if( !login_is_special(zLogin) ){
    @ <tr>
    @   <td align="right">Password:</td>
    if( zPw[0] ){
      /* Obscure the password for all users */
      @   <td><input type="password" autocomplete="off" name="pw"\
      @   value="**********" /></td>
    }else{
      /* Show an empty password as an empty input field */
      @   <td><input type="password" autocomplete="off" name="pw"\
      @   value="" /></td>
    }
    @ </tr>
  }
  zGroup = login_group_name();
  if( zGroup ){
    @ <tr>
    @ <td valign="top" align="right">Scope:</td>







|


|
|


|
|







655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
  @   <td>
  @     <span id="usetupEditCapability">(missing JS?)</span>
  @     <a href="%R/setup_ucap_list">(key)</a>
  @   </td>
  @ </tr>
  if( !login_is_special(zLogin) ){
    @ <tr>
    @   <td align="right" id="supw">Password:</td>
    if( zPw[0] ){
      /* Obscure the password for all users */
      @   <td><input aria-labelledby="supw" type="password" autocomplete="off" \
      @   name="pw" value="**********" /></td>
    }else{
      /* Show an empty password as an empty input field */
      @   <td><input aria-labelledby="supw" type="password" name="pw" \
      @        autocomplete="off" value="" /></td>
    }
    @ </tr>
  }
  zGroup = login_group_name();
  if( zGroup ){
    @ <tr>
    @ <td valign="top" align="right">Scope:</td>
Changes to src/skins.c.
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
  @ <h1>Step 7: Publish</h1>
  @
  if( !g.perm.Admin ){
    @ <p>Only administrators are allowed to publish draft skins.  Contact
    @ an administrator to get this "draft%d(iSkin)" skin published.</p>
  }else{
    @ <p>When the draft%d(iSkin) skin is ready for production use,
    @ make it the default scan by clicking the acknowledgements and
    @ pressing the button below:</p>
    @
    @ <form method='POST' action='%R/setup_skin#step7'>
    @ <p class='skinInput'>
    @ <input type='hidden' name='sk' value='%d(iSkin)'>
    @ <input type='checkbox' name='pub7ck1' value='yes'>\
    @ Skin draft%d(iSkin) has been tested and found ready for production.<br>







|







1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
  @ <h1>Step 7: Publish</h1>
  @
  if( !g.perm.Admin ){
    @ <p>Only administrators are allowed to publish draft skins.  Contact
    @ an administrator to get this "draft%d(iSkin)" skin published.</p>
  }else{
    @ <p>When the draft%d(iSkin) skin is ready for production use,
    @ make it the default skin by clicking the acknowledgements and
    @ pressing the button below:</p>
    @
    @ <form method='POST' action='%R/setup_skin#step7'>
    @ <p class='skinInput'>
    @ <input type='hidden' name='sk' value='%d(iSkin)'>
    @ <input type='checkbox' name='pub7ck1' value='yes'>\
    @ Skin draft%d(iSkin) has been tested and found ready for production.<br>
Changes to www/cgi.wiki.
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
A [./server/|separate document] talks about all of the many different methods for
setting up a Fossil server, one of which is [./server/any/cgi.md | as a CGI
script].  CGI is the technique that the three
[./selfhost.wiki|self-hosting Fossil repositories] all use.

Setting up a Fossil server using CGI is mostly about writing a short
script (usually just 2 lines line) in the cgi-bin folder of an ordinary
web-browser.  But there are a lot of extra options that can be added
to this script, to customize the configuration.  This article descripts
those options.

<h1>CGI Script Options</h1>

The CGI script used to launch a Fossil server will usually look something
like this:








|
|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
A [./server/|separate document] talks about all of the many different methods for
setting up a Fossil server, one of which is [./server/any/cgi.md | as a CGI
script].  CGI is the technique that the three
[./selfhost.wiki|self-hosting Fossil repositories] all use.

Setting up a Fossil server using CGI is mostly about writing a short
script (usually just 2 lines line) in the cgi-bin folder of an ordinary
web-server.  But there are a lot of extra options that can be added
to this script, to customize the configuration.  This article describes
those options.

<h1>CGI Script Options</h1>

The CGI script used to launch a Fossil server will usually look something
like this: