Fossil

Check-in [88a69253cd]
Login

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

Overview
Comment:All /fileedit/ajax requests now do a CSRF check and fail with 403 if CSRF seems likely.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | fileedit-ajaxify
Files: files | file ages | folders
SHA3-256: 88a69253cd7aa0d8000715fdfa2421eb9bb036c3cacd945ed9015adf089a1ee9
User & Date: stephan 2020-05-18 03:24:51.702
Context
2020-05-18
03:41
Replaced style.css?page=xxx with style.css/page, like the [style-css-revamp] branch does. ... (check-in: bc40707425 user: stephan tags: fileedit-ajaxify)
03:24
All /fileedit/ajax requests now do a CSRF check and fail with 403 if CSRF seems likely. ... (check-in: 88a69253cd user: stephan tags: fileedit-ajaxify)
2020-05-17
17:07
Merged in trunk. ... (check-in: b9b746e50f user: stephan tags: fileedit-ajaxify)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/fileedit.c.
1069
1070
1071
1072
1073
1074
1075



1076
1077
1078
1079
1080
1081
1082


1083
1084
1085
1086
1087
1088
1089
1090
}

/*
** Performs bootstrapping common to the /fileedit_xyz AJAX routes.
** Returns 0 if bootstrapping fails (wrong permissions), in which
** case it has reported the error and the route should immediately
** return. Returns true on success.



*/
static int fileedit_ajax_boostrap(void){
  login_check_credentials();
  if( !g.perm.Write ){
    fileedit_ajax_error(403,"Write permissions required.");
    return 0;
  }



  return 1;
}
/*
** Returns true if the current user is allowed to edit the given
** filename, as determined by fileedit_is_editable(), else false,
** in which case it queues up an error response and the caller
** must return immediately.







>
>
>

|




|
>
>
|







1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
}

/*
** Performs bootstrapping common to the /fileedit_xyz AJAX routes.
** Returns 0 if bootstrapping fails (wrong permissions), in which
** case it has reported the error and the route should immediately
** return. Returns true on success.
**
** Must be passed true if the request being set up requires POST,
** else false.
*/
static int fileedit_ajax_boostrap(int requirePost){
  login_check_credentials();
  if( !g.perm.Write ){
    fileedit_ajax_error(403,"Write permissions required.");
    return 0;
  }else if(0==cgi_csrf_safe(requirePost)){
    fileedit_ajax_error(403, "CSRF violation?");
    return 0;
  }
  return 1;
}
/*
** Returns true if the current user is allowed to edit the given
** filename, as determined by fileedit_is_editable(), else false,
** in which case it queues up an error response and the caller
** must return immediately.
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
  const char * zFilename = 0;
  const char * zRev = 0;
  int vid, frid;
  Blob content = empty_blob;
  const char * zMime;

  fileedit_get_fnci_args( &zFilename, &zRev );
  if(!fileedit_ajax_boostrap()
     || !fileedit_ajax_setup_filerev(zRev, 0, &vid,
                                     zFilename, &frid)){
    return;
  }
  zMime = mimetype_from_name(zFilename);
  content_get(frid, &content);
  if(0==zMime){







|







1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
  const char * zFilename = 0;
  const char * zRev = 0;
  int vid, frid;
  Blob content = empty_blob;
  const char * zMime;

  fileedit_get_fnci_args( &zFilename, &zRev );
  if(!fileedit_ajax_boostrap(0)
     || !fileedit_ajax_setup_filerev(zRev, 0, &vid,
                                     zFilename, &frid)){
    return;
  }
  zMime = mimetype_from_name(zFilename);
  content_get(frid, &content);
  if(0==zMime){
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
  const char * zContent = P("content");
  int renderMode = atoi(PD("render_mode","0"));
  int ln = atoi(PD("ln","0"));
  int iframeHeight = atoi(PD("iframe_height","40"));
  Blob content = empty_blob;
  const char * zRenderMode = 0;
  fileedit_get_fnci_args( &zFilename, 0 );
  if(!fileedit_ajax_boostrap()
     || !fileedit_ajax_check_filename(zFilename)){
    return;
  }
  cgi_set_content_type("text/html");
  blob_init(&content, zContent, -1);
  fileedit_render_preview(&content, zFilename,
                          ln ? FE_PREVIEW_LINE_NUMBERS : 0,







|







1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
  const char * zContent = P("content");
  int renderMode = atoi(PD("render_mode","0"));
  int ln = atoi(PD("ln","0"));
  int iframeHeight = atoi(PD("iframe_height","40"));
  Blob content = empty_blob;
  const char * zRenderMode = 0;
  fileedit_get_fnci_args( &zFilename, 0 );
  if(!fileedit_ajax_boostrap(1)
     || !fileedit_ajax_check_filename(zFilename)){
    return;
  }
  cgi_set_content_type("text/html");
  blob_init(&content, zContent, -1);
  fileedit_render_preview(&content, zFilename,
                          ln ? FE_PREVIEW_LINE_NUMBERS : 0,
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
  if(2==iFlag){
    diffFlags |= DIFF_IGNORE_ALLWS;
  }else if(1==iFlag){
    diffFlags |= DIFF_IGNORE_EOLWS;
  }
  diffFlags |= DIFF_STRIP_EOLCR;
  fileedit_get_fnci_args( &zFilename, &zRev );
  if(!fileedit_ajax_boostrap()
     || !fileedit_ajax_setup_filerev(zRev, &zRevUuid, &vid,
                                     zFilename, &frid)){
    return;
  }
  if(!zContent){
    zContent = "";
  }







|







1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
  if(2==iFlag){
    diffFlags |= DIFF_IGNORE_ALLWS;
  }else if(1==iFlag){
    diffFlags |= DIFF_IGNORE_EOLWS;
  }
  diffFlags |= DIFF_STRIP_EOLCR;
  fileedit_get_fnci_args( &zFilename, &zRev );
  if(!fileedit_ajax_boostrap(1)
     || !fileedit_ajax_setup_filerev(zRev, &zRevUuid, &vid,
                                     zFilename, &frid)){
    return;
  }
  if(!zContent){
    zContent = "";
  }
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
*/
static void fileedit_ajax_filelist(void){
  const char * zCi = PD("checkin",P("ci"));
  Blob sql = empty_blob;
  Stmt q = empty_Stmt;
  int i = 0;

  if(!fileedit_ajax_boostrap()){
    return;
  }
  cgi_set_content_type("application/json");
  if(zCi!=0){
    char * zCiFull = 0;
    int vid = 0;
    if(0==fileedit_ajax_setup_filerev(zCi, &zCiFull, &vid, 0, 0)){







|







1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
*/
static void fileedit_ajax_filelist(void){
  const char * zCi = PD("checkin",P("ci"));
  Blob sql = empty_blob;
  Stmt q = empty_Stmt;
  int i = 0;

  if(!fileedit_ajax_boostrap(0)){
    return;
  }
  cgi_set_content_type("application/json");
  if(zCi!=0){
    char * zCiFull = 0;
    int vid = 0;
    if(0==fileedit_ajax_setup_filerev(zCi, &zCiFull, &vid, 0, 0)){
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
  CheckinMiniInfo cimi;       /* checkin state */
  int rc;                     /* generic result code */
  int newVid = 0;             /* new version's RID */
  char * zNewUuid = 0;        /* newVid's UUID */
  char const * zMimetype;
  char * zBranch = 0;

  if(!fileedit_ajax_boostrap()){
    return;
  }
  db_begin_transaction();
  CheckinMiniInfo_init(&cimi);
  rc = fileedit_setup_cimi_from_p(&cimi, &err, 0);
  if(0!=rc){
    fileedit_ajax_error(rc,"%b",&err);







|







1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
  CheckinMiniInfo cimi;       /* checkin state */
  int rc;                     /* generic result code */
  int newVid = 0;             /* new version's RID */
  char * zNewUuid = 0;        /* newVid's UUID */
  char const * zMimetype;
  char * zBranch = 0;

  if(!fileedit_ajax_boostrap(1)){
    return;
  }
  db_begin_transaction();
  CheckinMiniInfo_init(&cimi);
  rc = fileedit_setup_cimi_from_p(&cimi, &err, 0);
  if(0!=rc){
    fileedit_ajax_error(rc,"%b",&err);
Changes to src/style.c.
1588
1589
1590
1591
1592
1593
1594








1595
1596
1597
1598
1599
1600
1601
    ** including a trailing slash. */
       "window.fossil.rootPath = %!j+'/';\n",
       get_version(), g.zTop);
    /* fossil.config = {...various config-level options...} */
    CX("window.fossil.config = {"
       "hashDigits: %d, hashDigitsUrl: %d"
       "};\n", hash_digits(0), hash_digits(1));








    /*
    ** fossil.page holds info about the current page. This is also
    ** where the current page "should" store any of its own
    ** page-specific state, and it is reserved for that purpose.
    */
    CX("window.fossil.page = {"
       "name:\"%T\""







>
>
>
>
>
>
>
>







1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
    ** including a trailing slash. */
       "window.fossil.rootPath = %!j+'/';\n",
       get_version(), g.zTop);
    /* fossil.config = {...various config-level options...} */
    CX("window.fossil.config = {"
       "hashDigits: %d, hashDigitsUrl: %d"
       "};\n", hash_digits(0), hash_digits(1));
#if 0
    /* Is it safe to emit the CSRF token here? Some pages add it
    ** as a hidden form field. */
    if(g.zCsrfToken[0]!=0){
      CX("window.fossil.csrfToken = %!j;\n",
         g.zCsrfToken);
    }
#endif
    /*
    ** fossil.page holds info about the current page. This is also
    ** where the current page "should" store any of its own
    ** page-specific state, and it is reserved for that purpose.
    */
    CX("window.fossil.page = {"
       "name:\"%T\""