Changes On Branch please-review
Not logged in

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

Changes In Branch please-review Excluding Merge-Ins

This is equivalent to a diff from 12b463ca05 to 9323045f05

2014-09-18
23:22
After deleting a newly proposed ticket or wiki page via moderation, redirect to the list of pending moderation requests. Changes to permit easier debugging of the moderation subsystem. Fix some TH1 script errors that could occur when attempting to view non-existent tickets. check-in: 636c3346d0 user: mistachkin tags: trunk
23:15
After deleting a newly proposed ticket or wiki page via moderation, redirect to the list of pending moderation requests. Closed-Leaf check-in: 9323045f05 user: mistachkin tags: please-review
23:04
Add comments for FOSSIL_FORCE_*_MODERATION environment variables. check-in: 2eafdad737 user: mistachkin tags: please-review
22:51
Merge updates from trunk. check-in: bf3f5d7947 user: mistachkin tags: please-review
22:51
Make sure the 'modreq' table is created, if necessary, in the repository database. check-in: 12b463ca05 user: mistachkin tags: trunk
2014-09-17
15:13
Fix an issue with the "uf=" query parameter on the timeline. check-in: d81c42d9ed user: drh tags: trunk

Changes to src/attach.c.
286
287
288
289
290
291
292
293
294


295
296
297
298
299
300
301
286
287
288
289
290
291
292


293
294
295
296
297
298
299
300
301







-
-
+
+







    manifest_destroy(pManifest);
    blob_init(&content, aContent, szContent);
    if( pManifest ){
      blob_compress(&content, &content);
      addCompress = 1;
    }
    needModerator =
         (zTkt!=0 && g.perm.ModTkt==0 && db_get_boolean("modreq-tkt",0)==1) ||
         (zPage!=0 && g.perm.ModWiki==0 && db_get_boolean("modreq-wiki",0)==1);
         (zTkt!=0 && ticket_need_moderation(0)) ||
         (zPage!=0 && wiki_need_moderation(0));
    rid = content_put_ex(&content, 0, 0, 0, needModerator);
    zUUID = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
    blob_zero(&manifest);
    for(i=n=0; zName[i]; i++){
      if( zName[i]=='/' || zName[i]=='\\' ) n = i;
    }
    zName += n;
Changes to src/info.c.
762
763
764
765
766
767
768






769
770






771
772
773
774
775
776
777
762
763
764
765
766
767
768
769
770
771
772
773
774


775
776
777
778
779
780
781
782
783
784
785
786
787







+
+
+
+
+
+
-
-
+
+
+
+
+
+







    @ No such object: %h(P("name"))
    style_footer();
    return;
  }
  if( g.perm.ModWiki && (zModAction = P("modaction"))!=0 ){
    if( strcmp(zModAction,"delete")==0 ){
      moderation_disapprove(rid);
      /*
      ** Next, check if the wiki page still exists; if not, we cannot
      ** redirect to it.
      */
      if( db_exists("SELECT 1 FROM tagxref JOIN tag USING(tagid)"
                    " WHERE rid=%d AND tagname LIKE 'wiki-%%'", rid) ){
      cgi_redirectf("%R/wiki?name=%T", pWiki->zWikiTitle);
      /*NOTREACHED*/
        cgi_redirectf("%R/wiki?name=%T", pWiki->zWikiTitle);
        /*NOTREACHED*/
      }else{
        cgi_redirectf("%R/modreq");
        /*NOTREACHED*/
      }
    }
    if( strcmp(zModAction,"approve")==0 ){
      moderation_approve(rid);
    }
  }
  style_header("Update of \"%h\"", pWiki->zWikiTitle);
  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
1887
1888
1889
1890
1891
1892
1893






1894
1895






1896
1897
1898
1899
1900
1901
1902
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909


1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922







+
+
+
+
+
+
-
-
+
+
+
+
+
+







  pTktChng = manifest_get(rid, CFTYPE_TICKET, 0);
  if( pTktChng==0 ) fossil_redirect_home();
  zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
  memcpy(zTktName, pTktChng->zTicketUuid, UUID_SIZE+1);
  if( g.perm.ModTkt && (zModAction = P("modaction"))!=0 ){
    if( strcmp(zModAction,"delete")==0 ){
      moderation_disapprove(rid);
      /*
      ** Next, check if the ticket still exists; if not, we cannot
      ** redirect to it.
      */
      if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'",
                    zTktName) ){
      cgi_redirectf("%R/tktview/%s", zTktName);
      /*NOTREACHED*/
        cgi_redirectf("%R/tktview/%s", zTktName);
        /*NOTREACHED*/
      }else{
        cgi_redirectf("%R/modreq");
        /*NOTREACHED*/
      }
    }
    if( strcmp(zModAction,"approve")==0 ){
      moderation_approve(rid);
    }
  }
  zTktTitle = db_table_has_column( "ticket", "title" )
      ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName)
Changes to src/json_wiki.c.
373
374
375
376
377
378
379
380

381
382
383
384
385
386
387
373
374
375
376
377
378
379

380
381
382
383
384
385
386
387







-
+







  contentLen = (int)cson_string_length_bytes(jstr);
  if(contentLen){
    blob_append(&content, cson_string_cstr(jstr),contentLen);
  }

  zMimeType = json_find_option_cstr("mimetype","mimetype","M");

  wiki_cmd_commit(zPageName, 0==rid, &content, zMimeType);
  wiki_cmd_commit(zPageName, 0==rid, &content, zMimeType, 0);
  blob_reset(&content);
  /*
    Our return value here has a race condition: if this operation
    is called concurrently for the same wiki page via two requests,
    payV could reflect the results of the other save operation.
  */
  payV = json_get_wiki_page_by_name(
Changes to src/tkt.c.
271
272
273
274
275
276
277























278
279
280
281
282
283
284
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







    db_finalize(&q);
  }
  blob_reset(&sql2);
  blob_reset(&sql3);
  fossil_free(aUsed);
  return tktid;
}

/*
** Returns non-zero if moderation is required for ticket changes and ticket
** attachments.
*/
int ticket_need_moderation(
  int localUser /* Are we being called for a local interactive user? */
){
  /*
  ** If the FOSSIL_FORCE_TICKET_MODERATION variable is set, *ALL* changes for
  ** tickets will be required to go through moderation (even those performed
  ** by the local interactive user via the command line).  This can be useful
  ** for local (or remote) testing of the moderation subsystem and its impact
  ** on the contents and status of tickets.
  */
  if( fossil_getenv("FOSSIL_FORCE_TICKET_MODERATION")!=0 ){
    return 1;
  }
  if( localUser ){
    return 0;
  }
  return g.perm.ModTkt==0 && db_get_boolean("modreq-tkt",0)==1;
}

/*
** Rebuild an entire entry in the TICKET table
*/
void ticket_rebuild_entry(const char *zTktUuid){
  char *zTag = mprintf("tkt-%s", zTktUuid);
  int tagid = tag_findid(zTag, 1);
565
566
567
568
569
570
571

572
573
574
575
576
577
578
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602







+







  int *argl
){
  char *zDate;
  const char *zUuid;
  int i;
  int nJ = 0;
  Blob tktchng, cksum;
  int needMod;

  login_verify_csrf_secret();
  if( !captcha_is_correct() ){
    @ <p class="generalError">Error: Incorrect security code.</p>
    return TH_OK;
  }
  zUuid = (const char *)pUuid;
620
621
622
623
624
625
626

627

628
629
630
631

632
633
634
635
636
637
638
639
640

641
642
643
644
645
646
647
648
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666

667

668
669
670
671
672
673
674







+

+




+








-
+
-







  blob_appendf(&tktchng, "U %F\n", login_name());
  md5sum_blob(&tktchng, &cksum);
  blob_appendf(&tktchng, "Z %b\n", &cksum);
  if( nJ==0 ){
    blob_reset(&tktchng);
    return TH_OK;
  }
  needMod = ticket_need_moderation(0);
  if( g.zPath[0]=='d' ){
    const char *zNeedMod = needMod ? "required" : "skipped";
    /* If called from /debug_tktnew or /debug_tktedit... */
    @ <font color="blue">
    @ <p>Ticket artifact that would have been submitted:</p>
    @ <blockquote><pre>%h(blob_str(&tktchng))</pre></blockquote>
    @ <blockquote><pre>Moderation would be %h(zNeedMod).</pre></blockquote>
    @ <hr /></font>
    return TH_OK;
  }else{
    if( g.thTrace ){
      Th_Trace("submit_ticket {\n<blockquote><pre>\n%h\n</pre></blockquote>\n"
               "}<br />\n",
         blob_str(&tktchng));
    }
    ticket_put(&tktchng, zUuid,
    ticket_put(&tktchng, zUuid, needMod);
               (g.perm.ModTkt==0 && db_get_boolean("modreq-tkt",0)==1));
  }
  return ticket_change(zUuid);
}


/*
** WEBPAGE: tktnew
1345
1346
1347
1348
1349
1350
1351
1352

1353
1354
1355
1356
1357
1358
1359
1360
1371
1372
1373
1374
1375
1376
1377

1378
1379
1380
1381
1382
1383
1384
1385
1386







-
+








                       aField[i].zName, strlen(zValue), zValue);
        }
      }
      blob_appendf(&tktchng, "K %s\n", zTktUuid);
      blob_appendf(&tktchng, "U %F\n", zUser);
      md5sum_blob(&tktchng, &cksum);
      blob_appendf(&tktchng, "Z %b\n", &cksum);
      if( ticket_put(&tktchng, zTktUuid, 0) ){
      if( ticket_put(&tktchng, zTktUuid, ticket_need_moderation(1)) ){
        fossil_fatal("%s\n", g.zErrMsg);
      }else{
        fossil_print("ticket %s succeeded for %s\n",
             (eCmd==set?"set":"add"),zTktUuid);
      }
    }
  }
}
Changes to src/tktsetup.c.
433
434
435
436
437
438
439

440
441
442






443

444





445
446
447
448
449
450
451
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







+
-
-
-
+
+
+
+
+
+

+
-
+
+
+
+
+







  );
}

static const char zDefaultView[] =
@ <table cellpadding="5">
@ <tr><td class="tktDspLabel">Ticket&nbsp;UUID:</td>
@ <th1>
@ if {[info exists tkt_uuid]} {
@ if {[hascap s]} {
@   html "<td class='tktDspValue' colspan='3'>$tkt_uuid "
@   html "($tkt_id)</td></tr>\n"
@   if {[hascap s]} {
@     html "<td class='tktDspValue' colspan='3'>$tkt_uuid "
@     html "($tkt_id)</td></tr>\n"
@   } else {
@     html "<td class='tktDspValue' colspan='3'>$tkt_uuid</td></tr>\n"
@   }
@ } else {
@   if {[hascap s]} {
@   html "<td class='tktDspValue' colspan='3'>$tkt_uuid</td></tr>\n"
@     html "<td class='tktDspValue' colspan='3'>Deleted "
@     html "(0)</td></tr>\n"
@   } else {
@     html "<td class='tktDspValue' colspan='3'>Deleted</td></tr>\n"
@   }
@ }
@ </th1>
@ <tr><td class="tktDspLabel">Title:</td>
@ <td class="tktDspValue" colspan="3">
@ $<title>
@ </td></tr>
@ <tr><td class="tktDspLabel">Status:</td><td class="tktDspValue">
463
464
465
466
467
468
469


470



471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493












494
495
496
497
498
499
500
472
473
474
475
476
477
478
479
480

481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496










497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515







+
+
-
+
+
+













-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+







@ <tr><td class="tktDspLabel">Subsystem:</td><td class="tktDspValue">
@ $<subsystem>
@ </td>
@ <td class="tktDspLabel">Resolution:</td><td class="tktDspValue">
@ $<resolution>
@ </td></tr>
@ <tr><td class="tktDspLabel">Last&nbsp;Modified:</td><td class="tktDspValue">
@ <th1>
@ if {[info exists tkt_datetime]} {
@ $<tkt_datetime>
@   html $tkt_datetime
@ }
@ </th1>
@ </td>
@ <th1>enable_output [hascap e]</th1>
@   <td class="tktDspLabel">Contact:</td><td class="tktDspValue">
@   $<private_contact>
@   </td>
@ <th1>enable_output 1</th1>
@ </tr>
@ <tr><td class="tktDspLabel">Version&nbsp;Found&nbsp;In:</td>
@ <td colspan="3" valign="top" class="tktDspValue">
@ $<foundin>
@ </td></tr>
@
@ <th1>
@ if {[info exists comment] && [string length $comment]>10} {
@   html {
@     <tr><td class="tktDspLabel">Description:</td></tr>
@     <tr><td colspan="5" class="tktDspValue">
@   }
@   if {[info exists plaintext]} {
@     set r [randhex]
@     wiki "<verbatim-$r links>\n$comment\n</verbatim-$r>"
@   } else {
@     wiki $comment
@ if {[info exists comment]} {
@   if {[string length $comment]>10} {
@     html {
@       <tr><td class="tktDspLabel">Description:</td></tr>
@       <tr><td colspan="5" class="tktDspValue">
@     }
@     if {[info exists plaintext]} {
@       set r [randhex]
@       wiki "<verbatim-$r links>\n$comment\n</verbatim-$r>"
@     } else {
@       wiki $comment
@     }
@   }
@ }
@ set seenRow 0
@ set alwaysPlaintext [info exists plaintext]
@ query {SELECT datetime(tkt_mtime) AS xdate, login AS xlogin,
@               mimetype as xmimetype, icomment AS xcomment,
@               username AS xusername
Changes to src/wiki.c.
154
155
156
157
158
159
160






















161
162
163
164
165
166
167
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  }else{
    @ <pre>
    @ %h(blob_str(pWiki))
    @ </pre>
  }
}

/*
** Returns non-zero if moderation is required for wiki changes and wiki
** attachments.
*/
int wiki_need_moderation(
  int localUser /* Are we being called for a local interactive user? */
){
  /*
  ** If the FOSSIL_FORCE_WIKI_MODERATION variable is set, *ALL* changes for
  ** wiki pages will be required to go through moderation (even those performed
  ** by the local interactive user via the command line).  This can be useful
  ** for local (or remote) testing of the moderation subsystem and its impact
  ** on the contents and status of wiki pages.
  */
  if( fossil_getenv("FOSSIL_FORCE_WIKI_MODERATION")!=0 ){
    return 1;
  }
  if( localUser ){
    return 0;
  }
  return g.perm.ModWiki==0 && db_get_boolean("modreq-wiki",0)==1;
}

/*
** WEBPAGE: wiki
** URL: /wiki?name=PAGENAME
*/
void wiki_page(void){
  char *zTag;
280
281
282
283
284
285
286
287

288
289

290
291
292
293
294
295
296
302
303
304
305
306
307
308

309
310

311
312
313
314
315
316
317
318







-
+

-
+







  manifest_destroy(pWiki);
  style_footer();
}

/*
** Write a wiki artifact into the repository
*/
static void wiki_put(Blob *pWiki, int parent){
static void wiki_put(Blob *pWiki, int parent, int needMod){
  int nrid;
  if( g.perm.ModWiki || db_get_boolean("modreq-wiki",0)==0 ){
  if( !needMod ){
    nrid = content_put_ex(pWiki, 0, 0, 0, 0);
    if( parent) content_deltify(parent, nrid, 0);
  }else{
    nrid = content_put_ex(pWiki, 0, 0, 0, 1);
    moderation_table_create();
    db_multi_exec("INSERT INTO modreq(objid) VALUES(%d)", nrid);
  }
425
426
427
428
429
430
431
432

433
434
435
436
437
438
439
447
448
449
450
451
452
453

454
455
456
457
458
459
460
461







-
+







      if( !login_is_nobody() ){
        blob_appendf(&wiki, "U %F\n", login_name());
      }
      blob_appendf(&wiki, "W %d\n%s\n", strlen(zBody), zBody);
      md5sum_blob(&wiki, &cksum);
      blob_appendf(&wiki, "Z %b\n", &cksum);
      blob_reset(&cksum);
      wiki_put(&wiki, 0);
      wiki_put(&wiki, 0, wiki_need_moderation(0));
    }
    db_end_transaction(0);
    cgi_redirectf("wiki?name=%T", zPageName);
  }
  if( P("cancel")!=0 ){
    cgi_redirectf("wiki?name=%T", zPageName);
    return;
656
657
658
659
660
661
662
663

664
665
666
667
668
669
670
678
679
680
681
682
683
684

685
686
687
688
689
690
691
692







-
+







        blob_appendf(&wiki, "U %F\n", login_name());
      }
      appendRemark(&body, zMimetype);
      blob_appendf(&wiki, "W %d\n%s\n", blob_size(&body), blob_str(&body));
      md5sum_blob(&wiki, &cksum);
      blob_appendf(&wiki, "Z %b\n", &cksum);
      blob_reset(&cksum);
      wiki_put(&wiki, rid);
      wiki_put(&wiki, rid, wiki_need_moderation(0));
      db_end_transaction(0);
    }
    cgi_redirectf("wiki?name=%T", zPageName);
  }
  if( P("cancel")!=0 ){
    cgi_redirectf("wiki?name=%T", zPageName);
    return;
959
960
961
962
963
964
965
966

967
968
969
970
971
972
973
981
982
983
984
985
986
987

988
989
990
991
992
993
994
995







-
+







** The content of the new page is given by the blob pContent.
**
** zMimeType specifies the N-card for the wiki page. If it is 0,
** empty, or "text/x-fossil-wiki" (the default format) then it is
** ignored.
*/
int wiki_cmd_commit(const char *zPageName, int isNew, Blob *pContent,
                    const char *zMimeType){
                    const char *zMimeType, int localUser){
  Blob wiki;              /* Wiki page content */
  Blob cksum;             /* wiki checksum */
  int rid;                /* artifact ID of parent page */
  char *zDate;            /* timestamp */
  char *zUuid;            /* uuid for rid */

  rid = db_int(0,
1009
1010
1011
1012
1013
1014
1015
1016

1017
1018
1019
1020
1021
1022
1023
1031
1032
1033
1034
1035
1036
1037

1038
1039
1040
1041
1042
1043
1044
1045







-
+







  }
  blob_appendf( &wiki, "W %d\n%s\n", blob_size(pContent),
                blob_str(pContent) );
  md5sum_blob(&wiki, &cksum);
  blob_appendf(&wiki, "Z %b\n", &cksum);
  blob_reset(&cksum);
  db_begin_transaction();
  wiki_put(&wiki, 0);
  wiki_put(&wiki, 0, wiki_need_moderation(localUser));
  db_end_transaction(0);
  return 1;
}

/*
** COMMAND: wiki*
**
1117
1118
1119
1120
1121
1122
1123
1124

1125
1126
1127

1128
1129
1130
1131
1132
1133
1134
1139
1140
1141
1142
1143
1144
1145

1146
1147
1148

1149
1150
1151
1152
1153
1154
1155
1156







-
+


-
+







                   );
      if(rid>0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0
         && (pWiki->zMimetype && *pWiki->zMimetype)){
        zMimeType = pWiki->zMimetype;
      }
    }
    if( g.argv[2][1]=='r' ){
      wiki_cmd_commit(zPageName, 1, &content, zMimeType);
      wiki_cmd_commit(zPageName, 1, &content, zMimeType, 1);
      fossil_print("Created new wiki page %s.\n", zPageName);
    }else{
      wiki_cmd_commit(zPageName, 0, &content, zMimeType);
      wiki_cmd_commit(zPageName, 0, &content, zMimeType, 1);
      fossil_print("Updated wiki page %s.\n", zPageName);
    }
    manifest_destroy(pWiki);
    blob_reset(&content);
  }else if( strncmp(g.argv[2],"delete",n)==0 ){
    if( g.argc!=5 ){
      usage("delete PAGENAME");