Fossil

Check-in [22c1ac41d4]
Login

Check-in [22c1ac41d4]

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

Overview
Comment:Add separate "clone" permissions. Previously, one needed "History" premission in order to clone. But sometimes we want to grant clone without granting history.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 22c1ac41d4c02c44fe1763b9267a5f06e95c5a24
User & Date: drh 2007-08-23 19:52:19.000
Context
2007-08-25
03:23
Fixed typos in comments ... (check-in: 609e4caf29 user: aku tags: trunk)
2007-08-23
23:10
Website updates. Change the message for unrecognized commands to refer the user to "help". ... (check-in: 0cd202a86e user: drh tags: trunk)
19:52
Add separate "clone" permissions. Previously, one needed "History" premission in order to clone. But sometimes we want to grant clone without granting history. ... (check-in: 22c1ac41d4 user: drh tags: trunk)
2007-08-19
11:06
Fix the "Leaves" computation on the vinfo web page. Improvements to the vinfo web page. ... (check-in: 4ac16995e8 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/login.c.
285
286
287
288
289
290
291
292
293
294
295
296
297

298
299
300
301
302
303
304
void login_set_capabilities(const char *zCap){
  int i;
  for(i=0; zCap[i]; i++){
    switch( zCap[i] ){
      case 's':   g.okSetup = g.okDelete = 1;
      case 'a':   g.okAdmin = g.okRdTkt = g.okWrTkt = g.okQuery =
                              g.okRdWiki = g.okWrWiki = g.okHistory =
                              g.okNewTkt = g.okPassword = 1;
      case 'i':   g.okRead = g.okWrite = 1;                     break;
      case 'o':   g.okRead = 1;                                 break;

      case 'd':   g.okDelete = 1;                               break;
      case 'h':   g.okHistory = 1;                              break;

      case 'p':   g.okPassword = 1;                             break;
      case 'q':   g.okQuery = 1;                                break;

      case 'j':   g.okRdWiki = 1;                               break;
      case 'k':   g.okWrWiki = g.okRdWiki = g.okApndWiki =1;    break;
      case 'm':   g.okApndWiki = 1;                             break;
      case 'f':   g.okNewWiki = 1;                              break;







|





>







285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
void login_set_capabilities(const char *zCap){
  int i;
  for(i=0; zCap[i]; i++){
    switch( zCap[i] ){
      case 's':   g.okSetup = g.okDelete = 1;
      case 'a':   g.okAdmin = g.okRdTkt = g.okWrTkt = g.okQuery =
                              g.okRdWiki = g.okWrWiki = g.okHistory =
                              g.okNewTkt = g.okPassword = g.okClone = 1;
      case 'i':   g.okRead = g.okWrite = 1;                     break;
      case 'o':   g.okRead = 1;                                 break;

      case 'd':   g.okDelete = 1;                               break;
      case 'h':   g.okHistory = 1;                              break;
      case 'g':   g.okClone = 1;                                break;
      case 'p':   g.okPassword = 1;                             break;
      case 'q':   g.okQuery = 1;                                break;

      case 'j':   g.okRdWiki = 1;                               break;
      case 'k':   g.okWrWiki = g.okRdWiki = g.okApndWiki =1;    break;
      case 'm':   g.okApndWiki = 1;                             break;
      case 'f':   g.okNewWiki = 1;                              break;
Changes to src/main.c.
83
84
85
86
87
88
89




90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

  /* Information used to populate the RCVFROM table */
  int rcvid;              /* The rcvid.  0 if not yet defined. */
  char *zIpAddr;          /* The remote IP address */
  char *zNonce;           /* The nonce used for login */
  
  /* permissions used by the server */




  int okRead;             /* xfer outbound */
  int okWrite;            /* xfer inbound */
  int okSetup;            /* use Setup screens on web interface */
  int okRdTkt;            /* view tickets via web */
  int okWrTkt;            /* make changes to tickets via web */
  int okNewTkt;           /* create new tickets */
  int okApndTkt;          /* append to tickets via the web */
  int okRdWiki;           /* view wiki via web */
  int okWrWiki;           /* edit wiki via web */
  int okNewWiki;          /* create new wiki via web */
  int okApndWiki;         /* append to wiki via web */
  int okPassword;         /* change password */
  int okAdmin;            /* administrative permission */
  int okDelete;           /* delete wiki or tickets */
  int okQuery;            /* create new reports */
  int okHistory;          /* access historical information */

  FILE *fDebug;           /* Write debug information here, if the file exists */
};

/*
** Macro for debugging:
*/







>
>
>
>
|
|
|
|
|
<
<
|
<
|
|
|
|
|
|
|







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98


99

100
101
102
103
104
105
106
107
108
109
110
111
112
113

  /* Information used to populate the RCVFROM table */
  int rcvid;              /* The rcvid.  0 if not yet defined. */
  char *zIpAddr;          /* The remote IP address */
  char *zNonce;           /* The nonce used for login */
  
  /* permissions used by the server */
  int okSetup;            /* s: use Setup screens on web interface */
  int okAdmin;            /* a: administrative permission */
  int okDelete;           /* d: delete wiki or tickets */
  int okPassword;         /* p: change password */
  int okQuery;            /* q: create new reports */
  int okWrite;            /* i: xfer inbound. checkin */
  int okRead;             /* o: xfer outbound. checkout */
  int okHistory;          /* h: access historical information. */
  int okClone;            /* g: clone */


  int okRdWiki;           /* j: view wiki via web */

  int okNewWiki;          /* f: create new wiki via web */
  int okApndWiki;         /* m: append to wiki via web */
  int okWrWiki;           /* k: edit wiki via web */
  int okRdTkt;            /* r: view tickets via web */
  int okNewTkt;           /* n: create new tickets */
  int okApndTkt;          /* c: append to tickets via the web */
  int okWrTkt;            /* w: make changes to tickets via web */

  FILE *fDebug;           /* Write debug information here, if the file exists */
};

/*
** Macro for debugging:
*/
Changes to src/setup.c.
115
116
117
118
119
120
121

122
123
124
125
126
127
128
129
130
131
132
133
134
135

136




137

138

139
140
141
142
143

144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
  }
  @ </table></td></tr></table>
  @ <p style="clear:both">
  @ <b>Notes:</b>
  @ <ol>
  @ <li><p>The permission flags are as follows:</p>
  @ <table>

  @ <tr><td>a</td><td width="10"></td>
  @     <td>Admin: Create or delete users and ticket report formats</td></tr>
  @ <tr><td>d</td><td></td>
  @     <td>Delete: Erase anonymous wiki, tickets, and attachments</td></tr>
  @ <tr><td>h</td><td></td>
  @     <td>History: Access older version of code, tickets, or wiki</td></tr>
  @ <tr><td>i</td><td></td>
  @     <td>Check-in: Add new code to the repository</td></tr>
  @ <tr><td>j</td><td></td><td>Read-Wiki: View wiki pages</td></tr>
  @ <tr><td>k</td><td></td><td>Wiki: Create or modify wiki pages</td></tr>
  @ <tr><td>n</td><td></td><td>New: Create new tickets</td></tr>
  @ <tr><td>o</td><td></td>
  @     <td>Check-out: Read code out of the repository</td></tr>
  @ <tr><td>p</td><td></td><td>Password: Change password</td></tr>

  @ <tr><td>q</td><td></td><td>Query: Create or edit report formats</td></tr>




  @ <tr><td>r</td><td></td><td>Read: View tickets and change histories</td></tr>

  @ <tr><td>s</td><td></td><td>Setup: Change CVSTrac options</td></tr>

  @ <tr><td>w</td><td></td><td>Write: Edit tickets</td></tr>
  @ </table>
  @ </p></li>
  @
  @ <li><p>

  @ If a user named "<b>anonymous</b>" exists, then anyone can access
  @ the server without having to log in.  The permissions on the
  @ anonymous user determine the access rights for anyone who is not
  @ logged in.
  @ </p></li>
  @
  @ </ol>
  style_footer();
}

/*
** WEBPAGE: /setup_uedit
*/
void user_edit(void){
  const char *zId, *zLogin, *zInfo, *zCap;
  char *oaa, *oas, *oar, *oaw, *oan, *oai, *oaj, *oao, *oap ;
  char *oak, *oad, *oaq, *oac, *oaf, *oam, *oah;
  int doWrite;
  int uid;
  int higherUser = 0;  /* True if user being edited is SETUP and the */
                       /* user doing the editing is ADMIN.  Disallow editing */

  /* Must have ADMIN privleges to access this page
  */







>




|
|


<
<
<


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




>
|
|
|
<












|







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  }
  @ </table></td></tr></table>
  @ <p style="clear:both">
  @ <b>Notes:</b>
  @ <ol>
  @ <li><p>The permission flags are as follows:</p>
  @ <table>
  @ <tr><td>s</td><td></td><td>Setup: Superuser can do anything</td></tr>
  @ <tr><td>a</td><td width="10"></td>
  @     <td>Admin: Create or delete users and ticket report formats</td></tr>
  @ <tr><td>d</td><td></td>
  @     <td>Delete: Erase anonymous wiki, tickets, and attachments</td></tr>
  @ <tr><td>p</td><td></td><td>Password: Change password</td></tr>
  @ <tr><td>q</td><td></td><td>Query: Create or edit report formats</td></tr>
  @ <tr><td>i</td><td></td>
  @     <td>Check-in: Add new code to the repository</td></tr>



  @ <tr><td>o</td><td></td>
  @     <td>Check-out: Read code out of the repository</td></tr>
  @ <tr><td>h</td><td></td>
  @     <td>History: Access older version of code, tickets, or wiki</td></tr>
  @ <tr><td>g</td><td></td><td>Clone: Clone the repository</td></tr>
  @ <tr><td>j</td><td></td><td>Read-Wiki: View wiki pages</td></tr>
  @ <tr><td>f</td><td></td><td>New-Wiki: Create new wiki pages</td></tr>
  @ <tr><td>m</td><td></td><td>Append-Wiki: Append to wiki pages</td></tr>
  @ <tr><td>k</td><td></td><td>Write-Wiki: Modify wiki pages</td></tr>
  @ <tr><td>r</td><td></td>
  @      <td>Read-Tkt: View tickets and change histories</td></tr>
  @ <tr><td>n</td><td></td><td>New-Tkt: Create new tickets</td></tr>
  @ <tr><td>c</td><td></td><td>Append-Tkt: Append to tickets</td></tr>
  @ <tr><td>w</td><td></td><td>Write-Tkt: Edit tickets</td></tr>
  @ </table>
  @ </p></li>
  @
  @ <li><p>
  @ Every user, logged in or not, has the privileges of <b>nobody</b>.
  @ Any human can login as <b>anonymous</b> since the password is
  @ clearly displayed on the login page for them to type.  The purpose
  @ of requiring anonymous to log in is to prevent access by spiders.

  @ </p></li>
  @
  @ </ol>
  style_footer();
}

/*
** WEBPAGE: /setup_uedit
*/
void user_edit(void){
  const char *zId, *zLogin, *zInfo, *zCap;
  char *oaa, *oas, *oar, *oaw, *oan, *oai, *oaj, *oao, *oap ;
  char *oak, *oad, *oaq, *oac, *oaf, *oam, *oah, *oag;
  int doWrite;
  int uid;
  int higherUser = 0;  /* True if user being edited is SETUP and the */
                       /* user doing the editing is ADMIN.  Disallow editing */

  /* Must have ADMIN privleges to access this page
  */
206
207
208
209
210
211
212

213
214
215
216
217

218
219
220
221
222
223
224
    int ar = P("ar")!=0;
    int as = g.okSetup && P("as")!=0;
    int aw = P("aw")!=0;
    int ac = P("ac")!=0;
    int af = P("af")!=0;
    int am = P("am")!=0;
    int ah = P("ah")!=0;

    if( aa ){ zCap[i++] = 'a'; }
    if( ac ){ zCap[i++] = 'c'; }
    if( ad ){ zCap[i++] = 'd'; }
    if( af ){ zCap[i++] = 'f'; }
    if( ah ){ zCap[i++] = 'h'; }

    if( ai ){ zCap[i++] = 'i'; }
    if( aj ){ zCap[i++] = 'j'; }
    if( ak ){ zCap[i++] = 'k'; }
    if( am ){ zCap[i++] = 'm'; }
    if( an ){ zCap[i++] = 'n'; }
    if( ao ){ zCap[i++] = 'o'; }
    if( ap ){ zCap[i++] = 'p'; }







>





>







211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
    int ar = P("ar")!=0;
    int as = g.okSetup && P("as")!=0;
    int aw = P("aw")!=0;
    int ac = P("ac")!=0;
    int af = P("af")!=0;
    int am = P("am")!=0;
    int ah = P("ah")!=0;
    int ag = P("ag")!=0;
    if( aa ){ zCap[i++] = 'a'; }
    if( ac ){ zCap[i++] = 'c'; }
    if( ad ){ zCap[i++] = 'd'; }
    if( af ){ zCap[i++] = 'f'; }
    if( ah ){ zCap[i++] = 'h'; }
    if( ag ){ zCap[i++] = 'g'; }
    if( ai ){ zCap[i++] = 'i'; }
    if( aj ){ zCap[i++] = 'j'; }
    if( ak ){ zCap[i++] = 'k'; }
    if( am ){ zCap[i++] = 'm'; }
    if( an ){ zCap[i++] = 'n'; }
    if( ao ){ zCap[i++] = 'o'; }
    if( ap ){ zCap[i++] = 'p'; }
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
  }

  /* Load the existing information about the user, if any
  */
  zLogin = "";
  zInfo = "";
  zCap = "";
  oaa = oac = oad = oaf = oah = oai = oaj = oak = oam =
        oan = oao = oap = oaq = oar = oas = oaw = "";
  if( uid ){
    zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid);
    zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid);
    zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid);
    if( strchr(zCap, 'a') ) oaa = " checked";
    if( strchr(zCap, 'c') ) oac = " checked";
    if( strchr(zCap, 'd') ) oad = " checked";
    if( strchr(zCap, 'f') ) oaf = " checked";

    if( strchr(zCap, 'h') ) oah = " checked";
    if( strchr(zCap, 'i') ) oai = " checked";
    if( strchr(zCap, 'j') ) oaj = " checked";
    if( strchr(zCap, 'k') ) oak = " checked";
    if( strchr(zCap, 'm') ) oam = " checked";
    if( strchr(zCap, 'n') ) oan = " checked";
    if( strchr(zCap, 'o') ) oao = " checked";







|









>







261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  }

  /* Load the existing information about the user, if any
  */
  zLogin = "";
  zInfo = "";
  zCap = "";
  oaa = oac = oad = oaf = oag = oah = oai = oaj = oak = oam =
        oan = oao = oap = oaq = oar = oas = oaw = "";
  if( uid ){
    zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid);
    zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid);
    zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid);
    if( strchr(zCap, 'a') ) oaa = " checked";
    if( strchr(zCap, 'c') ) oac = " checked";
    if( strchr(zCap, 'd') ) oad = " checked";
    if( strchr(zCap, 'f') ) oaf = " checked";
    if( strchr(zCap, 'g') ) oag = " checked";
    if( strchr(zCap, 'h') ) oah = " checked";
    if( strchr(zCap, 'i') ) oai = " checked";
    if( strchr(zCap, 'j') ) oaj = " checked";
    if( strchr(zCap, 'k') ) oak = " checked";
    if( strchr(zCap, 'm') ) oam = " checked";
    if( strchr(zCap, 'n') ) oan = " checked";
    if( strchr(zCap, 'o') ) oao = " checked";
318
319
320
321
322
323
324

325
326
327
328
329
330
331
  @     <input type="checkbox" name="aa"%s(oaa)>Admin</input><br>
  @     <input type="checkbox" name="ad"%s(oad)>Delete</input><br>
  @     <input type="checkbox" name="ap"%s(oap)>Password</input><br>
  @     <input type="checkbox" name="aq"%s(oaq)>Query</input><br>
  @     <input type="checkbox" name="ai"%s(oai)>Check-In</input><br>
  @     <input type="checkbox" name="ao"%s(oao)>Check-Out</input><br>
  @     <input type="checkbox" name="ah"%s(oah)>History</input><br>

  @     <input type="checkbox" name="aj"%s(oaj)>Read Wiki</input><br>
  @     <input type="checkbox" name="af"%s(oaf)>New Wiki</input><br>
  @     <input type="checkbox" name="am"%s(oam)>Append Wiki</input><br>
  @     <input type="checkbox" name="ak"%s(oak)>Write Wiki</input><br>
  @     <input type="checkbox" name="ar"%s(oar)>Read Tkt</input><br>
  @     <input type="checkbox" name="an"%s(oan)>New Tkt</input><br>
  @     <input type="checkbox" name="ac"%s(oac)>Append Tkt</input><br>







>







326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
  @     <input type="checkbox" name="aa"%s(oaa)>Admin</input><br>
  @     <input type="checkbox" name="ad"%s(oad)>Delete</input><br>
  @     <input type="checkbox" name="ap"%s(oap)>Password</input><br>
  @     <input type="checkbox" name="aq"%s(oaq)>Query</input><br>
  @     <input type="checkbox" name="ai"%s(oai)>Check-In</input><br>
  @     <input type="checkbox" name="ao"%s(oao)>Check-Out</input><br>
  @     <input type="checkbox" name="ah"%s(oah)>History</input><br>
  @     <input type="checkbox" name="ag"%s(oag)>Clone</input><br>
  @     <input type="checkbox" name="aj"%s(oaj)>Read Wiki</input><br>
  @     <input type="checkbox" name="af"%s(oaf)>New Wiki</input><br>
  @     <input type="checkbox" name="am"%s(oam)>Append Wiki</input><br>
  @     <input type="checkbox" name="ak"%s(oak)>Write Wiki</input><br>
  @     <input type="checkbox" name="ar"%s(oar)>Read Tkt</input><br>
  @     <input type="checkbox" name="an"%s(oan)>New Tkt</input><br>
  @     <input type="checkbox" name="ac"%s(oac)>Append Tkt</input><br>
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
  @ is able to change the repository to
  @ which this program is linked.
  @ </p></li>
  @
  @ <li><p>
  @ The <b>History</b> privilege allows a user to see a timeline
  @ with hyperlinks to version information, to download ZIP archives
  @ of individual versions, and to clone the repository.
  @ </p></li>
  @
  @ <li><p>
  @ No login is required for user "<b>nobody</b>".  The capabilities
  @ of this user are available to anyone without supplying a username or
  @ password.  To disable nobody access, make sure there is no user
  @ with an ID of <b>nobody</b> or that the nobody user has no







|







380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
  @ is able to change the repository to
  @ which this program is linked.
  @ </p></li>
  @
  @ <li><p>
  @ The <b>History</b> privilege allows a user to see a timeline
  @ with hyperlinks to version information, to download ZIP archives
  @ of individual versions.
  @ </p></li>
  @
  @ <li><p>
  @ No login is required for user "<b>nobody</b>".  The capabilities
  @ of this user are available to anyone without supplying a username or
  @ password.  To disable nobody access, make sure there is no user
  @ with an ID of <b>nobody</b> or that the nobody user has no
Changes to src/wiki.c.
34
35
36
37
38
39
40


























** the url.
*/
void wiki_page(void){
  style_header("Wiki");
  @ extra=%h(g.zExtra)
  style_footer();
}

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
** the url.
*/
void wiki_page(void){
  style_header("Wiki");
  @ extra=%h(g.zExtra)
  style_footer();
}

/*
** WEBPAGE: ambiguous
**
** This is the destination for UUID hyperlinks that are ambiguous.
** Show all possible choices for the destination with links to each.
**
** The ambiguous UUID prefix is in g.zExtra
*/
void ambiguous_page(void){
  Stmt q;
  style_header("Ambiguous UUID");
  @ <p>The link <a href="%s(g.zBaseURL)/ambiguous/%T(g.zExtra)">
  @ [%h(g.zExtra)]</a> is ambiguous.  It might mean any of the following:</p>
  @ <ul>
  db_prepare(&q, "SELECT uuid, rid FROM blob WHERE uuid>=%Q AND uuid<'%qz'"
                 " ORDER BY uuid", g.zExtra, g.zExtra);
  while( db_step(&q)==SQLITE_ROW ){
    const char *zUuid = db_column_text(&q, 0);
    int rid = db_column_int(&q, 1);
    @ <li> %s(zUuid) - %d(rid)
  }
  db_finalize(&q);
  @ </ul>
  style_footer();
}
Changes to src/wikiformat.c.
522
523
524
525
526
527
528

529

530
531
532
533
534
535
536
537
538
    unsigned char iCode;     /* ATTR_* */
    char *zValue;            /* Argument to this attribute.  Might be NULL */
    char cTerm;              /* Original argument termination character */
  } aAttr[10];
};

/*

** Parse the markup in z[] into the p structure.  The content

** of z[] is modified by converting characters to lowercase
** and by inserting some "\000" characters.
*/
static void parseMarkup(ParsedMarkup *p, char *z){
  int i, c;
  char *zTag, *zValue;
  int seen = 0;

  if( z[1]=='/' ){







>
|
>
|
|







522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
    unsigned char iCode;     /* ATTR_* */
    char *zValue;            /* Argument to this attribute.  Might be NULL */
    char cTerm;              /* Original argument termination character */
  } aAttr[10];
};

/*
** z[] is an HTML markup element - something that begins with '<'.
** Parse this element into the p structure.
**
** The content of z[] might be modified by converting characters 
** to lowercase and by inserting some "\000" characters.
*/
static void parseMarkup(ParsedMarkup *p, char *z){
  int i, c;
  char *zTag, *zValue;
  int seen = 0;

  if( z[1]=='/' ){
698
699
700
701
702
703
704



705
706
707
708
709
710
711
    popStack(p);
  }
  return 1;
}

/*
** Add missing markup in preparation for writing text.



*/
static void addMissingMarkup(Renderer *p){
  /* TBD */
}

/*
** Resolve a hyperlink.  The argument is the content of the [...]







>
>
>







700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
    popStack(p);
  }
  return 1;
}

/*
** Add missing markup in preparation for writing text.
**
** "Missing" markup are things like start tags for table rows
** or table columns or paragraphs that are omitted from input.
*/
static void addMissingMarkup(Renderer *p){
  /* TBD */
}

/*
** Resolve a hyperlink.  The argument is the content of the [...]
Changes to src/xfer.c.
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
    /*    clone
    **
    ** The client knows nothing.  Tell all.
    */
    if( blob_eq(&xfer.aToken[0], "clone") ){
      int rootid;
      login_check_credentials();
      if( !g.okRead || !g.okHistory ){
        cgi_reset_content();
        @ error not\sauthorized\sto\sclone
        nErr++;
        break;
      }
      isPull = 1;
      @ push %s(db_get("server-code", "x")) %s(db_get("project-code", "x"))







|







514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
    /*    clone
    **
    ** The client knows nothing.  Tell all.
    */
    if( blob_eq(&xfer.aToken[0], "clone") ){
      int rootid;
      login_check_credentials();
      if( !g.okClone ){
        cgi_reset_content();
        @ error not\sauthorized\sto\sclone
        nErr++;
        break;
      }
      isPull = 1;
      @ push %s(db_get("server-code", "x")) %s(db_get("project-code", "x"))