| | @@ -903,11 +903,11 @@ |
| 903 | 903 | |
| 904 | 904 | enum fileedit_render_preview_flags { |
| 905 | 905 | FE_PREVIEW_LINE_NUMBERS = 1 |
| 906 | 906 | }; |
| 907 | 907 | enum fileedit_render_modes { |
| 908 | | -/* GUESS must be 0. All others have specified values. */ |
| 908 | +/* GUESS must be 0. All others have unspecified values. */ |
| 909 | 909 | FE_RENDER_GUESS = 0, |
| 910 | 910 | FE_RENDER_PLAIN_TEXT, |
| 911 | 911 | FE_RENDER_HTML, |
| 912 | 912 | FE_RENDER_WIKI |
| 913 | 913 | }; |
| | @@ -1015,11 +1015,11 @@ |
| 1015 | 1015 | db_finalize(&stmt); |
| 1016 | 1016 | return zFileUuid; |
| 1017 | 1017 | } |
| 1018 | 1018 | |
| 1019 | 1019 | /* |
| 1020 | | -** Helper for /filepage_xyz routes. Clears the CGI content buffer, |
| 1020 | +** Helper for /fileedit_xyz routes. Clears the CGI content buffer, |
| 1021 | 1021 | ** sets an error status code, and queues up a JSON response in the |
| 1022 | 1022 | ** form of an object: |
| 1023 | 1023 | ** |
| 1024 | 1024 | ** {error: formatted message} |
| 1025 | 1025 | ** |
| | @@ -1135,10 +1135,11 @@ |
| 1135 | 1135 | const char * zFilename = PD("file",P("name")); |
| 1136 | 1136 | const char * zRev = P("r"); |
| 1137 | 1137 | int vid, frid; |
| 1138 | 1138 | Blob content = empty_blob; |
| 1139 | 1139 | const char * zMime; |
| 1140 | + |
| 1140 | 1141 | if(!fileedit_ajax_boostrap() |
| 1141 | 1142 | || !fileedit_ajax_setup_filerev(zRev, 0, &vid, |
| 1142 | 1143 | zFilename, &frid)){ |
| 1143 | 1144 | return; |
| 1144 | 1145 | } |
| | @@ -1149,15 +1150,24 @@ |
| 1149 | 1150 | } |
| 1150 | 1151 | |
| 1151 | 1152 | /* |
| 1152 | 1153 | ** WEBPAGE: fileedit_preview |
| 1153 | 1154 | ** |
| 1154 | | -** Query parameters: |
| 1155 | +** Required query parameters: |
| 1155 | 1156 | ** |
| 1156 | 1157 | ** file=FILENAME |
| 1157 | | -** render_mode=integer (FE_RENDER_xxx) (default=FE_RENDER_GUESS) |
| 1158 | 1158 | ** content=text |
| 1159 | +** |
| 1160 | +** Optional query parameters: |
| 1161 | +** |
| 1162 | +** render_mode=integer (FE_RENDER_xxx) (default=FE_RENDER_GUESS) |
| 1163 | +** |
| 1164 | +** ln=0 or 1 to disable/enable line number mode in |
| 1165 | +** FE_RENDER_PLAIN_TEXT mode. |
| 1166 | +** |
| 1167 | +** iframe_height=integer (default=40) Height, in EMs of HTML preview |
| 1168 | +** iframe. |
| 1159 | 1169 | ** |
| 1160 | 1170 | ** User must have Write access to use this page. |
| 1161 | 1171 | ** |
| 1162 | 1172 | ** Responds with the HTML content of the preview. On error it produces |
| 1163 | 1173 | ** a JSON response as documented for fileedit_ajax_error(). |
| | @@ -1167,10 +1177,11 @@ |
| 1167 | 1177 | const char * zContent = P("content"); |
| 1168 | 1178 | int renderMode = atoi(PD("render_mode","0")); |
| 1169 | 1179 | int ln = atoi(PD("ln","0")); |
| 1170 | 1180 | int iframeHeight = atoi(PD("iframe_height","40")); |
| 1171 | 1181 | Blob content = empty_blob; |
| 1182 | + |
| 1172 | 1183 | if(!fileedit_ajax_boostrap() |
| 1173 | 1184 | || !fileedit_ajax_check_filename(zFilename)){ |
| 1174 | 1185 | return; |
| 1175 | 1186 | } |
| 1176 | 1187 | cgi_set_content_type("text/html"); |
| | @@ -1181,15 +1192,20 @@ |
| 1181 | 1192 | } |
| 1182 | 1193 | |
| 1183 | 1194 | /* |
| 1184 | 1195 | ** WEBPAGE: fileedit_diff |
| 1185 | 1196 | ** |
| 1197 | +** Required query parameters: |
| 1198 | +** |
| 1186 | 1199 | ** file=FILENAME |
| 1187 | | -** sbs=integer (1=side-by-side or 0=unified) |
| 1188 | 1200 | ** content=text |
| 1189 | 1201 | ** r=checkin version |
| 1190 | 1202 | ** |
| 1203 | +** Optional parameters: |
| 1204 | +** |
| 1205 | +** sbs=integer (1=side-by-side or 0=unified, default=0) |
| 1206 | +** |
| 1191 | 1207 | ** User must have Write access to use this page. |
| 1192 | 1208 | ** |
| 1193 | 1209 | ** Responds with the HTML content of the diff. On error it produces a |
| 1194 | 1210 | ** JSON response as documented for fileedit_ajax_error(). |
| 1195 | 1211 | */ |
| | @@ -1205,10 +1221,11 @@ |
| 1205 | 1221 | const char * zContent = P("content"); |
| 1206 | 1222 | char * zRevUuid = 0; |
| 1207 | 1223 | int isSbs = atoi(PD("sbs","0")); |
| 1208 | 1224 | int vid, frid; |
| 1209 | 1225 | Blob content = empty_blob; |
| 1226 | + |
| 1210 | 1227 | if(!fileedit_ajax_boostrap() |
| 1211 | 1228 | || !fileedit_ajax_setup_filerev(zRev, &zRevUuid, &vid, |
| 1212 | 1229 | zFilename, &frid)){ |
| 1213 | 1230 | return; |
| 1214 | 1231 | } |
| | @@ -1221,25 +1238,27 @@ |
| 1221 | 1238 | fossil_free(zRevUuid); |
| 1222 | 1239 | blob_reset(&content); |
| 1223 | 1240 | } |
| 1224 | 1241 | |
| 1225 | 1242 | /* |
| 1226 | | -** Sets up and validates must, but not all, of p's checkin-related |
| 1243 | +** Sets up and validates most, but not all, of p's checkin-related |
| 1227 | 1244 | ** state from the CGI environment. Returns 0 on success or a suggested |
| 1228 | 1245 | ** HTTP result code on error, in which case a message will have been |
| 1229 | 1246 | ** written to pErr. |
| 1230 | 1247 | ** |
| 1231 | 1248 | ** It always fails if it cannot completely resolve the 'file' and 'r' |
| 1232 | 1249 | ** parameters, including verifying that the refer to a real |
| 1233 | | -** file/version combination. Most others are optional. |
| 1250 | +** file/version combination and editable by the current user. All |
| 1251 | +** others are optional (at this level, anyway, but upstream code might |
| 1252 | +** require them). |
| 1234 | 1253 | ** |
| 1235 | 1254 | ** Intended to be used only by /filepage and /filepage_commit. |
| 1236 | 1255 | */ |
| 1237 | 1256 | static int fileedit_setup_cimi_from_p(CheckinMiniInfo * p, Blob * pErr){ |
| 1238 | | - char * zFileUuid = 0; |
| 1239 | | - const char * zFlag; |
| 1240 | | - int rc = 0, vid = 0, frid = 0; |
| 1257 | + char * zFileUuid = 0; /* UUID of file content */ |
| 1258 | + const char * zFlag; /* generic flag */ |
| 1259 | + int rc = 0, vid = 0, frid = 0; /* result code, checkin/file rids */ |
| 1241 | 1260 | |
| 1242 | 1261 | #define fail(EXPR) blob_appendf EXPR; goto end_fail |
| 1243 | 1262 | zFlag = PD("file",P("name")); |
| 1244 | 1263 | if(zFlag==0 || !*zFlag){ |
| 1245 | 1264 | rc = 400; |
| | @@ -1301,11 +1320,10 @@ |
| 1301 | 1320 | zFlag = P("comment_mimetype"); |
| 1302 | 1321 | if(zFlag){ |
| 1303 | 1322 | p->zCommentMimetype = mprintf("%s",zFlag); |
| 1304 | 1323 | zFlag = 0; |
| 1305 | 1324 | } |
| 1306 | | - p->zUser = mprintf("%s",g.zLogin); |
| 1307 | 1325 | #define p_int(K) atoi(PD(K,"0")) |
| 1308 | 1326 | if(p_int("dry_run")!=0){ |
| 1309 | 1327 | p->flags |= CIMINI_DRY_RUN; |
| 1310 | 1328 | } |
| 1311 | 1329 | if(p_int("allow_fork")!=0){ |
| | @@ -1323,23 +1341,21 @@ |
| 1323 | 1341 | if(p_int("prefer_delta")!=0){ |
| 1324 | 1342 | p->flags |= CIMINI_PREFER_DELTA; |
| 1325 | 1343 | } |
| 1326 | 1344 | |
| 1327 | 1345 | /* EOL conversion policy... */ |
| 1328 | | - { |
| 1329 | | - const int eolMode = p_int("eol"); |
| 1330 | | - switch(eolMode){ |
| 1331 | | - case 1: p->flags |= CIMINI_CONVERT_EOL_UNIX; break; |
| 1332 | | - case 2: p->flags |= CIMINI_CONVERT_EOL_WINDOWS; break; |
| 1333 | | - default: p->flags |= CIMINI_CONVERT_EOL_INHERIT; break; |
| 1334 | | - } |
| 1346 | + switch(p_int("eol")){ |
| 1347 | + case 1: p->flags |= CIMINI_CONVERT_EOL_UNIX; break; |
| 1348 | + case 2: p->flags |= CIMINI_CONVERT_EOL_WINDOWS; break; |
| 1349 | + default: p->flags |= CIMINI_CONVERT_EOL_INHERIT; break; |
| 1335 | 1350 | } |
| 1336 | 1351 | #undef p_int |
| 1337 | 1352 | /* |
| 1338 | 1353 | ** TODO?: date-override date selection field. Maybe use |
| 1339 | 1354 | ** an input[type=datetime-local]. |
| 1340 | 1355 | */ |
| 1356 | + p->zUser = mprintf("%s",g.zLogin); |
| 1341 | 1357 | return 0; |
| 1342 | 1358 | end_fail: |
| 1343 | 1359 | #undef fail |
| 1344 | 1360 | fossil_free(zFileUuid); |
| 1345 | 1361 | return rc ? rc : 500; |
| | @@ -1363,25 +1379,26 @@ |
| 1363 | 1379 | ** |
| 1364 | 1380 | ** User must have Write access to use this page. |
| 1365 | 1381 | ** |
| 1366 | 1382 | ** Responds with JSON: |
| 1367 | 1383 | ** |
| 1368 | | -** {uuid: newUUID, |
| 1384 | +** { |
| 1385 | +** uuid: newUUID, |
| 1369 | 1386 | ** manifest: text of manifest, |
| 1370 | 1387 | ** dryRun: bool |
| 1371 | 1388 | ** } |
| 1372 | 1389 | ** |
| 1373 | 1390 | ** On error it produces a JSON response as documented for |
| 1374 | 1391 | ** fileedit_ajax_error(). |
| 1375 | 1392 | */ |
| 1376 | 1393 | void fileedit_ajax_commit(){ |
| 1377 | | - int newVid = 0; |
| 1378 | | - Blob err = empty_blob; |
| 1379 | | - Blob manifest = empty_blob; |
| 1380 | | - CheckinMiniInfo cimi; |
| 1381 | | - int rc; |
| 1382 | | - char * zNewUuid = 0; |
| 1394 | + Blob err = empty_blob; /* Error messages */ |
| 1395 | + Blob manifest = empty_blob; /* raw new manifest */ |
| 1396 | + CheckinMiniInfo cimi; /* checkin state */ |
| 1397 | + int rc; /* generic result code */ |
| 1398 | + int newVid = 0; /* new version's RID */ |
| 1399 | + char * zNewUuid = 0; /* newVid's UUID */ |
| 1383 | 1400 | |
| 1384 | 1401 | if(!fileedit_ajax_boostrap()){ |
| 1385 | 1402 | goto end_cleanup; |
| 1386 | 1403 | } |
| 1387 | 1404 | db_begin_transaction(); |
| | @@ -1408,11 +1425,12 @@ |
| 1408 | 1425 | CX("\"uuid\":\"%j\",", zNewUuid); |
| 1409 | 1426 | CX("\"dryRun\": %s,", |
| 1410 | 1427 | (CIMINI_DRY_RUN & cimi.flags) ? "true" : "false"); |
| 1411 | 1428 | CX("\"manifest\": \"%j\"", blob_str(&manifest)); |
| 1412 | 1429 | CX("}"); |
| 1413 | | - db_end_transaction(0); |
| 1430 | + db_end_transaction(0/*noting that dry-run mode will have already |
| 1431 | + ** set this to rollback mode. */); |
| 1414 | 1432 | end_cleanup: |
| 1415 | 1433 | fossil_free(zNewUuid); |
| 1416 | 1434 | blob_reset(&err); |
| 1417 | 1435 | blob_reset(&manifest); |
| 1418 | 1436 | CheckinMiniInfo_cleanup(&cimi); |
| | @@ -1453,19 +1471,17 @@ |
| 1453 | 1471 | CheckinMiniInfo cimi; /* Checkin state */ |
| 1454 | 1472 | int previewHtmlHeight = 0; /* iframe height (EMs) */ |
| 1455 | 1473 | int previewRenderMode = FE_RENDER_GUESS; /* preview mode */ |
| 1456 | 1474 | char * zFileUuid = 0; /* File content UUID */ |
| 1457 | 1475 | Blob err = empty_blob; /* Error report */ |
| 1458 | | - Blob submitResult = empty_blob; /* Error report */ |
| 1459 | 1476 | Blob endScript = empty_blob; /* Script code to run at the |
| 1460 | 1477 | end. This content will be |
| 1461 | 1478 | combined into a single JS |
| 1462 | 1479 | function call, thus each |
| 1463 | 1480 | entry must end with a |
| 1464 | 1481 | semicolon. */ |
| 1465 | 1482 | Stmt stmt = empty_Stmt; |
| 1466 | | -#define fail(EXPR) blob_appendf EXPR; goto end_footer |
| 1467 | 1483 | |
| 1468 | 1484 | login_check_credentials(); |
| 1469 | 1485 | if( !g.perm.Write ){ |
| 1470 | 1486 | login_needed(g.anon.Write); |
| 1471 | 1487 | return; |
| | @@ -1472,40 +1488,31 @@ |
| 1472 | 1488 | } |
| 1473 | 1489 | db_begin_transaction(); |
| 1474 | 1490 | CheckinMiniInfo_init(&cimi); |
| 1475 | 1491 | |
| 1476 | 1492 | style_header("File Editor"); |
| 1477 | | - /* As of this point, don't use return or fossil_fatal(), use |
| 1478 | | - ** fail((&err,...)) instead so that we can be sure to do any |
| 1479 | | - ** cleanup and end the transaction cleanly. |
| 1493 | + /* As of this point, don't use return or fossil_fatal(). Write any |
| 1494 | + ** error in (&err) and goto end_footer instead so that we can be |
| 1495 | + ** sure to do any cleanup and end the transaction cleanly. |
| 1480 | 1496 | */ |
| 1481 | 1497 | if(fileedit_setup_cimi_from_p(&cimi, &err)!=0){ |
| 1482 | 1498 | goto end_footer; |
| 1483 | 1499 | } |
| 1484 | 1500 | zFilename = cimi.zFilename; |
| 1485 | 1501 | zRev = cimi.zParentUuid; |
| 1486 | | - |
| 1487 | 1502 | assert(zRev); |
| 1488 | 1503 | assert(zFilename); |
| 1489 | 1504 | zFileMime = mimetype_from_name(cimi.zFilename); |
| 1490 | 1505 | |
| 1491 | 1506 | /******************************************************************** |
| 1492 | 1507 | ** All errors which "could" have happened up to this point are of a |
| 1493 | 1508 | ** degree which keep us from rendering the rest of the page, and |
| 1494 | | - ** thus fail() has already skipped to the end of the page to render |
| 1495 | | - ** the errors. Any up-coming errors, barring malloc failure or |
| 1496 | | - ** similar, are not "that" fatal. We can/should continue rendering |
| 1497 | | - ** the page, then output the error message at the end. |
| 1498 | | - ** |
| 1499 | | - ** Because we cannot intercept the output of the PREVIEW and DIFF |
| 1500 | | - ** rendering, we have to delay the "real work" for those modes until |
| 1501 | | - ** after the rest of the page has been rendered. In the case of |
| 1502 | | - ** SAVE, we can capture all of the output, and thus can perform that |
| 1503 | | - ** work before rendering, which is important so that we have the |
| 1504 | | - ** proper version information when rendering the rest of the page. |
| 1509 | + ** thus have already caused us to skipped to the end of the page to |
| 1510 | + ** render the errors. Any up-coming errors, barring malloc failure |
| 1511 | + ** or similar, are not "that" fatal. We can/should continue |
| 1512 | + ** rendering the page, then output the error message at the end. |
| 1505 | 1513 | ********************************************************************/ |
| 1506 | | -#undef fail |
| 1507 | 1514 | CX("<h1>Editing:</h1>"); |
| 1508 | 1515 | CX("<p class='fileedit-hint'>"); |
| 1509 | 1516 | CX("File: " |
| 1510 | 1517 | "[<a id='finfo-link' href='#'>info</a>] " |
| 1511 | 1518 | /* %R/finfo?name=%T&m=%!S */ |
| | @@ -1598,17 +1605,25 @@ |
| 1598 | 1605 | ? 2 : 0), |
| 1599 | 1606 | "Inherit", 0, |
| 1600 | 1607 | "Unix", 1, |
| 1601 | 1608 | "Windows", 2, |
| 1602 | 1609 | NULL); |
| 1610 | + style_select_list_int("select-font-size", |
| 1611 | + "editor_font_size", "Editor Font Size", |
| 1612 | + NULL/*tooltip*/, |
| 1613 | + 100, |
| 1614 | + "100%", 100, "125%", 125, |
| 1615 | + "150%", 150, "175%", 175, |
| 1616 | + "200%", 200, NULL); |
| 1603 | 1617 | |
| 1604 | 1618 | CX("</div></fieldset>") /* end of checkboxes */; |
| 1605 | 1619 | |
| 1606 | 1620 | /******* Comment *******/ |
| 1607 | 1621 | CX("<a id='comment'></a>"); |
| 1608 | 1622 | CX("<fieldset><legend>Commit message</legend><div>"); |
| 1609 | | - CX("<textarea name='comment' rows='3' cols='80'>"); |
| 1623 | + CX("<textarea name='comment' rows='3' cols='80' " |
| 1624 | + "id='fileedit-comment'>"); |
| 1610 | 1625 | /* ^^^ adding the 'required' attribute means we cannot even submit |
| 1611 | 1626 | ** for PREVIEW mode if it's empty :/. */ |
| 1612 | 1627 | if(blob_size(&cimi.comment)){ |
| 1613 | 1628 | CX("%h", blob_str(&cimi.comment)); |
| 1614 | 1629 | } |
| | @@ -1636,11 +1651,12 @@ |
| 1636 | 1651 | "Wiki/Markdown", FE_RENDER_WIKI, |
| 1637 | 1652 | "HTML (iframe)", FE_RENDER_HTML, |
| 1638 | 1653 | "Plain Text", FE_RENDER_PLAIN_TEXT, |
| 1639 | 1654 | NULL); |
| 1640 | 1655 | /* |
| 1641 | | - ** Set up a JS-side mapping of the FE_RENDER_xyz values |
| 1656 | + ** Set up a JS-side mapping of the FE_RENDER_xyz values. This is |
| 1657 | + ** used for dynamically toggling certain UI components on and off. |
| 1642 | 1658 | */ |
| 1643 | 1659 | blob_appendf(&endScript, "fossil.page.previewModes={" |
| 1644 | 1660 | "guess: %d, %d: 'guess', wiki: %d, %d: 'wiki'," |
| 1645 | 1661 | "html: %d, %d: 'html', text: %d, %d: 'text'" |
| 1646 | 1662 | "};\n", |
| | @@ -1691,14 +1707,11 @@ |
| 1691 | 1707 | db_finalize(&stmt); |
| 1692 | 1708 | } |
| 1693 | 1709 | if(blob_size(&err)){ |
| 1694 | 1710 | CX("<div class='fileedit-error-report'>%s</div>", |
| 1695 | 1711 | blob_str(&err)); |
| 1696 | | - }else if(blob_size(&submitResult)){ |
| 1697 | | - CX("%b",&submitResult); |
| 1698 | 1712 | } |
| 1699 | | - blob_reset(&submitResult); |
| 1700 | 1713 | blob_reset(&err); |
| 1701 | 1714 | CheckinMiniInfo_cleanup(&cimi); |
| 1702 | 1715 | style_emit_script_fetch(); |
| 1703 | 1716 | fileedit_emit_page_script(); |
| 1704 | 1717 | if(blob_size(&endScript)>0){ |
| | @@ -1707,9 +1720,8 @@ |
| 1707 | 1720 | CX("try{\n%b\n}catch(e){console.error('Exception:',e)}\n", |
| 1708 | 1721 | &endScript); |
| 1709 | 1722 | CX("})();"); |
| 1710 | 1723 | style_emit_script_tag(1); |
| 1711 | 1724 | } |
| 1712 | | - db_end_transaction(0/*noting that dry-run mode will have already |
| 1713 | | - ** set this to rollback mode. */); |
| 1725 | + db_end_transaction(0); |
| 1714 | 1726 | style_footer(); |
| 1715 | 1727 | } |
| 1716 | 1728 | |