Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Fix overlong lines and remove trailing whitespace from non-external C files. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
275da70f8cc6b943752b1273a22b572f |
| User & Date: | danield 2024-02-02 22:22:37.329 |
Context
|
2024-02-03
| ||
| 20:32 | In the /timeline, automatically highlight the from= and to= selections. check-in: bb3de39ffe user: drh tags: trunk | |
| 16:55 | Update with all changes from trunk. check-in: c454059a18 user: andybradford tags: clone-resume | |
|
2024-02-02
| ||
| 22:22 | Fix overlong lines and remove trailing whitespace from non-external C files. check-in: 275da70f8c user: danield tags: trunk | |
| 22:18 | Remove trailing whitespace from non-external C files. Closed-Leaf check-in: 7db0a2d910 user: danield tags: fix-overlength-lines | |
| 16:23 | Replace stray tab characters. check-in: 9db696ea78 user: danield tags: trunk | |
Changes
Changes to src/alerts.c.
| ︙ | ︙ | |||
1458 1459 1460 1461 1462 1463 1464 | /* If we reach this point, all is well */ return 1; } /* ** Text of email message sent in order to confirm a subscription. */ | | | 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 | /* If we reach this point, all is well */ return 1; } /* ** Text of email message sent in order to confirm a subscription. */ static const char zConfirmMsg[] = @ Someone has signed you up for email alerts on the Fossil repository @ at %s. @ @ To confirm your subscription and begin receiving alerts, click on @ the following hyperlink: @ @ %s/alerts/%s |
| ︙ | ︙ | |||
2561 2562 2563 2564 2565 2566 2567 | } /* ** Compute a string that is appropriate for the EmailEvent.zPriors field ** for a particular forum post. ** ** This string is an encode list of sender names and rids for all ancestors | | | 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 |
}
/*
** Compute a string that is appropriate for the EmailEvent.zPriors field
** for a particular forum post.
**
** This string is an encode list of sender names and rids for all ancestors
** of the fpdi post - the post that fpid answer, the post that that parent
** post answers, and so forth back up to the root post. Duplicates sender
** names are omitted.
**
** The EmailEvent.zPriors field is used to screen events for people who
** only want to see replies to their own posts or to specific posts.
*/
static char *alert_compute_priors(int fpid){
|
| ︙ | ︙ | |||
3221 3222 3223 3224 3225 3226 3227 |
** alerts that have been completely sent.
*/
db_multi_exec("DELETE FROM pending_alert WHERE sentDigest AND sentSep;");
/* Send renewal messages to subscribers whose subscriptions are about
** to expire. Only do this if:
**
| | | 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 |
** alerts that have been completely sent.
*/
db_multi_exec("DELETE FROM pending_alert WHERE sentDigest AND sentSep;");
/* Send renewal messages to subscribers whose subscriptions are about
** to expire. Only do this if:
**
** (1) email-renew-interval is 14 or greater (or in other words if
** subscription expiration is enabled).
**
** (2) The SENDALERT_RENEWAL flag is set
*/
send_alert_expiration_warnings:
if( (flags & SENDALERT_RENEWAL)!=0
&& (iInterval = db_get_int("email-renew-interval",0))>=14
|
| ︙ | ︙ |
Changes to src/allrepo.c.
| ︙ | ︙ | |||
132 133 134 135 136 137 138 | ** ** ui Run the "ui" command on all repositories. Like "server" ** but bind to the loopback TCP address only, enable ** the --localauth option and automatically launch a ** web-browser ** ** whatis Run the "whatis" command on all repositories. Only | | | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | ** ** ui Run the "ui" command on all repositories. Like "server" ** but bind to the loopback TCP address only, enable ** the --localauth option and automatically launch a ** web-browser ** ** whatis Run the "whatis" command on all repositories. Only ** show output for repositories that have a match. ** ** ** In addition, the following maintenance operations are supported: ** ** add Add all the repositories named to the set of repositories ** tracked by Fossil. Normally Fossil is able to keep up with ** this list by itself, but sometimes it can benefit from this |
| ︙ | ︙ |
Changes to src/attach.c.
| ︙ | ︙ | |||
748 749 750 751 752 753 754 |
if( (pWiki = manifest_get(rid, CFTYPE_EVENT, 0))!=0 ){
zBody = pWiki->zWiki;
}
if( zBody==0 ){
fossil_fatal("technote [%s] not found",zETime);
}
zTarget = db_text(0,
| | > | 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 |
if( (pWiki = manifest_get(rid, CFTYPE_EVENT, 0))!=0 ){
zBody = pWiki->zWiki;
}
if( zBody==0 ){
fossil_fatal("technote [%s] not found",zETime);
}
zTarget = db_text(0,
"SELECT substr(tagname,7) FROM tag "
" WHERE tagid=(SELECT tagid FROM event WHERE objid='%d')",
rid
);
zFile = g.argv[3];
}
blob_read_from_file(&content, zFile, ExtFILE);
user_select();
attach_commit(
|
| ︙ | ︙ |
Changes to src/backlink.c.
| ︙ | ︙ | |||
247 248 249 250 251 252 253 |
void *opaque
){
Backlink *p = (Backlink*)opaque;
char *zTarget = blob_buffer(target);
int nTarget = blob_size(target);
backlink_create(p, zTarget, nTarget);
| | | 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
void *opaque
){
Backlink *p = (Backlink*)opaque;
char *zTarget = blob_buffer(target);
int nTarget = blob_size(target);
backlink_create(p, zTarget, nTarget);
return 1;
}
/* No-op routines for the rendering callbacks that we do not need */
static void mkdn_noop_prolog(Blob *b, void *v){ return; }
static void (*mkdn_noop_epilog)(Blob*, void*) = mkdn_noop_prolog;
static void mkdn_noop_footnotes(Blob *b1, const Blob *b2, void *v){ return; }
static void mkdn_noop_blockcode(Blob *b1, Blob *b2, void *v){ return; }
|
| ︙ | ︙ |
Changes to src/backoffice.c.
| ︙ | ︙ | |||
313 314 315 316 317 318 319 |
** we cannot prove that the process is dead, return true.
*/
static int backofficeProcessExists(sqlite3_uint64 pid){
#if defined(_WIN32)
return pid>0 && backofficeWin32ProcessExists((DWORD)pid)!=0;
#else
return pid>0 && kill((pid_t)pid, 0)==0;
| | | | 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
** we cannot prove that the process is dead, return true.
*/
static int backofficeProcessExists(sqlite3_uint64 pid){
#if defined(_WIN32)
return pid>0 && backofficeWin32ProcessExists((DWORD)pid)!=0;
#else
return pid>0 && kill((pid_t)pid, 0)==0;
#endif
}
/*
** Check to see if the process identified by pid has finished. If
** we cannot prove that the process is still running, return true.
*/
static int backofficeProcessDone(sqlite3_uint64 pid){
#if defined(_WIN32)
return pid<=0 || backofficeWin32ProcessExists((DWORD)pid)==0;
#else
return pid<=0 || kill((pid_t)pid, 0)!=0;
#endif
}
/*
** Return a process id number for the current process
*/
static sqlite3_uint64 backofficeProcessId(void){
return (sqlite3_uint64)GETPID();
|
| ︙ | ︙ | |||
673 674 675 676 677 678 679 | ** This might be done by a cron job or similar to make sure backoffice ** processing happens periodically. Or, the --poll option can be used ** to run this command as a daemon that will periodically invoke backoffice ** on a collection of repositories. ** ** If only a single repository is named and --poll is omitted, then the ** backoffice work is done in-process. But if there are multiple repositories | | | 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 | ** This might be done by a cron job or similar to make sure backoffice ** processing happens periodically. Or, the --poll option can be used ** to run this command as a daemon that will periodically invoke backoffice ** on a collection of repositories. ** ** If only a single repository is named and --poll is omitted, then the ** backoffice work is done in-process. But if there are multiple repositories ** or if --poll is used, a separate sub-process is started for each poll of ** each repository. ** ** Standard options: ** ** --debug Show what this command is doing ** ** --logfile FILE Append a log of backoffice actions onto FILE |
| ︙ | ︙ |
Changes to src/blob.c.
| ︙ | ︙ | |||
1549 1550 1551 1552 1553 1554 1555 |
z[--j] = z[i];
}
}
}
/*
** ASCII (for reference):
| | | | | | | | | | | 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 |
z[--j] = z[i];
}
}
}
/*
** ASCII (for reference):
** x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf
** 0x ^` ^a ^b ^c ^d ^e ^f ^g \b \t \n () \f \r ^n ^o
** 1x ^p ^q ^r ^s ^t ^u ^v ^w ^x ^y ^z ^{ ^| ^} ^~ ^
** 2x () ! " # $ % & ' ( ) * + , - . /
** 3x 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
** 4x @ A B C D E F G H I J K L M N O
** 5x P Q R S T U V W X Y Z [ \ ] ^ _
** 6x ` a b c d e f g h i j k l m n o
** 7x p q r s t u v w x y z { | } ~ ^_
*/
/*
** Meanings for bytes in a filename:
**
** 0 Ordinary character. No encoding required
** 1 Needs to be escaped
|
| ︙ | ︙ | |||
1663 1664 1665 1666 1667 1668 1669 |
blob_token(pBlob, &bad);
fossil_fatal("the [%s] argument to the \"%s\" command contains "
"an illegal UTF-8 character",
zIn, blob_str(&bad));
}
i += x-2;
}
| | | 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 |
blob_token(pBlob, &bad);
fossil_fatal("the [%s] argument to the \"%s\" command contains "
"an illegal UTF-8 character",
zIn, blob_str(&bad));
}
i += x-2;
}
}
}
/* Separate from the previous argument by a space */
if( n>0 && !fossil_isspace(z[n-1]) ){
blob_append_char(pBlob, ' ');
}
|
| ︙ | ︙ | |||
1793 1794 1795 1796 1797 1798 1799 |
}
#ifdef _WIN32
if( zBuf[0]=='-' && zArg[0]=='.' && zArg[1]=='\\' ) zArg += 2;
#else
if( zBuf[0]=='-' && zArg[0]=='.' && zArg[1]=='/' ) zArg += 2;
#endif
if( strcmp(zBuf, zArg)!=0 ){
| | | 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 |
}
#ifdef _WIN32
if( zBuf[0]=='-' && zArg[0]=='.' && zArg[1]=='\\' ) zArg += 2;
#else
if( zBuf[0]=='-' && zArg[0]=='.' && zArg[1]=='/' ) zArg += 2;
#endif
if( strcmp(zBuf, zArg)!=0 ){
fossil_fatal("argument disagree: \"%s\" (%s) versus \"%s\"",
zBuf, g.argv[i-1], zArg);
}
continue;
}else if( fossil_strcmp(zArg, "--fuzz")==0 && i+1<g.argc ){
int n = atoi(g.argv[++i]);
int j;
for(j=0; j<n; j++){
|
| ︙ | ︙ |
Changes to src/branch.c.
| ︙ | ︙ | |||
338 339 340 341 342 343 344 |
blob_append_sql(&sql,
"SELECT name, isprivate, mtime, mergeto FROM tmp_brlist WHERE 1"
);
break;
}
case BRL_OPEN_ONLY: {
blob_append_sql(&sql,
| | > | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
blob_append_sql(&sql,
"SELECT name, isprivate, mtime, mergeto FROM tmp_brlist WHERE 1"
);
break;
}
case BRL_OPEN_ONLY: {
blob_append_sql(&sql,
"SELECT name, isprivate, mtime, mergeto FROM tmp_brlist "
" WHERE NOT isclosed"
);
break;
}
}
if( brFlags & BRL_PRIVATE ) blob_append_sql(&sql, " AND isprivate");
if( brFlags & BRL_MERGED ) blob_append_sql(&sql, " AND mergeto IS NOT NULL");
if( zBrNameGlob ) blob_append_sql(&sql, " AND (name GLOB %Q)", zBrNameGlob);
|
| ︙ | ︙ | |||
770 771 772 773 774 775 776 |
int isPriv = db_column_int(&q, 1)==1;
const char *zMergeTo = db_column_text(&q, 2);
int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
const char *zUsers = db_column_text(&q, 3);
if( (brFlags & BRL_MERGED) && fossil_strcmp(zCurrent,zMergeTo)!=0 ){
continue;
}
| | | 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 |
int isPriv = db_column_int(&q, 1)==1;
const char *zMergeTo = db_column_text(&q, 2);
int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
const char *zUsers = db_column_text(&q, 3);
if( (brFlags & BRL_MERGED) && fossil_strcmp(zCurrent,zMergeTo)!=0 ){
continue;
}
if( (brFlags & BRL_UNMERGED) && (fossil_strcmp(zCurrent,zMergeTo)==0
|| isCur) ){
continue;
}
blob_appendf(&txt, "%s%s%s",
( (brFlags & BRL_PRIVATE) ? " " : ( isPriv ? "#" : " ") ),
(isCur ? "* " : " "), zBr);
if( nUsers ){
|
| ︙ | ︙ | |||
884 885 886 887 888 889 890 |
}
}
if( zBgClr && zBgClr[0] && show_colors ){
@ <tr style="background-color:%s(zBgClr)">
}else{
@ <tr>
}
| | | 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 |
}
}
if( zBgClr && zBgClr[0] && show_colors ){
@ <tr style="background-color:%s(zBgClr)">
}else{
@ <tr>
}
@ <td>%z(href("%R/timeline?r=%T",zBranch))%h(zBranch)</a><input
@ type="checkbox" disabled="disabled"/></td>
@ <td data-sortkey="%016llx(iMtime)">%s(zAge)</td>
@ <td>%d(nCkin)</td>
fossil_free(zAge);
@ <td>%s(isClosed?"closed":"")</td>
if( zMergeTo ){
@ <td>merged into
|
| ︙ | ︙ |
Changes to src/browse.c.
| ︙ | ︙ | |||
356 357 358 359 360 361 362 | /* Generate a multi-column table listing the contents of zD[] ** directory. */ mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles /*scan*/"); if( mxLen<12 ) mxLen = 12; mxLen += (mxLen+9)/10; | | | 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 |
/* Generate a multi-column table listing the contents of zD[]
** directory.
*/
mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles /*scan*/");
if( mxLen<12 ) mxLen = 12;
mxLen += (mxLen+9)/10;
db_prepare(&q,
"SELECT x, u FROM localfiles ORDER BY x COLLATE uintnocase /*scan*/");
@ <div class="columns files" style="columns: %d(mxLen)ex auto">
@ <ul class="browser">
while( db_step(&q)==SQLITE_ROW ){
const char *zFN;
zFN = db_column_text(&q, 0);
if( zFN[0]=='/' ){
|
| ︙ | ︙ | |||
469 470 471 472 473 474 475 | FileTreeNode *pSibling; /* Next element in the same subdirectory */ FileTreeNode *pChild; /* List of child nodes */ FileTreeNode *pLastChild; /* Last child on the pChild list */ char *zName; /* Name of this entry. The "tail" */ char *zFullName; /* Full pathname of this entry */ char *zUuid; /* Artifact hash of this file. May be NULL. */ double mtime; /* Modification time for this entry */ | | > | 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 |
FileTreeNode *pSibling; /* Next element in the same subdirectory */
FileTreeNode *pChild; /* List of child nodes */
FileTreeNode *pLastChild; /* Last child on the pChild list */
char *zName; /* Name of this entry. The "tail" */
char *zFullName; /* Full pathname of this entry */
char *zUuid; /* Artifact hash of this file. May be NULL. */
double mtime; /* Modification time for this entry */
double sortBy; /* Either mtime or size, depending on desired
sort order */
int iSize; /* Size for this entry */
unsigned nFullName; /* Length of zFullName */
unsigned iLevel; /* Levels of parent directories */
};
/*
** A complete file hierarchy
|
| ︙ | ︙ | |||
506 507 508 509 510 511 512 |
const char *zUuid, /* Hash of the file. Might be NULL. */
double mtime, /* Modification time for this entry */
int size, /* Size for this entry */
int sortOrder /* 0: filename, 1: mtime, 2: size */
){
int i;
FileTreeNode *pParent; /* Parent (directory) of the next node to insert */
| | | 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 |
const char *zUuid, /* Hash of the file. Might be NULL. */
double mtime, /* Modification time for this entry */
int size, /* Size for this entry */
int sortOrder /* 0: filename, 1: mtime, 2: size */
){
int i;
FileTreeNode *pParent; /* Parent (directory) of the next node to insert */
/* Make pParent point to the most recent ancestor of zPath, or
** NULL if there are no prior entires that are a container for zPath.
*/
pParent = pTree->pLast;
while( pParent!=0 &&
( strncmp(pParent->zFullName, zPath, pParent->nFullName)!=0
|| zPath[pParent->nFullName]!='/' )
|
| ︙ | ︙ |
Changes to src/builtin.c.
| ︙ | ︙ | |||
519 520 521 522 523 524 525 | builtinVtab_cursor *pCur = (builtinVtab_cursor*)cur; return pCur->iRowid>count(aBuiltinFiles); } /* ** This method is called to "rewind" the builtinVtab_cursor object back ** to the first row of output. This method is always called at least | | | | 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 |
builtinVtab_cursor *pCur = (builtinVtab_cursor*)cur;
return pCur->iRowid>count(aBuiltinFiles);
}
/*
** This method is called to "rewind" the builtinVtab_cursor object back
** to the first row of output. This method is always called at least
** once prior to any call to builtinVtabColumn() or builtinVtabRowid() or
** builtinVtabEof().
*/
static int builtinVtabFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
builtinVtab_cursor *pCur = (builtinVtab_cursor *)pVtabCursor;
pCur->iRowid = 1;
return SQLITE_OK;
}
|
| ︙ | ︙ | |||
548 549 550 551 552 553 554 |
){
pIdxInfo->estimatedCost = (double)count(aBuiltinFiles);
pIdxInfo->estimatedRows = count(aBuiltinFiles);
return SQLITE_OK;
}
/*
| | | 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 |
){
pIdxInfo->estimatedCost = (double)count(aBuiltinFiles);
pIdxInfo->estimatedRows = count(aBuiltinFiles);
return SQLITE_OK;
}
/*
** This following structure defines all the methods for the
** virtual table.
*/
static sqlite3_module builtinVtabModule = {
/* iVersion */ 0,
/* xCreate */ 0, /* The builtin vtab is eponymous and read-only */
/* xConnect */ builtinVtabConnect,
/* xBestIndex */ builtinVtabBestIndex,
|
| ︙ | ︙ | |||
814 815 816 817 818 819 820 | ** per-page basis. In this case, all arguments are ignored! ** ** This function has an internal mapping of the dependencies for each ** of the known fossil.XYZ.js modules and ensures that the ** dependencies also get queued (recursively) and that each module is ** queued only once. ** | | | 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 | ** per-page basis. In this case, all arguments are ignored! ** ** This function has an internal mapping of the dependencies for each ** of the known fossil.XYZ.js modules and ensures that the ** dependencies also get queued (recursively) and that each module is ** queued only once. ** ** If passed a name which is not a base fossil module name then it ** will fail fatally! ** ** DO NOT use this for loading fossil.page.*.js: use ** builtin_request_js() for those. ** ** If the current JS delivery mode is *not* JS_BUNDLED then this ** function queues up a request for each given module and its known |
| ︙ | ︙ |
Changes to src/cache.c.
| ︙ | ︙ | |||
311 312 313 314 315 316 317 |
sqlite3_exec(db, "DELETE FROM cache; DELETE FROM blob; VACUUM;",0,0,0);
sqlite3_close(db);
fossil_print("cache cleared\n");
}else{
fossil_print("nothing to clear; cache does not exist\n");
}
}else if( strncmp(zCmd, "list", nCmd)==0
| | | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
sqlite3_exec(db, "DELETE FROM cache; DELETE FROM blob; VACUUM;",0,0,0);
sqlite3_close(db);
fossil_print("cache cleared\n");
}else{
fossil_print("nothing to clear; cache does not exist\n");
}
}else if( strncmp(zCmd, "list", nCmd)==0
|| strncmp(zCmd, "ls", nCmd)==0
|| strncmp(zCmd, "status", nCmd)==0
){
db = cacheOpen(0);
if( db==0 ){
fossil_print("cache does not exist\n");
}else{
int nEntry = 0;
|
| ︙ | ︙ | |||
430 431 432 433 434 435 436 |
@ hit-count: %d(sqlite3_column_int(pStmt,2))
@ last-access: %s(sqlite3_column_text(pStmt,3)) \
if( zHash ){
@ %z(href("%R/timeline?c=%S",zHash))check-in</a>\
fossil_free(zHash);
}
@ </p></li>
| | | 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 |
@ hit-count: %d(sqlite3_column_int(pStmt,2))
@ last-access: %s(sqlite3_column_text(pStmt,3)) \
if( zHash ){
@ %z(href("%R/timeline?c=%S",zHash))check-in</a>\
fossil_free(zHash);
}
@ </p></li>
}
sqlite3_finalize(pStmt);
@ </ol>
}
zDbName = cacheName();
bigSizeName(sizeof(zBuf), zBuf, file_size(zDbName, ExtFILE));
@ <p>
|
| ︙ | ︙ |
Changes to src/capabilities.c.
| ︙ | ︙ | |||
399 400 401 402 403 404 405 |
@ <th>Unversioned Content</th></tr>
while( db_step(&q)==SQLITE_ROW ){
const char *zId = db_column_text(&q, 0);
const char *zCap = db_column_text(&q, 1);
int n = db_column_int(&q, 3);
int eType;
static const char *const azType[] = { "off", "read", "write" };
| | | 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
@ <th>Unversioned Content</th></tr>
while( db_step(&q)==SQLITE_ROW ){
const char *zId = db_column_text(&q, 0);
const char *zCap = db_column_text(&q, 1);
int n = db_column_int(&q, 3);
int eType;
static const char *const azType[] = { "off", "read", "write" };
static const char *const azClass[] =
{ "capsumOff", "capsumRead", "capsumWrite" };
if( n==0 ) continue;
/* Code */
if( db_column_int(&q,2)<10 ){
@ <tr><th align="right"><tt>"%h(zId)"</tt></th>
|
| ︙ | ︙ |
Changes to src/cgi.c.
| ︙ | ︙ | |||
35 36 37 38 39 40 41 | ** So, even though the name of this file implies that it only deals with ** CGI, in fact, the code in this file is used to interpret webpage requests ** received by a variety of means, and to generate well-formatted replies ** to those requests. ** ** The code in this file abstracts the web-request so that downstream ** modules that generate the body of the reply (based on the requested page) | | | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | ** So, even though the name of this file implies that it only deals with ** CGI, in fact, the code in this file is used to interpret webpage requests ** received by a variety of means, and to generate well-formatted replies ** to those requests. ** ** The code in this file abstracts the web-request so that downstream ** modules that generate the body of the reply (based on the requested page) ** do not need to know if the request is coming from CGI, direct HTTP, ** SCGI, or some other means. ** ** This module gathers information about web page request into a key/value ** store. Keys and values come from: ** ** * Query parameters ** * POST parameter |
| ︙ | ︙ | |||
479 480 481 482 483 484 485 |
if( iReplyStatus<=0 ){
iReplyStatus = 200;
zReplyStatus = "OK";
}
if( g.fullHttpReply ){
if( rangeEnd>0
| | | 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 |
if( iReplyStatus<=0 ){
iReplyStatus = 200;
zReplyStatus = "OK";
}
if( g.fullHttpReply ){
if( rangeEnd>0
&& iReplyStatus==200
&& fossil_strcmp(P("REQUEST_METHOD"),"GET")==0
){
iReplyStatus = 206;
zReplyStatus = "Partial Content";
}
blob_appendf(&hdr, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
blob_appendf(&hdr, "Date: %s\r\n", cgi_rfc822_datestamp(time(0)));
|
| ︙ | ︙ | |||
560 561 562 563 564 565 566 |
blob_appendf(&hdr, "Content-Encoding: gzip\r\n");
blob_appendf(&hdr, "Vary: Accept-Encoding\r\n");
}
total_size = blob_size(&cgiContent[0]) + blob_size(&cgiContent[1]);
if( iReplyStatus==206 ){
blob_appendf(&hdr, "Content-Range: bytes %d-%d/%d\r\n",
rangeStart, rangeEnd-1, total_size);
| | | 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 |
blob_appendf(&hdr, "Content-Encoding: gzip\r\n");
blob_appendf(&hdr, "Vary: Accept-Encoding\r\n");
}
total_size = blob_size(&cgiContent[0]) + blob_size(&cgiContent[1]);
if( iReplyStatus==206 ){
blob_appendf(&hdr, "Content-Range: bytes %d-%d/%d\r\n",
rangeStart, rangeEnd-1, total_size);
total_size = rangeEnd - rangeStart;
}
blob_appendf(&hdr, "Content-Length: %d\r\n", total_size);
}else{
total_size = 0;
}
blob_appendf(&hdr, "\r\n");
cgi_fwrite(blob_buffer(&hdr), blob_size(&hdr));
|
| ︙ | ︙ | |||
1309 1310 1311 1312 1313 1314 1315 | ** / \ ** https://fossil-scm.org/forum/info/12736b30c072551a?t=c ** \___/ \____________/\____/\____________________/ \_/ ** | | | | | ** | HTTP_HOST | PATH_INFO QUERY_STRING ** | | ** REQUEST_SCHEMA SCRIPT_NAME | | | 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 |
** / \
** https://fossil-scm.org/forum/info/12736b30c072551a?t=c
** \___/ \____________/\____/\____________________/ \_/
** | | | | |
** | HTTP_HOST | PATH_INFO QUERY_STRING
** | |
** REQUEST_SCHEMA SCRIPT_NAME
**
*/
void cgi_init(void){
char *z;
const char *zType;
char *zSemi;
int len;
const char *zRequestUri = cgi_parameter("REQUEST_URI",0);
|
| ︙ | ︙ | |||
1346 1347 1348 1349 1350 1351 1352 |
zScriptName = fossil_strndup(zRequestUri,(int)(z-zRequestUri));
cgi_set_parameter("SCRIPT_NAME", zScriptName);
}
#ifdef _WIN32
/* The Microsoft IIS web server does not define REQUEST_URI, instead it uses
** PATH_INFO for virtually the same purpose. Define REQUEST_URI the same as
| | | 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 |
zScriptName = fossil_strndup(zRequestUri,(int)(z-zRequestUri));
cgi_set_parameter("SCRIPT_NAME", zScriptName);
}
#ifdef _WIN32
/* The Microsoft IIS web server does not define REQUEST_URI, instead it uses
** PATH_INFO for virtually the same purpose. Define REQUEST_URI the same as
** PATH_INFO and redefine PATH_INFO with SCRIPT_NAME removed from the
** beginning. */
if( zServerSoftware && strstr(zServerSoftware, "Microsoft-IIS") ){
int i, j;
cgi_set_parameter("REQUEST_URI", zPathInfo);
for(i=0; zPathInfo[i]==zScriptName[i] && zPathInfo[i]; i++){}
for(j=i; zPathInfo[j] && zPathInfo[j]!='?'; j++){}
zPathInfo = fossil_strndup(zPathInfo+i, j-i);
|
| ︙ | ︙ |
Changes to src/chat.c.
| ︙ | ︙ | |||
32 33 34 35 36 37 38 | ** * Chat content lives in a single repository. It is never synced. ** Content expires and is deleted after a set interval (a week or so). ** ** Notification is accomplished using the "hanging GET" or "long poll" design ** in which a GET request is issued but the server does not send a reply until ** new content arrives. Newer Web Sockets and Server Sent Event protocols are ** more elegant, but are not compatible with CGI, and would thus complicate | | | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | ** * Chat content lives in a single repository. It is never synced. ** Content expires and is deleted after a set interval (a week or so). ** ** Notification is accomplished using the "hanging GET" or "long poll" design ** in which a GET request is issued but the server does not send a reply until ** new content arrives. Newer Web Sockets and Server Sent Event protocols are ** more elegant, but are not compatible with CGI, and would thus complicate ** configuration. */ #include "config.h" #include <assert.h> #include "chat.h" /* ** Outputs JS code to initialize a list of chat alert audio files for |
| ︙ | ︙ | |||
317 318 319 320 321 322 323 |
" ORDER BY msgid LIMIT 1");
if( rAge>mxDays ){
msgid = db_int(0, "SELECT msgid FROM chat"
" ORDER BY msgid DESC LIMIT 1 OFFSET %d", mxCnt);
if( msgid>0 ){
Stmt s;
db_multi_exec("PRAGMA secure_delete=ON;");
| | | 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 |
" ORDER BY msgid LIMIT 1");
if( rAge>mxDays ){
msgid = db_int(0, "SELECT msgid FROM chat"
" ORDER BY msgid DESC LIMIT 1 OFFSET %d", mxCnt);
if( msgid>0 ){
Stmt s;
db_multi_exec("PRAGMA secure_delete=ON;");
db_prepare(&s,
"DELETE FROM chat WHERE mtime<julianday('now')-:mxage"
" AND msgid<%d", msgid);
db_bind_double(&s, ":mxage", mxDays);
db_step(&s);
db_finalize(&s);
}
}
|
| ︙ | ︙ | |||
691 692 693 694 695 696 697 |
}
sqlite3_sleep(iDelay); nDelay--;
}
} /* Exit by "break" */
db_finalize(&q1);
blob_append(&json, "\n]}", 3);
cgi_set_content(&json);
| | | 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 |
}
sqlite3_sleep(iDelay); nDelay--;
}
} /* Exit by "break" */
db_finalize(&q1);
blob_append(&json, "\n]}", 3);
cgi_set_content(&json);
return;
}
/*
** WEBPAGE: chat-fetch-one hidden loadavg-exempt
**
** /chat-fetch-one/N
**
|
| ︙ | ︙ | |||
724 725 726 727 728 729 730 |
if( !g.perm.Chat ) {
chat_emit_permissions_error(0);
return;
}
zChatUser = db_get("chat-timeline-user",0);
chat_create_tables();
cgi_set_content_type("application/json");
| | | 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 |
if( !g.perm.Chat ) {
chat_emit_permissions_error(0);
return;
}
zChatUser = db_get("chat-timeline-user",0);
chat_create_tables();
cgi_set_content_type("application/json");
db_prepare(&q,
"SELECT datetime(mtime), xfrom, xmsg, octet_length(file),"
" fname, fmime, lmtime"
" FROM chat WHERE msgid=%d AND mdel IS NULL",
msgid);
if(SQLITE_ROW==db_step(&q)){
const char *zDate = db_column_text(&q, 0);
const char *zFrom = db_column_text(&q, 1);
|
| ︙ | ︙ | |||
767 768 769 770 771 772 773 |
fossil_free(zMsg);
}
if( nByte==0 ){
blob_appendf(&json, "\"fsize\":0");
}else{
blob_appendf(&json, "\"fsize\":%d,\"fname\":%!j,\"fmime\":%!j",
nByte, zFName, zFMime);
| | | 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 |
fossil_free(zMsg);
}
if( nByte==0 ){
blob_appendf(&json, "\"fsize\":0");
}else{
blob_appendf(&json, "\"fsize\":%d,\"fname\":%!j,\"fmime\":%!j",
nByte, zFName, zFMime);
}
blob_append(&json,"}",1);
cgi_set_content(&json);
}else{
ajax_route_error(404,"Chat message #%d not found.", msgid);
}
db_finalize(&q);
}
|
| ︙ | ︙ | |||
955 956 957 958 959 960 961 |
sqlite3_value **argv
){
const char *zType = (const char*)sqlite3_value_text(argv[0]);
int rid = sqlite3_value_int(argv[1]);
const char *zUser = (const char*)sqlite3_value_text(argv[2]);
const char *zMsg = (const char*)sqlite3_value_text(argv[3]);
char *zRes = 0;
| | | 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 |
sqlite3_value **argv
){
const char *zType = (const char*)sqlite3_value_text(argv[0]);
int rid = sqlite3_value_int(argv[1]);
const char *zUser = (const char*)sqlite3_value_text(argv[2]);
const char *zMsg = (const char*)sqlite3_value_text(argv[3]);
char *zRes = 0;
if( zType==0 || zUser==0 || zMsg==0 ) return;
if( zType[0]=='c' ){
/* Check-ins */
char *zBranch;
char *zUuid;
zBranch = db_text(0,
|
| ︙ | ︙ |
Changes to src/checkin.c.
| ︙ | ︙ | |||
2533 2534 2535 2536 2537 2538 2539 |
"use --override-lock",
g.ckinLockFail);
}else{
fossil_fatal("Would fork. \"update\" first or use --branch or "
"--allow-fork.");
}
}
| | | | 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 |
"use --override-lock",
g.ckinLockFail);
}else{
fossil_fatal("Would fork. \"update\" first or use --branch or "
"--allow-fork.");
}
}
/*
** Do not allow a commit against a closed leaf unless the commit
** ends up on a different branch.
*/
if(
/* parent check-in has the "closed" tag... */
leaf_is_closed(vid)
/* ... and the new check-in has no --branch option or the --branch
** option does not actually change the branch */
&& (sCiInfo.zBranch==0
|| db_exists("SELECT 1 FROM tagxref"
" WHERE tagid=%d AND rid=%d AND tagtype>0"
" AND value=%Q", TAG_BRANCH, vid, sCiInfo.zBranch))
){
fossil_fatal("cannot commit against a closed leaf");
}
/* Always exit the loop on the second pass */
if( bRecheck ) break;
/* Get the check-in comment. This might involve prompting the
** user for the check-in comment, in which case we should resync
** to renew the check-in lock and repeat the checks for conflicts.
*/
if( zComment ){
blob_zero(&comment);
blob_append(&comment, zComment, -1);
|
| ︙ | ︙ |
Changes to src/clone.c.
| ︙ | ︙ | |||
194 195 196 197 198 199 200 |
g.argv[2]);
}
zRepo = mprintf("./%s.fossil", zBase);
if( zWorkDir==0 ){
zWorkDir = mprintf("./%s", zBase);
}
fossil_free(zBase);
| | | 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
g.argv[2]);
}
zRepo = mprintf("./%s.fossil", zBase);
if( zWorkDir==0 ){
zWorkDir = mprintf("./%s", zBase);
}
fossil_free(zBase);
}
if( -1 != file_size(zRepo, ExtFILE) ){
fossil_fatal("file already exists: %s", zRepo);
}
/* Fail before clone if open will fail because inside an open check-out */
if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){
if( db_open_local_v2(0, allowNested) ){
fossil_fatal("there is already an open tree at %s", g.zLocalRoot);
|
| ︙ | ︙ |
Changes to src/cookies.c.
| ︙ | ︙ | |||
237 238 239 240 241 242 243 |
zDel = mprintf("del%s",zName);
if( P(zDel)!=0 ){
cgi_set_cookie(zName, "", 0, -1);
cgi_redirect("cookies");
}
nCookie++;
@ <li><p><b>%h(zName)</b>: %h(zValue)
| | | 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
zDel = mprintf("del%s",zName);
if( P(zDel)!=0 ){
cgi_set_cookie(zName, "", 0, -1);
cgi_redirect("cookies");
}
nCookie++;
@ <li><p><b>%h(zName)</b>: %h(zValue)
@ <input type="submit" name="%h(zDel)" value="Delete">
if( fossil_strcmp(zName, DISPLAY_SETTINGS_COOKIE)==0 && cookies.nParam>0 ){
int j;
@ <ul>
for(j=0; j<cookies.nParam; j++){
@ <li>%h(cookies.aParam[j].zPName): "%h(cookies.aParam[j].zPValue)"
}
@ </ul>
|
| ︙ | ︙ |
Changes to src/db.c.
| ︙ | ︙ | |||
455 456 457 458 459 460 461 |
** be compromised by an attack.
*/
void db_protect_only(unsigned flags){
if( db.nProtect>=count(db.aProtect)-2 ){
fossil_panic("too many db_protect() calls");
}
db.aProtect[db.nProtect++] = db.protectMask;
| | | 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 |
** be compromised by an attack.
*/
void db_protect_only(unsigned flags){
if( db.nProtect>=count(db.aProtect)-2 ){
fossil_panic("too many db_protect() calls");
}
db.aProtect[db.nProtect++] = db.protectMask;
if( (flags & PROTECT_SENSITIVE)!=0
&& db.bProtectTriggers==0
&& g.repositoryOpen
){
/* Create the triggers needed to protect sensitive settings from
** being created or modified the first time that PROTECT_SENSITIVE
** is enabled. Deleting a sensitive setting is harmless, so there
** is not trigger to block deletes. After being created once, the
|
| ︙ | ︙ | |||
1555 1556 1557 1558 1559 1560 1561 |
sqlite3_create_function(db, "protected_setting", 1, SQLITE_UTF8, 0,
db_protected_setting_func, 0, 0);
sqlite3_create_function(db, "win_reserved", 1, SQLITE_UTF8, 0,
db_win_reserved_func,0,0);
sqlite3_create_function(db, "url_nouser", 1, SQLITE_UTF8, 0,
url_nouser_func,0,0);
sqlite3_create_function(db, "chat_msg_from_event", 4,
| | | | 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 |
sqlite3_create_function(db, "protected_setting", 1, SQLITE_UTF8, 0,
db_protected_setting_func, 0, 0);
sqlite3_create_function(db, "win_reserved", 1, SQLITE_UTF8, 0,
db_win_reserved_func,0,0);
sqlite3_create_function(db, "url_nouser", 1, SQLITE_UTF8, 0,
url_nouser_func,0,0);
sqlite3_create_function(db, "chat_msg_from_event", 4,
SQLITE_UTF8 | SQLITE_INNOCUOUS, 0,
chat_msg_from_event, 0, 0);
}
#if USE_SEE
/*
** This is a pointer to the saved database encryption key string.
*/
static char *zSavedKey = 0;
|
| ︙ | ︙ | |||
2487 2488 2489 2490 2491 2492 2493 |
db_multi_exec("ALTER TABLE undo ADD COLUMN isLink BOOLEAN DEFAULT 0");
}
if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){
db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0");
}
}
| | | 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 |
db_multi_exec("ALTER TABLE undo ADD COLUMN isLink BOOLEAN DEFAULT 0");
}
if( db_local_table_exists_but_lacks_column("undo_vfile", "islink") ){
db_multi_exec("ALTER TABLE undo_vfile ADD COLUMN islink BOOL DEFAULT 0");
}
}
/* The design of the check-out database changed on 2019-01-19 adding the mhash
** column to vfile and vmerge and changing the UNIQUE index on vmerge into
** a PRIMARY KEY that includes the new mhash column. However, we must have
** the repository database at hand in order to do the migration, so that
** step is deferred. */
return 1;
}
|
| ︙ | ︙ | |||
2604 2605 2606 2607 2608 2609 2610 | sqlite3_stmt *pStmt = 0; sz = file_size(zDbName, ExtFILE); if( sz<16834 ) return 0; db = db_open(zDbName); if( !db ) return 0; if( !g.zVfsName && sz%512 ) return 0; | | | 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 |
sqlite3_stmt *pStmt = 0;
sz = file_size(zDbName, ExtFILE);
if( sz<16834 ) return 0;
db = db_open(zDbName);
if( !db ) return 0;
if( !g.zVfsName && sz%512 ) return 0;
rc = sqlite3_prepare_v2(db,
"SELECT count(*) FROM sqlite_schema"
" WHERE name COLLATE nocase IN"
"('blob','delta','rcvfrom','user','config','mlink','plink');",
-1, &pStmt, 0);
if( rc ) goto is_repo_end;
rc = sqlite3_step(pStmt);
if( rc!=SQLITE_ROW ) goto is_repo_end;
|
| ︙ | ︙ | |||
3714 3715 3716 3717 3718 3719 3720 |
z = fossil_strdup(pSetting->def);
}else{
z = fossil_strdup(zDefault);
}
}
return z;
}
| | > | 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 |
z = fossil_strdup(pSetting->def);
}else{
z = fossil_strdup(zDefault);
}
}
return z;
}
char *db_get_mtime(const char *zName, const char *zFormat,
const char *zDefault){
char *z = 0;
if( g.repositoryOpen ){
z = db_text(0, "SELECT mtime FROM config WHERE name=%Q", zName);
}
if( z==0 ){
z = fossil_strdup(zDefault);
}else if( zFormat!=0 ){
|
| ︙ | ︙ | |||
4019 4020 4021 4022 4023 4024 4025 |
if( !g.localOpen ) return;
zName = db_repository_filename();
}
file_canonical_name(zName, &full, 0);
(void)filename_collation(); /* Initialize before connection swap */
db_swap_connections();
zRepoSetting = mprintf("repo:%q", blob_str(&full));
| | | 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 |
if( !g.localOpen ) return;
zName = db_repository_filename();
}
file_canonical_name(zName, &full, 0);
(void)filename_collation(); /* Initialize before connection swap */
db_swap_connections();
zRepoSetting = mprintf("repo:%q", blob_str(&full));
db_unprotect(PROTECT_CONFIG);
db_multi_exec(
"DELETE FROM global_config WHERE name %s = %Q;",
filename_collation(), zRepoSetting
);
db_multi_exec(
"INSERT OR IGNORE INTO global_config(name,value)"
|
| ︙ | ︙ | |||
4183 4184 4185 4186 4187 4188 4189 |
if( keepFlag==0
&& bForce==0
&& (nLocal = file_directory_size(".", 0, 1))>0
&& (nLocal>1 || isUri || !file_in_cwd(zRepo))
){
fossil_fatal("directory %s is not empty\n"
"use the -f (--force) option to override\n"
| | | 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 |
if( keepFlag==0
&& bForce==0
&& (nLocal = file_directory_size(".", 0, 1))>0
&& (nLocal>1 || isUri || !file_in_cwd(zRepo))
){
fossil_fatal("directory %s is not empty\n"
"use the -f (--force) option to override\n"
"or the -k (--keep) option to keep local files unchanged",
file_getcwd(0,0));
}
if( db_open_local_v2(0, allowNested) ){
fossil_fatal("there is already an open tree at %s", g.zLocalRoot);
}
|
| ︙ | ︙ | |||
4389 4390 4391 4392 4393 4394 4395 | ** ** When the admin-log setting is enabled, configuration changes are recorded ** in the "admin_log" table of the repository. */ /* ** SETTING: allow-symlinks boolean default=off sensitive ** | | | 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 | ** ** When the admin-log setting is enabled, configuration changes are recorded ** in the "admin_log" table of the repository. */ /* ** SETTING: allow-symlinks boolean default=off sensitive ** ** When allow-symlinks is OFF, Fossil does not see symbolic links ** (a.k.a "symlinks") on disk as a separate class of object. Instead Fossil ** sees the object that the symlink points to. Fossil will only manage files ** and directories, not symlinks. When a symlink is added to a repository, ** the object that the symlink points to is added, not the symlink itself. ** ** When allow-symlinks is ON, Fossil sees symlinks on disk as a separate ** object class that is distinct from files and directories. When a symlink |
| ︙ | ︙ | |||
4447 4448 4449 4450 4451 4452 4453 | ** When the auto-hyperlink setting is 1, the javascript that runs to set ** the href= attributes of hyperlinks delays by this many milliseconds ** after the page load. Suggested values: 50 to 200. */ /* ** SETTING: auto-hyperlink-mouseover boolean default=off ** | | | 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 | ** When the auto-hyperlink setting is 1, the javascript that runs to set ** the href= attributes of hyperlinks delays by this many milliseconds ** after the page load. Suggested values: 50 to 200. */ /* ** SETTING: auto-hyperlink-mouseover boolean default=off ** ** When the auto-hyperlink setting is 1 and this setting is on, the ** javascript that runs to set the href= attributes of hyperlinks waits ** until either a mousedown or mousemove event is seen. This helps ** to distinguish real users from robots. For maximum robot defense, ** the recommended setting is ON. */ /* ** SETTING: auto-shun boolean default=on |
| ︙ | ︙ | |||
4671 4672 4673 4674 4675 4676 4677 | ** Note that /fileedit cannot edit binary files, so the list should not ** contain any globs for, e.g., images or PDFs. */ /* ** SETTING: forbid-delta-manifests boolean default=off ** If enabled on a client, new delta manifests are prohibited on ** commits. If enabled on a server, whenever a client attempts | | | 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 | ** Note that /fileedit cannot edit binary files, so the list should not ** contain any globs for, e.g., images or PDFs. */ /* ** SETTING: forbid-delta-manifests boolean default=off ** If enabled on a client, new delta manifests are prohibited on ** commits. If enabled on a server, whenever a client attempts ** to obtain a check-in lock during auto-sync, the server will ** send the "pragma avoid-delta-manifests" statement in its reply, ** which will cause the client to avoid generating a delta ** manifest. */ /* ** SETTING: forum-close-policy boolean default=off ** If true, forum moderators may close/re-open forum posts, and reply |
| ︙ | ︙ | |||
5012 5013 5014 5015 5016 5017 5018 | ** Defaults to "start" on windows, "open" on Mac, ** and "firefox" on Unix. */ /* ** SETTING: large-file-size width=10 default=200000000 ** Fossil considers any file whose size is greater than this value ** to be a "large file". Fossil might issue warnings if you try to | | | 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 | ** Defaults to "start" on windows, "open" on Mac, ** and "firefox" on Unix. */ /* ** SETTING: large-file-size width=10 default=200000000 ** Fossil considers any file whose size is greater than this value ** to be a "large file". Fossil might issue warnings if you try to ** "add" or "commit" a "large file". Set this value to 0 or less ** to disable all such warnings. */ /* ** Look up a control setting by its name. Return a pointer to the Setting ** object, or NULL if there is no such setting. ** |
| ︙ | ︙ |
Changes to src/diff.c.
| ︙ | ︙ | |||
88 89 90 91 92 93 94 | ** Conceptually, this object is as an encoding of the command-line options ** for the "fossil diff" command. That is not a precise description, though, ** because not all diff operations are started from the command-line. But ** the idea is sound. ** ** Information encoded by this object includes but is not limited to: ** | | | | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
** Conceptually, this object is as an encoding of the command-line options
** for the "fossil diff" command. That is not a precise description, though,
** because not all diff operations are started from the command-line. But
** the idea is sound.
**
** Information encoded by this object includes but is not limited to:
**
** * The desired output format (unified vs. side-by-side,
** TCL, JSON, HTML vs. plain-text).
**
** * Number of lines of context surrounding each difference block
**
** * Width of output columns for text side-by-side diffop
*/
struct DiffConfig {
u64 diffFlags; /* Diff flags */
int nContext; /* Number of lines of context */
int wColumn; /* Column width in -y mode */
u32 nFile; /* Number of files diffed so far */
const char *zDiffCmd; /* External diff command to use instead of builtin */
|
| ︙ | ︙ | |||
913 914 915 916 917 918 919 | /* ** This is an abstract superclass for an object that accepts difference ** lines and formats them for display. Subclasses of this object format ** the diff output in different ways. ** ** To subclass, create an instance of the DiffBuilder object and fill ** in appropriate method implementations. | | | 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 |
/*
** This is an abstract superclass for an object that accepts difference
** lines and formats them for display. Subclasses of this object format
** the diff output in different ways.
**
** To subclass, create an instance of the DiffBuilder object and fill
** in appropriate method implementations.
*/
typedef struct DiffBuilder DiffBuilder;
struct DiffBuilder {
void (*xSkip)(DiffBuilder*, unsigned int, int);
void (*xCommon)(DiffBuilder*,const DLine*);
void (*xInsert)(DiffBuilder*,const DLine*);
void (*xDelete)(DiffBuilder*,const DLine*);
void (*xReplace)(DiffBuilder*,const DLine*,const DLine*);
|
| ︙ | ︙ | |||
1098 1099 1100 1101 1102 1103 1104 |
blob_append_char(p->pOut, ' ');
blob_append_tcl_literal(p->pOut, pX->z + x, chng.a[i].iStart1 - x);
x = chng.a[i].iStart1;
blob_append_char(p->pOut, ' ');
blob_append_tcl_literal(p->pOut, pX->z + x, chng.a[i].iLen1);
x += chng.a[i].iLen1;
blob_append_char(p->pOut, ' ');
| | | 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 |
blob_append_char(p->pOut, ' ');
blob_append_tcl_literal(p->pOut, pX->z + x, chng.a[i].iStart1 - x);
x = chng.a[i].iStart1;
blob_append_char(p->pOut, ' ');
blob_append_tcl_literal(p->pOut, pX->z + x, chng.a[i].iLen1);
x += chng.a[i].iLen1;
blob_append_char(p->pOut, ' ');
blob_append_tcl_literal(p->pOut,
pY->z + chng.a[i].iStart2, chng.a[i].iLen2);
}
if( x<pX->n ){
blob_append_char(p->pOut, ' ');
blob_append_tcl_literal(p->pOut, pX->z + x, pX->n - x);
}
blob_append_char(p->pOut, '\n');
|
| ︙ | ︙ | |||
1184 1185 1186 1187 1188 1189 1190 |
}
blob_append_json_literal(p->pOut, pX->z + x, chng.a[i].iStart1 - x);
x = chng.a[i].iStart1;
blob_append_char(p->pOut, ',');
blob_append_json_literal(p->pOut, pX->z + x, chng.a[i].iLen1);
x += chng.a[i].iLen1;
blob_append_char(p->pOut, ',');
| | | 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 |
}
blob_append_json_literal(p->pOut, pX->z + x, chng.a[i].iStart1 - x);
x = chng.a[i].iStart1;
blob_append_char(p->pOut, ',');
blob_append_json_literal(p->pOut, pX->z + x, chng.a[i].iLen1);
x += chng.a[i].iLen1;
blob_append_char(p->pOut, ',');
blob_append_json_literal(p->pOut,
pY->z + chng.a[i].iStart2, chng.a[i].iLen2);
}
blob_append_char(p->pOut, ',');
blob_append_json_literal(p->pOut, pX->z + x, pX->n - x);
blob_append(p->pOut, "],\n",3);
}
static void dfjsonEnd(DiffBuilder *p){
|
| ︙ | ︙ | |||
1266 1267 1268 1269 1270 1271 1272 | /* "+" marks for the separator on inserted lines */ for(i=0; i<p->nPending; i++) blob_append(&p->aCol[1], "+\n", 2); /* Text of the inserted lines */ blob_append(&p->aCol[2], "<ins>", 5); blob_append_xfer(&p->aCol[2], &p->aCol[4]); blob_append(&p->aCol[2], "</ins>", 6); | | | 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 |
/* "+" marks for the separator on inserted lines */
for(i=0; i<p->nPending; i++) blob_append(&p->aCol[1], "+\n", 2);
/* Text of the inserted lines */
blob_append(&p->aCol[2], "<ins>", 5);
blob_append_xfer(&p->aCol[2], &p->aCol[4]);
blob_append(&p->aCol[2], "</ins>", 6);
p->nPending = 0;
}
static void dfunifiedFinishRow(DiffBuilder *p){
dfunifiedFinishDelete(p);
dfunifiedFinishInsert(p);
if( blob_size(&p->aCol[0])==0 ) return;
blob_append(p->pOut, "</pre></td><td class=\"diffln difflnr\"><pre>\n", -1);
|
| ︙ | ︙ | |||
2003 2004 2005 2006 2007 2008 2009 |
aBig = aRight;
nBig = nRight;
}
iDivBig = nBig/2;
iDivSmall = nSmall/2;
if( pCfg->diffFlags & DIFF_DEBUG ){
| | | 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 |
aBig = aRight;
nBig = nRight;
}
iDivBig = nBig/2;
iDivSmall = nSmall/2;
if( pCfg->diffFlags & DIFF_DEBUG ){
fossil_print(" Divide at [%.*s]\n",
aBig[iDivBig].n, aBig[iDivBig].z);
}
bestScore = 10000;
for(i=0; i<nSmall; i++){
score = match_dline(aBig+iDivBig, aSmall+i) + abs(i-nSmall/2)*2;
if( score<bestScore ){
|
| ︙ | ︙ | |||
3491 3492 3493 3494 3495 3496 3497 |
}
p->nVers++;
cnt++;
}
if( p->nVers==0 ){
if( zRevision ){
| | > | 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 |
}
p->nVers++;
cnt++;
}
if( p->nVers==0 ){
if( zRevision ){
fossil_fatal("file %s does not exist in check-in %s",
zFilename, zRevision);
}else{
fossil_fatal("no history for file: %s", zFilename);
}
}
db_finalize(&q);
db_end_transaction(0);
|
| ︙ | ︙ |
Changes to src/diffcmd.c.
| ︙ | ︙ | |||
111 112 113 114 115 116 117 | } return 0; } /* ** Print details about the compared versions - possibly the working directory ** or the undo buffer. For check-ins, show hash and commit time. | | | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
}
return 0;
}
/*
** Print details about the compared versions - possibly the working directory
** or the undo buffer. For check-ins, show hash and commit time.
**
** This is intended primarily to go into the "header garbage" that is ignored
** by patch(1).
**
** zFrom and zTo are interpreted as symbolic version names, unless they
** start with '(', in which case they are printed directly.
*/
void diff_print_versions(const char *zFrom, const char *zTo, DiffConfig *pCfg){
|
| ︙ | ︙ | |||
216 217 218 219 220 221 222 | } } /* ** Default header texts for diff with --webpage */ | | | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
}
}
/*
** Default header texts for diff with --webpage
*/
static const char zWebpageHdr[] =
@ <!DOCTYPE html>
@ <html>
@ <head>
@ <meta charset="UTF-8">
@ <style>
@ body {
@ background-color: white;
|
| ︙ | ︙ | |||
340 341 342 343 344 345 346 |
@ background-color: #a2dbb2;
@ color: #000000;
@ }
@ td.difftxt ins > ins {
@ background-color: #559855;
@ }
@ }
| | | | | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
@ background-color: #a2dbb2;
@ color: #000000;
@ }
@ td.difftxt ins > ins {
@ background-color: #559855;
@ }
@ }
@
@ </style>
@ </head>
@ <body>
;
static const char zWebpageHdrDark[] =
@ <!DOCTYPE html>
@ <html>
@ <head>
@ <meta charset="UTF-8">
@ <style>
@ body {
@ background-color: #353535;
@ color: #ffffff;
@ }
@ h1 {
@ font-size: 150%;
@ }
@
@ table.diff {
@ width: 100%;
@ border-spacing: 0;
@ border: 1px solid black;
@ line-height: inherit;
@ font-size: inherit;
@ }
|
| ︙ | ︙ | |||
446 447 448 449 450 451 452 |
@ font-weight: bold;
@ }
@ td.difftxt ins > ins.edit {
@ background-color: #c0c0ff;
@ text-decoration: none;
@ font-weight: bold;
@ }
| | | | 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 |
@ font-weight: bold;
@ }
@ td.difftxt ins > ins.edit {
@ background-color: #c0c0ff;
@ text-decoration: none;
@ font-weight: bold;
@ }
@
@ </style>
@ </head>
@ <body>
;
const char zWebpageEnd[] =
@ </body>
@ </html>
;
/*
** State variables used by the --browser option for diff. These must
** be static variables, not elements of DiffConfig, since they are
|
| ︙ | ︙ | |||
514 515 516 517 518 519 520 |
#ifndef _WIN32
signal(SIGINT, diff_www_interrupt);
#else
SetConsoleCtrlHandler(diff_console_ctrl_handler, TRUE);
#endif
}
if( (pCfg->diffFlags & DIFF_WEBPAGE)!=0 ){
| | | | 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 |
#ifndef _WIN32
signal(SIGINT, diff_www_interrupt);
#else
SetConsoleCtrlHandler(diff_console_ctrl_handler, TRUE);
#endif
}
if( (pCfg->diffFlags & DIFF_WEBPAGE)!=0 ){
fossil_print("%s",(pCfg->diffFlags & DIFF_DARKMODE)!=0 ? zWebpageHdrDark :
zWebpageHdr);
fflush(stdout);
}
}
/* Do any final output required by a diff and complete the diff
** process.
**
** For --browser and --webpage, output any javascript required by
** the diff. (Currently JS is only needed for side-by-side diffs).
**
** For --browser, close the connection to the temporary file, then
** launch a web browser to view the file. After a delay
** of FOSSIL_BROWSER_DIFF_DELAY milliseconds, delete the temp file.
*/
void diff_end(DiffConfig *pCfg, int nErr){
|
| ︙ | ︙ | |||
945 946 947 948 949 950 951 |
){
Stmt q;
Blob content;
db_prepare(&q, "SELECT pathname, content FROM undo");
blob_init(&content, 0, 0);
if( (pCfg->diffFlags & DIFF_SHOW_VERS)!=0 ){
diff_print_versions("(undo)", "(workdir)", pCfg);
| | | 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 |
){
Stmt q;
Blob content;
db_prepare(&q, "SELECT pathname, content FROM undo");
blob_init(&content, 0, 0);
if( (pCfg->diffFlags & DIFF_SHOW_VERS)!=0 ){
diff_print_versions("(undo)", "(workdir)", pCfg);
}
while( db_step(&q)==SQLITE_ROW ){
char *zFullName;
const char *zFile = (const char*)db_column_text(&q, 0);
if( !file_dir_match(pFileDir, zFile) ) continue;
zFullName = mprintf("%s%s", g.zLocalRoot, zFile);
db_column_blob(&q, 1, &content);
diff_file(&content, zFullName, zFile, pCfg, 0);
|
| ︙ | ︙ | |||
1032 1033 1034 1035 1036 1037 1038 |
manifest_file_rewind(pFrom);
pFromFile = manifest_file_next(pFrom,0);
pTo = manifest_get_by_name(zTo, 0);
manifest_file_rewind(pTo);
pToFile = manifest_file_next(pTo,0);
if( (pCfg->diffFlags & DIFF_SHOW_VERS)!=0 ){
diff_print_versions(zFrom, zTo, pCfg);
| | | 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 |
manifest_file_rewind(pFrom);
pFromFile = manifest_file_next(pFrom,0);
pTo = manifest_get_by_name(zTo, 0);
manifest_file_rewind(pTo);
pToFile = manifest_file_next(pTo,0);
if( (pCfg->diffFlags & DIFF_SHOW_VERS)!=0 ){
diff_print_versions(zFrom, zTo, pCfg);
}
while( pFromFile || pToFile ){
int cmp;
if( pFromFile==0 ){
cmp = +1;
}else if( pToFile==0 ){
cmp = -1;
}else{
|
| ︙ | ︙ | |||
1248 1249 1250 1251 1252 1253 1254 | ** as binary ** --branch BRANCH Show diff of all changes on BRANCH ** --brief Show filenames only ** -b|--browser Show the diff output in a web-browser ** --by Shorthand for "--browser -y" ** -ci|--checkin VERSION Show diff of all changes in VERSION ** --command PROG External diff program. Overrides "diff-command" | | | | 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 | ** as binary ** --branch BRANCH Show diff of all changes on BRANCH ** --brief Show filenames only ** -b|--browser Show the diff output in a web-browser ** --by Shorthand for "--browser -y" ** -ci|--checkin VERSION Show diff of all changes in VERSION ** --command PROG External diff program. Overrides "diff-command" ** -c|--context N Show N lines of context around each change, ** with negative N meaning show all content ** --dark Use dark mode for the Tcl/Tk-based GUI and HTML ** --diff-binary BOOL Include binary files with external commands ** --exec-abs-paths Force absolute path names on external commands ** --exec-rel-paths Force relative path names on external commands ** -r|--from VERSION Select VERSION as source for the diff ** -w|--ignore-all-space Ignore white space when comparing lines ** -i|--internal Use internal diff logic |
| ︙ | ︙ | |||
1381 1382 1383 1384 1385 1386 1387 |
}
fossil_free(pFileDir[i].zName);
}
fossil_free(pFileDir);
}
diff_end(&DCfg, 0);
if ( DCfg.diffFlags & DIFF_NUMSTAT ){
| | | 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 |
}
fossil_free(pFileDir[i].zName);
}
fossil_free(pFileDir);
}
diff_end(&DCfg, 0);
if ( DCfg.diffFlags & DIFF_NUMSTAT ){
fossil_print("%10d %10d TOTAL over %d changed files\n",
g.diffCnt[1], g.diffCnt[2], g.diffCnt[0]);
}
}
/*
** WEBPAGE: vpatch
** URL: /vpatch?from=FROM&to=TO
|
| ︙ | ︙ |
Changes to src/dispatch.c.
| ︙ | ︙ | |||
451 452 453 454 455 456 457 |
aIndent[iLevel] = nIndent;
azEnd[iLevel] = zEndUL;
if( wantP ){
blob_append(pHtml,"<p>", 3);
wantP = 0;
}
blob_append(pHtml, "<ul>\n", 5);
| | | 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 |
aIndent[iLevel] = nIndent;
azEnd[iLevel] = zEndUL;
if( wantP ){
blob_append(pHtml,"<p>", 3);
wantP = 0;
}
blob_append(pHtml, "<ul>\n", 5);
}else if( isDT
|| zHelp[nIndent]=='-'
|| hasGap(zHelp+nIndent,i-nIndent) ){
iLevel++;
aIndent[iLevel] = nIndent;
azEnd[iLevel] = zEndDL;
wantP = 0;
blob_append(pHtml, "<blockquote><dl>\n", -1);
|
| ︙ | ︙ | |||
545 546 547 548 549 550 551 |
if( c=='[' && (x = help_is_link(zHelp+i, 100000))!=0 ){
if( i>0 ) blob_append(pText, zHelp, i);
zHelp += i+2;
blob_append(pText, zHelp, x-3);
zHelp += x-1;
i = -1;
continue;
| | | | 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 |
if( c=='[' && (x = help_is_link(zHelp+i, 100000))!=0 ){
if( i>0 ) blob_append(pText, zHelp, i);
zHelp += i+2;
blob_append(pText, zHelp, x-3);
zHelp += x-1;
i = -1;
continue;
}
}
if( i>0 ){
blob_append(pText, zHelp, i);
}
}
/*
** Display help for all commands based on provided flags.
*/
static void display_all_help(int mask, int useHtml, int rawOut){
int i;
|
| ︙ | ︙ | |||
633 634 635 636 637 638 639 | ** ** Show help text for commands and pages. Useful for proof-reading. ** Defaults to just the CLI commands. Specify --www to see only the ** web pages, or --everything to see both commands and pages. ** ** Options: ** -a|--aliases Show aliases | | | 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 | ** ** Show help text for commands and pages. Useful for proof-reading. ** Defaults to just the CLI commands. Specify --www to see only the ** web pages, or --everything to see both commands and pages. ** ** Options: ** -a|--aliases Show aliases ** -e|--everything Show all commands and pages. Omit aliases to ** avoid duplicates. ** -h|--html Transform output to HTML ** -o|--options Show global options ** -r|--raw No output formatting ** -s|--settings Show settings ** -t|--test Include test- commands ** -w|--www Show WWW pages |
| ︙ | ︙ | |||
659 660 661 662 663 664 665 |
CMDFLAG_ALIAS | CMDFLAG_SETTING | CMDFLAG_TEST;
}
if( find_option("settings","s",0) ){
mask = CMDFLAG_SETTING;
}
if( find_option("aliases","a",0) ){
mask = CMDFLAG_ALIAS;
| | | 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 |
CMDFLAG_ALIAS | CMDFLAG_SETTING | CMDFLAG_TEST;
}
if( find_option("settings","s",0) ){
mask = CMDFLAG_SETTING;
}
if( find_option("aliases","a",0) ){
mask = CMDFLAG_ALIAS;
}
if( find_option("test","t",0) ){
mask |= CMDFLAG_TEST;
}
display_all_help(mask, useHtml, rawOut);
}
/*
|
| ︙ | ︙ | |||
766 767 768 769 770 771 772 |
iLast = FOSSIL_FIRST_CMD-1;
}else{
iFirst = FOSSIL_FIRST_CMD;
iLast = MX_COMMAND-1;
}
while( n<nArray ){
| | | 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 |
iLast = FOSSIL_FIRST_CMD-1;
}else{
iFirst = FOSSIL_FIRST_CMD;
iLast = MX_COMMAND-1;
}
while( n<nArray ){
bestScore = mxScore;
for(i=iFirst; i<=iLast; i++){
m = edit_distance(zIn, aCommand[i].zName);
if( m<mnScore ) continue;
if( m==mnScore ){
azArray[n++] = aCommand[i].zName;
if( n>=nArray ) return n;
}else if( m<bestScore ){
|
| ︙ | ︙ | |||
895 896 897 898 899 900 901 |
@ <li><a href="%R/help?cmd=%s(z)">%s(zBoldOn)%s(z)%s(zBoldOff)</a>
/* Output aliases */
if( occHelp[aCommand[i].iHelp] > 1 ){
int j;
int aliases[MX_HELP_DUP], nAliases=0;
for(j=0; j<occHelp[aCommand[i].iHelp]; j++){
if( bktHelp[aCommand[i].iHelp][j] != i ){
| | > | 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 |
@ <li><a href="%R/help?cmd=%s(z)">%s(zBoldOn)%s(z)%s(zBoldOff)</a>
/* Output aliases */
if( occHelp[aCommand[i].iHelp] > 1 ){
int j;
int aliases[MX_HELP_DUP], nAliases=0;
for(j=0; j<occHelp[aCommand[i].iHelp]; j++){
if( bktHelp[aCommand[i].iHelp][j] != i ){
if( aCommand[bktHelp[aCommand[i].iHelp][j]].eCmdFlags
& CMDFLAG_ALIAS ){
aliases[nAliases++] = bktHelp[aCommand[i].iHelp][j];
}
}
}
if( nAliases>0 ){
int k;
@(\
|
| ︙ | ︙ | |||
985 986 987 988 989 990 991 |
style_set_current_feature("test");
style_header("All Help Text");
@ <dl>
/* Fill in help string buckets */
for(i=0; i<MX_COMMAND; i++){
if(aCommand[i].eCmdFlags & CMDFLAG_HIDDEN) continue;
bktHelp[aCommand[i].iHelp][occHelp[aCommand[i].iHelp]++] = i;
| | | 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 |
style_set_current_feature("test");
style_header("All Help Text");
@ <dl>
/* Fill in help string buckets */
for(i=0; i<MX_COMMAND; i++){
if(aCommand[i].eCmdFlags & CMDFLAG_HIDDEN) continue;
bktHelp[aCommand[i].iHelp][occHelp[aCommand[i].iHelp]++] = i;
}
for(i=0; i<MX_COMMAND; i++){
const char *zDesc;
unsigned int e = aCommand[i].eCmdFlags;
if( e & CMDFLAG_1ST_TIER ){
zDesc = "1st tier command";
}else if( e & CMDFLAG_2ND_TIER ){
zDesc = "2nd tier command";
|
| ︙ | ︙ | |||
1037 1038 1039 1040 1041 1042 1043 |
}else if( e & CMDFLAG_WEBPAGE ){
if( e & CMDFLAG_RAWCONTENT ){
zDesc = "raw-content web page";
}else{
zDesc = "web page";
}
}
| | | 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 |
}else if( e & CMDFLAG_WEBPAGE ){
if( e & CMDFLAG_RAWCONTENT ){
zDesc = "raw-content web page";
}else{
zDesc = "web page";
}
}
@ <dt><big><b>%s(aCommand[bktHelp[aCommand[i].iHelp][j]].zName)</b>
@</big> (%s(zDesc))</dt>
}
@ <p><dd>
help_to_html(aCommand[i].zHelp, cgi_output_blob());
@ </dd><p>
occHelp[aCommand[i].iHelp] = 0;
|
| ︙ | ︙ | |||
1116 1117 1118 1119 1120 1121 1122 | /* ** Documentation on universal command-line options. */ /* @-comment: # */ static const char zOptions[] = @ Command-line options common to all commands: | | | | | 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 | /* ** Documentation on universal command-line options. */ /* @-comment: # */ static const char zOptions[] = @ Command-line options common to all commands: @ @ --args FILENAME Read additional arguments and options from FILENAME @ --case-sensitive BOOL Set case sensitivity for file names @ --cgitrace Active CGI tracing @ --chdir PATH Change to PATH before performing any operations @ --comfmtflags VALUE Set comment formatting flags to VALUE @ --comment-format VALUE Alias for --comfmtflags @ --errorlog FILENAME Log errors to FILENAME @ --help Show help on the command rather than running it @ --httptrace Trace outbound HTTP requests @ --localtime Display times using the local timezone @ --nocgi Do not act as CGI @ --no-th-hook Do not run TH1 hooks @ --quiet Reduce the amount of output @ --sqlstats Show SQL usage statistics when done |
| ︙ | ︙ | |||
1485 1486 1487 1488 1489 1490 1491 | helptextVtab_cursor *pCur = (helptextVtab_cursor*)cur; return pCur->iRowid>=MX_COMMAND; } /* ** This method is called to "rewind" the helptextVtab_cursor object back ** to the first row of output. This method is always called at least | | | | 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 |
helptextVtab_cursor *pCur = (helptextVtab_cursor*)cur;
return pCur->iRowid>=MX_COMMAND;
}
/*
** This method is called to "rewind" the helptextVtab_cursor object back
** to the first row of output. This method is always called at least
** once prior to any call to helptextVtabColumn() or helptextVtabRowid() or
** helptextVtabEof().
*/
static int helptextVtabFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
helptextVtab_cursor *pCur = (helptextVtab_cursor *)pVtabCursor;
pCur->iRowid = 1;
return SQLITE_OK;
}
|
| ︙ | ︙ | |||
1514 1515 1516 1517 1518 1519 1520 |
){
pIdxInfo->estimatedCost = (double)MX_COMMAND;
pIdxInfo->estimatedRows = MX_COMMAND;
return SQLITE_OK;
}
/*
| | | 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 |
){
pIdxInfo->estimatedCost = (double)MX_COMMAND;
pIdxInfo->estimatedRows = MX_COMMAND;
return SQLITE_OK;
}
/*
** This following structure defines all the methods for the
** virtual table.
*/
static sqlite3_module helptextVtabModule = {
/* iVersion */ 0,
/* xCreate */ 0, /* Helptext is eponymous and read-only */
/* xConnect */ helptextVtabConnect,
/* xBestIndex */ helptextVtabBestIndex,
|
| ︙ | ︙ |
Changes to src/doc.c.
| ︙ | ︙ | |||
339 340 341 342 343 344 345 |
static char * zList = 0;
static char const * zEnd = 0;
static int once = 0;
char * z;
int tokenizerState /* 0=expecting a key, 1=skip next token,
** 2=accept next token */;
if(once==0){
| | | 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
static char * zList = 0;
static char const * zEnd = 0;
static int once = 0;
char * z;
int tokenizerState /* 0=expecting a key, 1=skip next token,
** 2=accept next token */;
if(once==0){
once = 1;
zList = db_get("mimetypes",0);
if(zList==0){
return 0;
}
/* Transform zList to simplify the main loop:
replace non-newline spaces with NUL bytes. */
zEnd = zList + strlen(zList);
|
| ︙ | ︙ | |||
727 728 729 730 731 732 733 | ** Transfer content to the output. During the transfer, when text of ** the following form is seen: ** ** href="$ROOT/..." ** action="$ROOT/..." ** href=".../doc/$CURRENT/..." ** | | | | 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 |
** Transfer content to the output. During the transfer, when text of
** the following form is seen:
**
** href="$ROOT/..."
** action="$ROOT/..."
** href=".../doc/$CURRENT/..."
**
** Convert $ROOT to the root URI of the repository, and $CURRENT to the
** version number of the /doc/ document currently being displayed (if any).
** Allow ' in place of " and any case for href or action.
**
** Efforts are made to limit this translation to cases where the text is
** fully contained with an HTML markup element.
*/
void convert_href_and_output(Blob *pIn){
int i, base;
int n = blob_size(pIn);
|
| ︙ | ︙ | |||
1209 1210 1211 1212 1213 1214 1215 | ** ** The intended use case here is to supply an icon for the "fossil ui" ** command. For a permanent website, the recommended process is for ** the admin to set up a project-specific icon and reference that icon ** in the HTML header using a line like: ** ** <link rel="icon" href="URL-FOR-YOUR-ICON" type="MIMETYPE"/> | | | 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 |
**
** The intended use case here is to supply an icon for the "fossil ui"
** command. For a permanent website, the recommended process is for
** the admin to set up a project-specific icon and reference that icon
** in the HTML header using a line like:
**
** <link rel="icon" href="URL-FOR-YOUR-ICON" type="MIMETYPE"/>
**
*/
void favicon_page(void){
Blob icon;
char *zMime;
etag_check(ETAG_CONFIG, 0);
zMime = db_get("icon-mimetype", "image/gif");
|
| ︙ | ︙ |
Changes to src/etag.c.
| ︙ | ︙ | |||
98 99 100 101 102 103 104 | char zBuf[50]; assert( zETag[0]==0 ); /* Only call this routine once! */ if( etagCancelled ) return; /* By default, ETagged URLs never expire since the ETag will change * when the content changes. Approximate this policy as 10 years. */ | | | | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
char zBuf[50];
assert( zETag[0]==0 ); /* Only call this routine once! */
if( etagCancelled ) return;
/* By default, ETagged URLs never expire since the ETag will change
* when the content changes. Approximate this policy as 10 years. */
iMaxAge = 10 * 365 * 24 * 60 * 60;
md5sum_init();
/* Always include the executable ID as part of the hash */
md5sum_step_text("exe-id: ", -1);
md5sum_step_text(fossil_exe_id(), -1);
md5sum_step_text("\n", 1);
if( (eFlags & ETAG_HASH)!=0 && zHash ){
md5sum_step_text("hash: ", -1);
md5sum_step_text(zHash, -1);
md5sum_step_text("\n", 1);
iMaxAge = 0;
}
if( eFlags & ETAG_DATA ){
|
| ︙ | ︙ | |||
208 209 210 211 212 213 214 |
/* Check to see the If-Modified-Since constraint is satisfied */
zIfModifiedSince = P("HTTP_IF_MODIFIED_SINCE");
if( zIfModifiedSince==0 ) return;
x = cgi_rfc822_parsedate(zIfModifiedSince);
if( x<mtime ) return;
| | | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
/* Check to see the If-Modified-Since constraint is satisfied */
zIfModifiedSince = P("HTTP_IF_MODIFIED_SINCE");
if( zIfModifiedSince==0 ) return;
x = cgi_rfc822_parsedate(zIfModifiedSince);
if( x<mtime ) return;
#if 0
/* If the Fossil executable is more recent than If-Modified-Since,
** go ahead and regenerate the resource. */
if( file_mtime(g.nameOfExe, ExtFILE)>x ) return;
#endif
/* If we reach this point, it means that the resource has not changed
** and that we should generate a 304 Not Modified reply */
|
| ︙ | ︙ | |||
242 243 244 245 246 247 248 |
/* Return the last-modified time in seconds since 1970. Or return 0 if
** there is no last-modified time.
*/
sqlite3_int64 etag_mtime(void){
return iEtagMtime;
}
| | | 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
/* Return the last-modified time in seconds since 1970. Or return 0 if
** there is no last-modified time.
*/
sqlite3_int64 etag_mtime(void){
return iEtagMtime;
}
/*
** COMMAND: test-etag
**
** Usage: fossil test-etag -key KEY-NUMBER -hash HASH
**
** Generate an etag given a KEY-NUMBER and/or a HASH.
**
** KEY-NUMBER is some combination of:
|
| ︙ | ︙ |
Changes to src/export.c.
| ︙ | ︙ | |||
447 448 449 450 451 452 453 |
}while( (rid = bag_next(vers, rid))!=0 );
}
}
}
/* This is the original header command (and hence documentation) for
** the "fossil export" command:
| | | 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 |
}while( (rid = bag_next(vers, rid))!=0 );
}
}
}
/* This is the original header command (and hence documentation) for
** the "fossil export" command:
**
** Usage: %fossil export --git ?OPTIONS? ?REPOSITORY?
**
** Write an export of all check-ins to standard output. The export is
** written in the git-fast-export file format assuming the --git option is
** provided. The git-fast-export format is currently the only VCS
** interchange format supported, though other formats may be added in
** the future.
|
| ︙ | ︙ | |||
1002 1003 1004 1005 1006 1007 1008 |
db_bind_int(&sIns, ":isfile", isFile!=0);
db_step(&sIns);
db_reset(&sIns);
return mprintf(":%d", db_last_insert_rowid());
}
/* This is the SHA3-256 hash of an empty file */
| | | 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 |
db_bind_int(&sIns, ":isfile", isFile!=0);
db_step(&sIns);
db_reset(&sIns);
return mprintf(":%d", db_last_insert_rowid());
}
/* This is the SHA3-256 hash of an empty file */
static const char zEmptySha3[] =
"a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a";
/*
** Export a single file named by zUuid.
**
** Return 0 on success and non-zero on any failure.
**
|
| ︙ | ︙ | |||
1035 1036 1037 1038 1039 1040 1041 |
}else{
rc = content_get(rid, &data);
if( rc==0 ){
if( bPhantomOk ){
blob_init(&data, 0, 0);
gitmirror_message(VERB_EXTRA, "missing file: %s\n", zUuid);
zUuid = zEmptySha3;
| | | 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 |
}else{
rc = content_get(rid, &data);
if( rc==0 ){
if( bPhantomOk ){
blob_init(&data, 0, 0);
gitmirror_message(VERB_EXTRA, "missing file: %s\n", zUuid);
zUuid = zEmptySha3;
}else{
return 1;
}
}
}
zMark = gitmirror_find_mark(zUuid, 1, 1);
if( zMark[0]==':' ){
fprintf(xCmd, "blob\nmark %s\ndata %d\n", zMark, blob_size(&data));
|
| ︙ | ︙ | |||
1348 1349 1350 1351 1352 1353 1354 |
int i;
zCmd = "git symbolic-ref --short HEAD";
gitmirror_message(VERB_NORMAL, "%s\n", zCmd);
xCmd = popen(zCmd, "r");
if( xCmd==0 ){
fossil_fatal("git command failed: %s", zCmd);
}
| | | | 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 |
int i;
zCmd = "git symbolic-ref --short HEAD";
gitmirror_message(VERB_NORMAL, "%s\n", zCmd);
xCmd = popen(zCmd, "r");
if( xCmd==0 ){
fossil_fatal("git command failed: %s", zCmd);
}
z = fgets(zLine, sizeof(zLine), xCmd);
pclose(xCmd);
if( z==0 ){
fossil_fatal("no output from \"%s\"", zCmd);
}
for(i=0; z[i] && !fossil_isspace(z[i]); i++){}
z[i] = 0;
zMainBr = fossil_strdup(z);
}
return zMainBr;
}
/*
** Implementation of the "fossil git export" command.
*/
void gitmirror_export_command(void){
const char *zLimit; /* Text of the --limit flag */
int nLimit = 0x7fffffff; /* Numeric value of the --limit flag */
|
| ︙ | ︙ | |||
1434 1435 1436 1437 1438 1439 1440 |
/* Make sure GIT has been initialized */
z = mprintf("%s/.git", zMirror);
if( !file_isdir(z, ExtFILE) ){
zMainBr = gitmirror_init(zMirror, zMainBr);
bNeedRepack = 1;
}
fossil_free(z);
| | | 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 |
/* Make sure GIT has been initialized */
z = mprintf("%s/.git", zMirror);
if( !file_isdir(z, ExtFILE) ){
zMainBr = gitmirror_init(zMirror, zMainBr);
bNeedRepack = 1;
}
fossil_free(z);
/* Make sure the .mirror_state subdirectory exists */
z = mprintf("%s/.mirror_state", zMirror);
rc = file_mkdir(z, ExtFILE, 0);
if( rc ) fossil_fatal("cannot create directory \"%s\"", z);
fossil_free(z);
/* Attach the .mirror_state/db database */
|
| ︙ | ︙ | |||
1741 1742 1743 1744 1745 1746 1747 |
char *zSql;
int bQuiet = 0;
int bByAll = 0; /* Undocumented option meaning this command was invoked
** from "fossil all" and should modify output accordingly */
db_find_and_open_repository(0, 0);
bQuiet = find_option("quiet","q",0)!=0;
| | | 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 |
char *zSql;
int bQuiet = 0;
int bByAll = 0; /* Undocumented option meaning this command was invoked
** from "fossil all" and should modify output accordingly */
db_find_and_open_repository(0, 0);
bQuiet = find_option("quiet","q",0)!=0;
bByAll = find_option("by-all",0,0)!=0;
verify_all_options();
zMirror = db_get("last-git-export-repo", 0);
if( zMirror==0 ){
if( bQuiet ) return;
if( bByAll ) return;
fossil_print("Git mirror: none\n");
return;
|
| ︙ | ︙ | |||
1854 1855 1856 1857 1858 1859 1860 | ** mapped into this name. "master" is used if ** this option is omitted. ** -q|--quiet Reduce output. Repeat for even less output. ** -v|--verbose More output ** ** > fossil git import MIRROR ** | | | 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 | ** mapped into this name. "master" is used if ** this option is omitted. ** -q|--quiet Reduce output. Repeat for even less output. ** -v|--verbose More output ** ** > fossil git import MIRROR ** ** TBD... ** ** > fossil git status ** ** Show the status of the current Git mirror, if there is one. ** ** -q|--quiet No output if there is nothing to report */ |
| ︙ | ︙ |
Changes to src/file.c.
| ︙ | ︙ | |||
2243 2244 2245 2246 2247 2248 2249 |
/*
** Return non-NULL if zFilename contains pathname elements that
** are reserved on Windows. The returned string is the disallowed
** path element.
*/
const char *file_is_win_reserved(const char *zPath){
| | | 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 |
/*
** Return non-NULL if zFilename contains pathname elements that
** are reserved on Windows. The returned string is the disallowed
** path element.
*/
const char *file_is_win_reserved(const char *zPath){
static const char *const azRes[] = { "CON","PRN","AUX","NUL","COM","LPT" };
static char zReturn[5];
int i;
while( zPath[0] ){
for(i=0; i<count(azRes); i++){
if( sqlite3_strnicmp(zPath, azRes[i], 3)==0
&& ((i>=4 && fossil_isdigit(zPath[3])
&& (zPath[4]=='/' || zPath[4]=='.' || zPath[4]==0))
|
| ︙ | ︙ |
Changes to src/fileedit.c.
| ︙ | ︙ | |||
434 435 436 437 438 439 440 | ** pCI's ownership is not modified. ** ** This function validates pCI's state and fails if any validation ** fails. ** ** On error, returns false (0) and, if pErr is not NULL, writes a ** diagnostic message there. | | | 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 | ** pCI's ownership is not modified. ** ** This function validates pCI's state and fails if any validation ** fails. ** ** On error, returns false (0) and, if pErr is not NULL, writes a ** diagnostic message there. ** ** Returns true on success. If pRid is not NULL, the RID of the ** resulting manifest is written to *pRid. ** ** The check-in process is largely influenced by pCI->flags, and that ** must be populated before calling this. See the fossil_cimini_flags ** enum for the docs for each flag. */ |
| ︙ | ︙ | |||
571 572 573 574 575 576 577 |
&& blob_size(&pCI->fileContent)>0
){
/* Convert to the requested EOL style. Note that this inherently
** runs a risk of breaking content, e.g. string literals which
** contain embedded newlines. Note that HTML5 specifies that
** form-submitted TEXTAREA content gets normalized to CRLF-style:
**
| | | 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 |
&& blob_size(&pCI->fileContent)>0
){
/* Convert to the requested EOL style. Note that this inherently
** runs a risk of breaking content, e.g. string literals which
** contain embedded newlines. Note that HTML5 specifies that
** form-submitted TEXTAREA content gets normalized to CRLF-style:
**
** https://html.spec.whatwg.org/#the-textarea-element
*/
const int pseudoBinary = LOOK_LONG | LOOK_NUL;
const int lookFlags = LOOK_CRLF | LOOK_LONE_LF | pseudoBinary;
const int lookNew = looks_like_utf8( &pCI->fileContent, lookFlags );
if(!(pseudoBinary & lookNew)){
int rehash = 0;
/*fossil_print("lookNew=%08x\n",lookNew);*/
|
| ︙ | ︙ | |||
979 980 981 982 983 984 985 |
char ** zRevUuid,
int * pVid,
const char * zFilename,
int * frid){
char * zFileUuid = 0; /* file content UUID */
const int checkFile = zFilename!=0 || frid!=0;
int vid = 0;
| | | 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 |
char ** zRevUuid,
int * pVid,
const char * zFilename,
int * frid){
char * zFileUuid = 0; /* file content UUID */
const int checkFile = zFilename!=0 || frid!=0;
int vid = 0;
if(checkFile && !fileedit_ajax_check_filename(zFilename)){
return 0;
}
vid = symbolic_name_to_rid(zRev, "ci");
if(0==vid){
ajax_route_error(404,"Cannot resolve name as a check-in: %s",
zRev);
|
| ︙ | ︙ | |||
1174 1175 1176 1177 1178 1179 1180 |
**
** Intended to be used only by /filepage and /filepage_commit.
*/
static int fileedit_setup_cimi_from_p(CheckinMiniInfo * p, Blob * pErr,
int * bIsMissingArg){
char * zFileUuid = 0; /* UUID of file content */
const char * zFlag; /* generic flag */
| | | 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 |
**
** Intended to be used only by /filepage and /filepage_commit.
*/
static int fileedit_setup_cimi_from_p(CheckinMiniInfo * p, Blob * pErr,
int * bIsMissingArg){
char * zFileUuid = 0; /* UUID of file content */
const char * zFlag; /* generic flag */
int rc = 0, vid = 0, frid = 0; /* result code, check-in/file rids */
#define fail(EXPR) blob_appendf EXPR; goto end_fail
zFlag = PD("filename",P("fn"));
if(zFlag==0 || !*zFlag){
rc = 400;
if(bIsMissingArg){
*bIsMissingArg = 1;
|
| ︙ | ︙ | |||
1369 1370 1371 1372 1373 1374 1375 |
if(i++){
CX(",");
}
CX("%!j", zFilename);
}
}
db_finalize(&q);
| | | 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 |
if(i++){
CX(",");
}
CX("%!j", zFilename);
}
}
db_finalize(&q);
CX("]}");
}
/*
** AJAX route /fileedit?ajax=filelist
**
** Fetches a JSON-format list of leaves and/or filenames for use in
** creating a file selection list in /fileedit. It has different modes
|
| ︙ | ︙ | |||
1425 1426 1427 1428 1429 1430 1431 | } } /* ** AJAX route /fileedit?ajax=commit ** ** Required query parameters: | | | | 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 | } } /* ** AJAX route /fileedit?ajax=commit ** ** Required query parameters: ** ** filename=FILENAME ** checkin=Parent check-in UUID ** content=text ** comment=non-empty text ** ** Optional query parameters: ** ** comment_mimetype=text (NOT currently honored) ** ** dry_run=int (1 or 0) ** ** include_manifest=int (1 or 0), whether to include ** the generated manifest in the response. ** ** ** User must have Write permissions to use this page. ** ** Responds with JSON (with some state repeated ** from the input in order to avoid certain race conditions ** client-side): ** |
| ︙ | ︙ | |||
1575 1576 1577 1578 1579 1580 1581 | ** use of the name parameter. ** ** Which additional parameters are used by each distinct ajax route ** is an internal implementation detail and may change with any ** given build of this code. An unknown "name" value triggers an ** error, as documented for ajax_route_error(). */ | | | 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 |
** use of the name parameter.
**
** Which additional parameters are used by each distinct ajax route
** is an internal implementation detail and may change with any
** given build of this code. An unknown "name" value triggers an
** error, as documented for ajax_route_error().
*/
/* Allow no access to this page without check-in privilege */
login_check_credentials();
if( !g.perm.Write ){
if(zAjax!=0){
ajax_route_error(403, "Write permissions required.");
}else{
login_needed(g.anon.Write);
|
| ︙ | ︙ | |||
1668 1669 1670 1671 1672 1673 1674 |
** have a common, page-specific container we can filter our CSS
** selectors, but we do have the BODY, which we can decorate with
** whatever CSS we wish...
*/
style_script_begin(__FILE__,__LINE__);
CX("document.body.classList.add('fileedit');\n");
style_script_end();
| | | 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 |
** have a common, page-specific container we can filter our CSS
** selectors, but we do have the BODY, which we can decorate with
** whatever CSS we wish...
*/
style_script_begin(__FILE__,__LINE__);
CX("document.body.classList.add('fileedit');\n");
style_script_end();
/* Status bar */
CX("<div id='fossil-status-bar' "
"title='Status message area. Double-click to clear them.'>"
"Status messages will go here.</div>\n"
/* will be moved into the tab container via JS */);
CX("<div id='fileedit-edit-status'>"
|
| ︙ | ︙ | |||
1937 1938 1939 1940 1941 1942 1943 |
*/
style_select_list_str("comment-mimetype", "comment_mimetype",
"Comment style:",
"Specify how fossil will interpret the "
"comment string.",
NULL,
"Fossil", "text/x-fossil-wiki",
| | | 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 |
*/
style_select_list_str("comment-mimetype", "comment_mimetype",
"Comment style:",
"Specify how fossil will interpret the "
"comment string.",
NULL,
"Fossil", "text/x-fossil-wiki",
"Markdown", "text/x-markdown",
"Plain text", "text/plain",
NULL);
CX("</div>\n");
}
CX("<div class='fileedit-hint flex-container flex-row'>"
"(Warning: switching from multi- to single-line mode will "
"strip out all newlines!)</div>");
|
| ︙ | ︙ |
Changes to src/graph.c.
| ︙ | ︙ | |||
309 310 311 312 313 314 315 |
dist = i - iNearto;
if( dist<0 ) dist = -dist;
if( dist<iBestDist ){
iBestDist = dist;
iBest = i;
}
}
| | | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
dist = i - iNearto;
if( dist<0 ) dist = -dist;
if( dist<iBestDist ){
iBestDist = dist;
iBest = i;
}
}
/* If no match, consider all possible rails */
if( iBestDist>1000 ){
for(i=0; i<=p->mxRail+1; i++){
int dist;
if( inUseMask & BIT(i) ) continue;
if( iNearto<=0 ){
iBest = i;
|
| ︙ | ︙ | |||
537 538 539 540 541 542 543 |
** the aParent[] array.
*/
if( (tmFlags & (TIMELINE_DISJOINT|TIMELINE_XMERGE))!=0 ){
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
for(i=1; i<pRow->nParent; i++){
GraphRow *pParent = hashFind(p, pRow->aParent[i]);
if( pParent==0 ){
| | | | 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 |
** the aParent[] array.
*/
if( (tmFlags & (TIMELINE_DISJOINT|TIMELINE_XMERGE))!=0 ){
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
for(i=1; i<pRow->nParent; i++){
GraphRow *pParent = hashFind(p, pRow->aParent[i]);
if( pParent==0 ){
memmove(pRow->aParent+i, pRow->aParent+i+1,
sizeof(pRow->aParent[0])*(pRow->nParent-i-1));
pRow->nParent--;
if( i<pRow->nNonCherrypick ){
pRow->nNonCherrypick--;
}else{
pRow->nCherrypick--;
}
i--;
}
}
}
}
/* Put the deepest (earliest) merge parent first in the list.
** An off-screen merge parent is considered deepest.
*/
for(pRow=p->pFirst; pRow; pRow=pRow->pNext ){
if( pRow->nParent<=1 ) continue;
for(i=1; i<pRow->nParent; i++){
GraphRow *pParent = hashFind(p, pRow->aParent[i]);
|
| ︙ | ︙ | |||
938 939 940 941 942 943 944 |
/* The parent branch from which this branch emerges is on the
** same rail as pRow. Do not shift as that would stack a child
** branch directly above its parent. */
continue;
}
/* All clear. Make the translation
| | | 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 |
/* The parent branch from which this branch emerges is on the
** same rail as pRow. Do not shift as that would stack a child
** branch directly above its parent. */
continue;
}
/* All clear. Make the translation
*/
for(pLoop=pRow; pLoop && pLoop->idx<=pBottom->idx; pLoop=pLoop->pNext){
if( pLoop->iRail==iFrom ){
pLoop->iRail = iTo;
pLoop->aiRiser[iTo] = pLoop->aiRiser[iFrom];
pLoop->aiRiser[iFrom] = -1;
}
}
|
| ︙ | ︙ |
Changes to src/http.c.
| ︙ | ︙ | |||
96 97 98 99 100 101 102 | ** sha1_shared_secret()), not the original password. So convert the ** password to its SHA1 encoding if it isn't already a SHA1 hash. ** ** We assume that a hexadecimal string of exactly 40 characters is a ** SHA1 hash, not an original password. If a user has a password which ** just happens to be a 40-character hex string, then this routine won't ** be able to distinguish it from a hash, the translation will not be | | | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
** sha1_shared_secret()), not the original password. So convert the
** password to its SHA1 encoding if it isn't already a SHA1 hash.
**
** We assume that a hexadecimal string of exactly 40 characters is a
** SHA1 hash, not an original password. If a user has a password which
** just happens to be a 40-character hex string, then this routine won't
** be able to distinguish it from a hash, the translation will not be
** performed, and the sync won't work.
*/
if( zPw && zPw[0] && (strlen(zPw)!=40 || !validate16(zPw,40)) ){
const char *zProjectCode = 0;
if( g.url.flags & URL_USE_PARENT ){
zProjectCode = db_get("parent-project-code", 0);
}else{
zProjectCode = db_get("project-code", 0);
|
| ︙ | ︙ | |||
256 257 258 259 260 261 262 |
blob_write_to_file(pSend, zUplink);
if( g.fHttpTrace ){
fossil_print("RUN %s\n", zCmd);
}
rc = fossil_system(zCmd);
if( rc ){
fossil_warning("Transport command failed: %s\n", zCmd);
| | | | 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
blob_write_to_file(pSend, zUplink);
if( g.fHttpTrace ){
fossil_print("RUN %s\n", zCmd);
}
rc = fossil_system(zCmd);
if( rc ){
fossil_warning("Transport command failed: %s\n", zCmd);
}
fossil_free(zCmd);
file_delete(zUplink);
if( file_size(zDownlink, ExtFILE)<0 ){
blob_zero(pReply);
}else{
blob_read_from_file(pReply, zDownlink, ExtFILE);
file_delete(zDownlink);
}
return rc;
}
/*
** Sign the content in pSend, compress it, and send it to the server
** via HTTP or HTTPS. Get a reply, uncompress the reply, and store the reply
** in pRecv. pRecv is assumed to be uninitialized when
** this routine is called - this routine will initialize it.
|
| ︙ | ︙ |
Changes to src/http_ssl.c.
| ︙ | ︙ | |||
57 58 59 60 61 62 63 | } sException; static int sslNoCertVerify = 0; /* Do not verify SSL certs */ /* This is a self-signed cert in the PEM format that can be used when ** no other certs are available. */ | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | } sException; static int sslNoCertVerify = 0; /* Do not verify SSL certs */ /* This is a self-signed cert in the PEM format that can be used when ** no other certs are available. */ static const char sslSelfCert[] = "-----BEGIN CERTIFICATE-----\n" "MIIDMTCCAhkCFGrDmuJkkzWERP/ITBvzwwI2lv0TMA0GCSqGSIb3DQEBCwUAMFQx\n" "CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJOQzESMBAGA1UEBwwJQ2hhcmxvdHRlMRMw\n" "EQYDVQQKDApGb3NzaWwtU0NNMQ8wDQYDVQQDDAZGb3NzaWwwIBcNMjExMjI3MTEz\n" "MTU2WhgPMjEyMTEyMjcxMTMxNTZaMFQxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJO\n" "QzESMBAGA1UEBwwJQ2hhcmxvdHRlMRMwEQYDVQQKDApGb3NzaWwtU0NNMQ8wDQYD\n" "VQQDDAZGb3NzaWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCCbTU2\n" |
| ︙ | ︙ | |||
81 82 83 84 85 86 87 | "G6wxc4kN9dLK+5S29q3nzl24/qzXoF8P9Re5KBCbrwaHgy+OEEceq5jkmfGFxXjw\n" "pvVCNry5uAhH5NqbXZampUWqiWtM4eTaIPo7Y2mDA1uWhuWtO6F9PsnFJlQHCnwy\n" "s/TsrXk=\n" "-----END CERTIFICATE-----\n"; /* This is the private-key corresponding to the cert above */ | | | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | "G6wxc4kN9dLK+5S29q3nzl24/qzXoF8P9Re5KBCbrwaHgy+OEEceq5jkmfGFxXjw\n" "pvVCNry5uAhH5NqbXZampUWqiWtM4eTaIPo7Y2mDA1uWhuWtO6F9PsnFJlQHCnwy\n" "s/TsrXk=\n" "-----END CERTIFICATE-----\n"; /* This is the private-key corresponding to the cert above */ static const char sslSelfPKey[] = "-----BEGIN PRIVATE KEY-----\n" "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCCbTU26GRQHQqL\n" "q7vyZ0OxpAxmgfAKCxt6eIz+jBi2ZM/CB5vVXWVh2+SkSiWEA3UZiUqXxZlzmS/C\n" "glZdiwLLDJML8B4OiV72oivFH/vJ7+cbvh1dTxnYiHuww7GfQngPrLfefiIYPDk1\n" "GTUJHBQ7Ue477F7F8vKuHdVgwktF/JDM6M60aSqlo2D/oysirrb+dlurTlv0rjsY\n" "Ofq6bLAajoL3qi/vek6DNssoywbge4PfbTgS9g7Gcgncbcet5pvaS12JavhFcd4J\n" "U4Ity49Hl9S/C2MfZ1tE53xVggRwKz4FPj65M5uymTdcxtjKXtCxIE1kKxJxXQh7\n" |
| ︙ | ︙ | |||
204 205 206 207 208 209 210 |
"or the ssl-identity setting.");
return 0; /* no cert available */
}
/*
** Convert an OpenSSL ASN1_TIME to an ISO8601 timestamp.
**
| | | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
"or the ssl-identity setting.");
return 0; /* no cert available */
}
/*
** Convert an OpenSSL ASN1_TIME to an ISO8601 timestamp.
**
** Per RFC 5280, ASN1 timestamps in X.509 certificates must
** be in UTC (Zulu timezone) with no fractional seconds.
**
** If showUtc==1, add " UTC" at the end of the returned string. This is
** not ISO8601-compliant, but makes the displayed value more user-friendly.
*/
static const char *ssl_asn1time_to_iso8601(ASN1_TIME *asn1_time,
int showUtc){
|
| ︙ | ︙ | |||
410 411 412 413 414 415 416 |
** Invoke this routine to disable SSL cert verification. After
** this call is made, any SSL cert that the server provides will
** be accepted. Communication will still be encrypted, but the
** client has no way of knowing whether it is talking to the
** real server or a man-in-the-middle imposter.
*/
void ssl_disable_cert_verification(void){
| | | 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 |
** Invoke this routine to disable SSL cert verification. After
** this call is made, any SSL cert that the server provides will
** be accepted. Communication will still be encrypted, but the
** client has no way of knowing whether it is talking to the
** real server or a man-in-the-middle imposter.
*/
void ssl_disable_cert_verification(void){
sslNoCertVerify = 1;
}
/*
** Open an SSL connection as a client that is to connect to the server
** identified by pUrlData.
**
* The identify of the server is determined as follows:
|
| ︙ | ︙ | |||
563 564 565 566 567 568 569 |
X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 0, XN_FLAG_ONELINE);
BIO_printf(mem, "\n notBefore: %s",
ssl_asn1time_to_iso8601(X509_get_notBefore(cert), 1));
BIO_printf(mem, "\n notAfter: %s",
ssl_asn1time_to_iso8601(X509_get_notAfter(cert), 1));
BIO_printf(mem, "\n sha256: %s", zHash);
desclen = BIO_get_mem_data(mem, &desc);
| | | | 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 |
X509_NAME_print_ex(mem, X509_get_issuer_name(cert), 0, XN_FLAG_ONELINE);
BIO_printf(mem, "\n notBefore: %s",
ssl_asn1time_to_iso8601(X509_get_notBefore(cert), 1));
BIO_printf(mem, "\n notAfter: %s",
ssl_asn1time_to_iso8601(X509_get_notAfter(cert), 1));
BIO_printf(mem, "\n sha256: %s", zHash);
desclen = BIO_get_mem_data(mem, &desc);
prompt = mprintf("Unable to verify SSL cert from %s\n%.*s\n"
"accept this cert and continue (y/N/fingerprint)? ",
pUrlData->name, desclen, desc);
BIO_free(mem);
prompt_user(prompt, &ans);
free(prompt);
cReply = blob_str(&ans)[0];
if( cReply!='y' && cReply!='Y'
&& fossil_stricmp(blob_str(&ans),zHash)!=0
){
X509_free(cert);
|
| ︙ | ︙ | |||
1183 1184 1185 1186 1187 1188 1189 |
/*
** Return the OpenSSL version number being used. Space to hold
** this name is obtained from fossil_malloc() and should be
** freed by the caller.
*/
char *fossil_openssl_version(void){
| | | 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 |
/*
** Return the OpenSSL version number being used. Space to hold
** this name is obtained from fossil_malloc() and should be
** freed by the caller.
*/
char *fossil_openssl_version(void){
#if defined(FOSSIL_ENABLE_SSL)
return mprintf("%s (0x%09x)\n",
SSLeay_version(SSLEAY_VERSION), OPENSSL_VERSION_NUMBER);
#else
return mprintf("none");
#endif
}
|
Changes to src/import.c.
| ︙ | ︙ | |||
815 816 817 818 819 820 821 |
gg.fromLoaded = 1;
}else
if( strncmp(zLine, "N ", 2)==0 ){
/* No-op */
}else
if( strncmp(zLine, "property branch-nick ", 21)==0 ){
/* Breezy uses this property to store the branch name.
| | | 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 |
gg.fromLoaded = 1;
}else
if( strncmp(zLine, "N ", 2)==0 ){
/* No-op */
}else
if( strncmp(zLine, "property branch-nick ", 21)==0 ){
/* Breezy uses this property to store the branch name.
** It has two values. Integer branch number, then the
** user-readable branch name. */
z = &zLine[21];
next_token(&z);
fossil_free(gg.zBranch);
gg.zBranch = fossil_strdup(next_token(&z));
}else
if( strncmp(zLine, "property rebase-of ", 19)==0 ){
|
| ︙ | ︙ |
Changes to src/info.c.
| ︙ | ︙ | |||
2500 2501 2502 2503 2504 2505 2506 |
) ){
if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
page_tree();
return;
}
/* No directory found, look for an historic version of the file
** that was subsequently deleted. */
| | | 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 |
) ){
if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
page_tree();
return;
}
/* No directory found, look for an historic version of the file
** that was subsequently deleted. */
db_prepare(&q,
"SELECT fid, uuid FROM mlink, filename, event, blob"
" WHERE filename.name=%Q"
" AND mlink.fnid=filename.fnid AND mlink.fid>0"
" AND event.objid=mlink.mid"
" AND blob.rid=mlink.mid"
" ORDER BY event.mtime DESC",
zName
|
| ︙ | ︙ | |||
2798 2799 2800 2801 2802 2803 2804 |
}
}
if( strcmp(zModAction,"approve")==0 ){
moderation_approve('t', rid);
}
}
zTktTitle = db_table_has_column("repository", "ticket", "title" )
| | | 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 |
}
}
if( strcmp(zModAction,"approve")==0 ){
moderation_approve('t', rid);
}
}
zTktTitle = db_table_has_column("repository", "ticket", "title" )
? db_text("(No title)",
"SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName)
: 0;
style_set_current_feature("tinfo");
style_header("Ticket Change Details");
style_submenu_element("Raw", "%R/artifact/%s", zUuid);
style_submenu_element("History", "%R/tkthistory/%s#%S", zTktName,zUuid);
style_submenu_element("Page", "%R/tktview/%t", zTktName);
|
| ︙ | ︙ | |||
3830 3831 3832 3833 3834 3835 3836 | ** If no VERSION is provided, describe the currently checked-out version. ** ** If VERSION and the found ancestor refer to the same commit, the last two ** components are omitted, unless --long is provided. When no fitting tagged ** ancestor is found, show only the short hash of VERSION. ** ** Options: | | | 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 |
** If no VERSION is provided, describe the currently checked-out version.
**
** If VERSION and the found ancestor refer to the same commit, the last two
** components are omitted, unless --long is provided. When no fitting tagged
** ancestor is found, show only the short hash of VERSION.
**
** Options:
** --digits Display so many hex digits of the hash
** (default: the larger of 6 and the 'hash-digit' setting)
** -d|--dirty Show whether there are changes to be committed
** --long Always show all three components
** --match GLOB Consider only non-propagating tags matching GLOB
*/
void describe_cmd(void){
const char *zName;
|
| ︙ | ︙ |
Changes to src/interwiki.c.
| ︙ | ︙ | |||
43 44 45 46 47 48 49 |
**
** {
** "base": Base URL for the remote site.
** "hash": Append this to "base" for Hash targets.
** "wiki": Append this to "base" for Wiki targets.
** }
**
| | | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
**
** {
** "base": Base URL for the remote site.
** "hash": Append this to "base" for Hash targets.
** "wiki": Append this to "base" for Wiki targets.
** }
**
** If the remote wiki is Fossil, then the correct value for "hash"
** is "/info/" and the correct value for "wiki" is "/wiki?name=".
** If (for example) Wikipedia is the remote, then "hash" should be
** omitted and the correct value for "wiki" is "/wiki/".
**
** PageName is link name of the target wiki. Several different forms
** of PageName are recognized.
**
** Path If PageName is empty or begins with a "/" character, then
** it is a pathname that is appended to "base".
**
|
| ︙ | ︙ | |||
80 81 82 83 84 85 86 |
static Stmt q;
for(i=0; fossil_isalnum(zTarget[i]); i++){}
if( zTarget[i]!=':' ) return 0;
nCode = i;
if( nCode==4 && strncmp(zTarget,"wiki",4)==0 ) return 0;
zPage = zTarget + nCode + 1;
nPage = (int)strlen(zPage);
| | | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
static Stmt q;
for(i=0; fossil_isalnum(zTarget[i]); i++){}
if( zTarget[i]!=':' ) return 0;
nCode = i;
if( nCode==4 && strncmp(zTarget,"wiki",4)==0 ) return 0;
zPage = zTarget + nCode + 1;
nPage = (int)strlen(zPage);
db_static_prepare(&q,
"SELECT value->>'base', value->>'hash', value->>'wiki'"
" FROM config WHERE name=lower($name) AND json_valid(value)"
);
zName = mprintf("interwiki:%.*s", nCode, zTarget);
db_bind_text(&q, "$name", zName);
while( db_step(&q)==SQLITE_ROW ){
const char *zBase = db_column_text(&q,0);
|
| ︙ | ︙ | |||
220 221 222 223 224 225 226 |
verify_all_options();
if( g.argc<4 ) usage("delete ID ...");
db_begin_write();
db_unprotect(PROTECT_CONFIG);
for(i=3; i<g.argc; i++){
const char *zName = g.argv[i];
db_multi_exec(
| | | 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 |
verify_all_options();
if( g.argc<4 ) usage("delete ID ...");
db_begin_write();
db_unprotect(PROTECT_CONFIG);
for(i=3; i<g.argc; i++){
const char *zName = g.argv[i];
db_multi_exec(
"DELETE FROM config WHERE name='interwiki:%q'",
zName
);
}
setup_incr_cfgcnt();
db_protect_pop();
db_commit_transaction();
}else
|
| ︙ | ︙ |
Changes to src/json.c.
| ︙ | ︙ | |||
21 22 23 24 25 26 27 | ** The JSON API's public interface is documented at: ** ** https://fossil-scm.org/fossil/doc/trunk/www/json-api/index.md ** ** Notes for hackers... ** ** Here's how command/page dispatching works: json_page_top() (in HTTP mode) or | | | > | > | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
** The JSON API's public interface is documented at:
**
** https://fossil-scm.org/fossil/doc/trunk/www/json-api/index.md
**
** Notes for hackers...
**
** Here's how command/page dispatching works: json_page_top() (in HTTP mode) or
** json_cmd_top() (in CLI mode) catch the "json" path/command. Those functions
** then dispatch to a JSON-mode-specific command/page handler with the type
** fossil_json_f().
** See the API docs for that typedef (below) for the semantics of the callbacks.
**
**
*/
#include "VERSION.h"
#include "config.h"
#include "json.h"
#include <assert.h>
#include <time.h>
#if INTERFACE
#include "json_detail.h" /* workaround for apparent enum limitation
in makeheaders */
#endif
const FossilJsonKeys_ FossilJsonKeys = {
"anonymousSeed" /*anonymousSeed*/,
"authToken" /*authToken*/,
"COMMAND_PATH" /*commandPath*/,
"mtime" /*mtime*/,
|
| ︙ | ︙ | |||
174 175 176 177 178 179 180 | return 0; } /* ** Convenience wrapper around cson_output() which appends the output ** to pDest. pOpt may be NULL, in which case g.json.outOpt will be used. */ | | > | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
return 0;
}
/*
** Convenience wrapper around cson_output() which appends the output
** to pDest. pOpt may be NULL, in which case g.json.outOpt will be used.
*/
int cson_output_Blob( cson_value const * pVal, Blob * pDest,
cson_output_opt const * pOpt ){
return cson_output( pVal, cson_data_dest_Blob,
pDest, pOpt ? pOpt : &g.json.outOpt );
}
/*
** Convenience wrapper around cson_parse() which reads its input
** from pSrc. pSrc is rewound before parsing.
|
| ︙ | ︙ | |||
705 706 707 708 709 710 711 |
login_cookie_name(), there is(?) a potential(?) login hijacking
window here. We may need to change the JSON auth token to be in
the form: login_cookie_name()=...
Then again, the hardened cookie value helps ensure that
only a proper key/value match is valid.
*/
| | > | 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 |
login_cookie_name(), there is(?) a potential(?) login hijacking
window here. We may need to change the JSON auth token to be in
the form: login_cookie_name()=...
Then again, the hardened cookie value helps ensure that
only a proper key/value match is valid.
*/
cgi_replace_parameter( login_cookie_name(),
cson_value_get_cstr(g.json.authToken) );
}else if( g.isHTTP ){
/* try fossil's conventional cookie. */
/* Reminder: chicken/egg scenario regarding db access in CLI
mode because login_cookie_name() needs the db. CLI
mode does not use any authentication, so we don't need
to support it here.
*/
|
| ︙ | ︙ | |||
902 903 904 905 906 907 908 |
assert( head != p );
zPart = (char*)fossil_malloc(len+1);
memcpy(zPart, head, len);
zPart[len] = 0;
if(doDeHttp){
dehttpize(zPart);
}
| > | | 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 |
assert( head != p );
zPart = (char*)fossil_malloc(len+1);
memcpy(zPart, head, len);
zPart[len] = 0;
if(doDeHttp){
dehttpize(zPart);
}
if( *zPart ){
/* should only fail if someone manages to url-encoded a NUL byte */
part = cson_value_new_string(zPart, strlen(zPart));
if( 0 != cson_array_append( target, part ) ){
cson_value_free(part);
rc = -rc;
break;
}
}else{
|
| ︙ | ︙ | |||
1084 1085 1086 1087 1088 1089 1090 |
break;
}
/* g.json.reqPayload exists only to simplify some of our access to
the request payload. We currently only use this in the context of
Object payloads, not Arrays, strings, etc.
*/
| | | 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 |
break;
}
/* g.json.reqPayload exists only to simplify some of our access to
the request payload. We currently only use this in the context of
Object payloads, not Arrays, strings, etc.
*/
g.json.reqPayload.v = cson_object_get( g.json.post.o,FossilJsonKeys.payload );
if( g.json.reqPayload.v ){
g.json.reqPayload.o = cson_value_get_object( g.json.reqPayload.v )
/* g.json.reqPayload.o may legally be NULL, which means only that
g.json.reqPayload.v is-not-a Object.
*/;
}
|
| ︙ | ︙ | |||
1113 1114 1115 1116 1117 1118 1119 |
}
if(!g.json.jsonp){
g.json.jsonp = json_find_option_cstr("jsonp",NULL,NULL);
}
if(!g.isHTTP){
| | | 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 |
}
if(!g.json.jsonp){
g.json.jsonp = json_find_option_cstr("jsonp",NULL,NULL);
}
if(!g.isHTTP){
g.json.errorDetailParanoia = 0;/*disable error code dumb-down for CLI mode*/
}
{/* set up JSON output formatting options. */
int indent = -1;
indent = json_find_option_int("indent",NULL,"I",-1);
g.json.outOpt.indentation = (0>indent)
? (g.isHTTP ? 0 : 1)
|
| ︙ | ︙ | |||
1164 1165 1166 1167 1168 1169 1170 |
** Note that CLI options are not included in the command path. Use
** find_option() to get those.
**
*/
char const * json_command_arg(unsigned short ndx){
cson_array * ar = g.json.cmd.a;
assert((NULL!=ar) && "Internal error. Was json_bootstrap_late() called?");
| | | 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 |
** Note that CLI options are not included in the command path. Use
** find_option() to get those.
**
*/
char const * json_command_arg(unsigned short ndx){
cson_array * ar = g.json.cmd.a;
assert((NULL!=ar) && "Internal error. Was json_bootstrap_late() called?");
assert((g.argc>1) &&"Internal error - we never should have gotten this far.");
if( g.json.cmd.offset < 0 ){
/* first-time setup. */
short i = 0;
#define NEXT cson_string_cstr( \
cson_value_get_string( \
cson_array_get(ar,i) \
))
|
| ︙ | ︙ | |||
1190 1191 1192 1193 1194 1195 1196 |
}
}
#undef NEXT
if(g.json.cmd.offset < 0){
return NULL;
}else{
ndx = g.json.cmd.offset + ndx;
| | > | > | 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 |
}
}
#undef NEXT
if(g.json.cmd.offset < 0){
return NULL;
}else{
ndx = g.json.cmd.offset + ndx;
return cson_string_cstr(cson_value_get_string(
cson_array_get( ar, g.json.cmd.offset + ndx )));
}
}
/* Returns the C-string form of json_auth_token(), or NULL
** if json_auth_token() returns NULL.
*/
char const * json_auth_token_cstr(){
return cson_value_get_cstr( json_auth_token() );
}
/*
** Returns the JsonPageDef with the given name, or NULL if no match is
** found.
**
** head must be a pointer to an array of JsonPageDefs in which the
** last entry has a NULL name.
*/
JsonPageDef const * json_handler_for_name( char const * name,
JsonPageDef const * head ){
JsonPageDef const * pageDef = head;
assert( head != NULL );
if(name && *name) for( ; pageDef->name; ++pageDef ){
if( 0 == strcmp(name, pageDef->name) ){
return pageDef;
}
}
|
| ︙ | ︙ | |||
1290 1291 1292 1293 1294 1295 1296 |
*/
static cson_value * json_response_command_path(){
if(!g.json.cmd.a){
return NULL;
}else{
cson_value * rc = NULL;
Blob path = empty_blob;
| | > | > | 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 |
*/
static cson_value * json_response_command_path(){
if(!g.json.cmd.a){
return NULL;
}else{
cson_value * rc = NULL;
Blob path = empty_blob;
unsigned int aLen = g.json.dispatchDepth+1;
/*cson_array_length_get(g.json.cmd.a);*/
unsigned int i = 1;
for( ; i < aLen; ++i ){
char const * part = cson_string_cstr(cson_value_get_string(
cson_array_get(g.json.cmd.a, i)));
if(!part){
#if 1
fossil_warning("Iterating further than expected in %s.",
__FILE__);
#endif
break;
}
|
| ︙ | ︙ | |||
1327 1328 1329 1330 1331 1332 1333 |
*/
cson_value * json_g_to_json(){
cson_object * o = NULL;
cson_object * pay = NULL;
pay = o = cson_new_object();
#define INT(OBJ,K) cson_object_set(o, #K, json_new_int(OBJ.K))
| | > | 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 |
*/
cson_value * json_g_to_json(){
cson_object * o = NULL;
cson_object * pay = NULL;
pay = o = cson_new_object();
#define INT(OBJ,K) cson_object_set(o, #K, json_new_int(OBJ.K))
#define CSTR(OBJ,K) cson_object_set(o, #K, OBJ.K ? json_new_string(OBJ.K) \
: cson_value_null())
#define VAL(K,V) cson_object_set(o, #K, (V) ? (V) : cson_value_null())
VAL(capabilities, json_cap_value());
INT(g, argc);
INT(g, isConst);
CSTR(g, zConfigDbName);
INT(g, repositoryOpen);
INT(g, localOpen);
|
| ︙ | ︙ | |||
1811 1812 1813 1814 1815 1816 1817 |
cson_string * kDesc;
cson_array_reserve( list, 35 );
kRC = cson_new_string("resultCode",10);
kSymbol = cson_new_string("cSymbol",7);
kNumber = cson_new_string("number",6);
kDesc = cson_new_string("description",11);
#define C(K) obj = cson_new_object(); \
| | | | | > | 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 |
cson_string * kDesc;
cson_array_reserve( list, 35 );
kRC = cson_new_string("resultCode",10);
kSymbol = cson_new_string("cSymbol",7);
kNumber = cson_new_string("number",6);
kDesc = cson_new_string("description",11);
#define C(K) obj = cson_new_object(); \
cson_object_set_s(obj, kRC,json_new_string(json_rc_cstr(FSL_JSON_E_##K))); \
cson_object_set_s(obj, kSymbol, json_new_string("FSL_JSON_E_"#K) ); \
cson_object_set_s(obj, kNumber, cson_value_new_integer(FSL_JSON_E_##K) ); \
cson_object_set_s(obj, kDesc, \
json_new_string(json_err_cstr(FSL_JSON_E_##K))); \
cson_array_append( list, cson_object_value(obj) ); obj = NULL;
C(GENERIC);
C(INVALID_REQUEST);
C(UNKNOWN_COMMAND);
C(UNKNOWN);
C(TIMEOUT);
|
| ︙ | ︙ | |||
2004 2005 2006 2007 2008 2009 2010 |
if( !g.perm.Read ){
json_set_err(FSL_JSON_E_DENIED,
"Requires 'o' permissions.");
return NULL;
}
full = json_find_option_bool("full",NULL,"f",
json_find_option_bool("verbose",NULL,"v",0));
| | > | | 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 |
if( !g.perm.Read ){
json_set_err(FSL_JSON_E_DENIED,
"Requires 'o' permissions.");
return NULL;
}
full = json_find_option_bool("full",NULL,"f",
json_find_option_bool("verbose",NULL,"v",0));
#define SETBUF(O,K) cson_object_set(O, K, \
cson_value_new_string(zBuf, strlen(zBuf)));
jv = cson_value_new_object();
jo = cson_value_get_object(jv);
zTmp = db_get("project-name",NULL);
cson_object_set(jo, "projectName", json_new_string(zTmp));
fossil_free(zTmp);
zTmp = db_get("project-description",NULL);
cson_object_set(jo, "projectDescription", json_new_string(zTmp));
fossil_free(zTmp);
zTmp = NULL;
fsize = file_size(g.zRepositoryName, ExtFILE);
cson_object_set(jo, "repositorySize",
cson_value_new_integer((cson_int_t)fsize));
if(full){
n = db_int(0, "SELECT count(*) FROM blob");
m = db_int(0, "SELECT count(*) FROM delta");
cson_object_set(jo, "blobCount", cson_value_new_integer((cson_int_t)n));
cson_object_set(jo, "deltaCount", cson_value_new_integer((cson_int_t)m));
|
| ︙ | ︙ | |||
2066 2067 2068 2069 2070 2071 2072 |
}/*full*/
n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
" + 0.99");
cson_object_set(jo, "ageDays", cson_value_new_integer((cson_int_t)n));
cson_object_set(jo, "ageYears", cson_value_new_double(n/365.2425));
sqlite3_snprintf(BufLen, zBuf, db_get("project-code",""));
SETBUF(jo, "projectCode");
| > | | | | > | > | > | | > | > | 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 |
}/*full*/
n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
" + 0.99");
cson_object_set(jo, "ageDays", cson_value_new_integer((cson_int_t)n));
cson_object_set(jo, "ageYears", cson_value_new_double(n/365.2425));
sqlite3_snprintf(BufLen, zBuf, db_get("project-code",""));
SETBUF(jo, "projectCode");
cson_object_set(jo, "compiler",
cson_value_new_string(COMPILER_NAME, strlen(COMPILER_NAME)));
jv2 = cson_value_new_object();
jo2 = cson_value_get_object(jv2);
cson_object_set(jo, "sqlite", jv2);
sqlite3_snprintf(BufLen, zBuf, "%.19s [%.10s] (%s)", sqlite3_sourceid(),
&sqlite3_sourceid()[20], sqlite3_libversion());
SETBUF(jo2, "version");
cson_object_set(jo2, "pageCount", cson_value_new_integer(
(cson_int_t)db_int(0, "PRAGMA repository.page_count")));
cson_object_set(jo2, "pageSize", cson_value_new_integer(
(cson_int_t)db_int(0, "PRAGMA repository.page_size")));
cson_object_set(jo2, "freeList", cson_value_new_integer(
(cson_int_t)db_int(0, "PRAGMA repository.freelist_count")));
sqlite3_snprintf(BufLen, zBuf, "%s", db_text(0,"PRAGMA repository.encoding"));
SETBUF(jo2, "encoding");
sqlite3_snprintf(BufLen, zBuf, "%s",
db_text(0, "PRAGMA repository.journal_mode"));
cson_object_set(jo2, "journalMode", *zBuf ?
cson_value_new_string(zBuf, strlen(zBuf)) : cson_value_null());
return jv;
#undef SETBUF
}
|
| ︙ | ︙ | |||
2235 2236 2237 2238 2239 2240 2241 |
cson_value * json_page_status(void);
/*
** Mapping of names to JSON pages/commands. Each name is a subpath of
** /json (in CGI mode) or a subcommand of the json command in CLI mode
*/
static const JsonPageDef JsonPageDefs[] = {
| | > | 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 |
cson_value * json_page_status(void);
/*
** Mapping of names to JSON pages/commands. Each name is a subpath of
** /json (in CGI mode) or a subcommand of the json command in CLI mode
*/
static const JsonPageDef JsonPageDefs[] = {
/* please keep alphabetically sorted (case-insensitive)
for maintenance reasons. */
{"anonymousPassword", json_page_anon_password, 0},
{"artifact", json_page_artifact, 0},
{"branch", json_page_branch,0},
{"cap", json_page_cap, 0},
{"config", json_page_config, 0 },
{"diff", json_page_diff, 0},
{"dir", json_page_dir, 0},
|
| ︙ | ︙ |
Changes to src/json_artifact.c.
| ︙ | ︙ | |||
209 210 211 212 213 214 215 |
}
/*
** Sub-impl of /json/artifact for check-ins.
*/
static cson_value * json_artifact_ci( cson_object * zParent, int rid ){
if(!g.perm.Read){
| | > | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
}
/*
** Sub-impl of /json/artifact for check-ins.
*/
static cson_value * json_artifact_ci( cson_object * zParent, int rid ){
if(!g.perm.Read){
json_set_err( FSL_JSON_E_DENIED,
"Viewing check-ins requires 'o' privileges." );
return NULL;
}else{
cson_value * artV = json_artifact_for_ci(rid, 1);
cson_object * art = cson_value_get_object(artV);
if(art){
cson_object_merge( zParent, art, CSON_MERGE_REPLACE );
cson_free_object(art);
|
| ︙ | ︙ | |||
248 249 250 251 252 253 254 |
** if either the includeContent (HTTP) or -content|-c boolean flags
** (CLI) are set.
*/
static int json_artifact_get_content_format_flag(void){
enum { MagicValue = -9 };
int contentFormat = json_wiki_get_content_format_flag(MagicValue);
if(MagicValue == contentFormat){
| | > | | 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
** if either the includeContent (HTTP) or -content|-c boolean flags
** (CLI) are set.
*/
static int json_artifact_get_content_format_flag(void){
enum { MagicValue = -9 };
int contentFormat = json_wiki_get_content_format_flag(MagicValue);
if(MagicValue == contentFormat){
contentFormat = json_find_option_bool("includeContent",
"content","c",0) /* deprecated */ ? -1 : 0;
}
return contentFormat;
}
extern int json_wiki_get_content_format_flag(int defaultValue) /* json_wiki.c*/;
cson_value * json_artifact_wiki(cson_object * zParent, int rid){
if( ! g.perm.RdWiki ){
json_set_err(FSL_JSON_E_DENIED,
"Requires 'j' privileges.");
return NULL;
}else{
|
| ︙ | ︙ | |||
378 379 380 381 382 383 384 |
);
/* TODO: add a "state" flag for the file in each check-in,
e.g. "modified", "new", "deleted".
*/
checkin_arr = cson_new_array();
cson_object_set(pay, "checkins", cson_array_value(checkin_arr));
while( (SQLITE_ROW==db_step(&q) ) ){
| | > | | | 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 |
);
/* TODO: add a "state" flag for the file in each check-in,
e.g. "modified", "new", "deleted".
*/
checkin_arr = cson_new_array();
cson_object_set(pay, "checkins", cson_array_value(checkin_arr));
while( (SQLITE_ROW==db_step(&q) ) ){
cson_object * row = cson_value_get_object(
cson_sqlite3_row_to_object(q.pStmt));
/* FIXME: move this isNew/isDel stuff into an SQL CASE statement. */
char const isNew = cson_value_get_bool(cson_object_get(row,"isNew"));
char const isDel = cson_value_get_bool(cson_object_get(row,"isDel"));
cson_object_set(row, "isNew", NULL);
cson_object_set(row, "isDel", NULL);
cson_object_set(row, "state", json_new_string(
json_artifact_status_to_string(isNew, isDel)));
cson_array_append( checkin_arr, cson_object_value(row) );
}
db_finalize(&q);
return cson_object_value(pay);
}
/*
|
| ︙ | ︙ |
Changes to src/json_branch.c.
| ︙ | ︙ | |||
200 201 202 203 204 205 206 |
Manifest *pParent; /* Parsed parent manifest */
Blob mcksum; /* Self-checksum on the manifest */
int bAutoColor = 0; /* Value of "--bgcolor" is "auto" */
if( fossil_strncmp(zColor, "auto", 4)==0 ) {
bAutoColor = 1;
zColor = 0;
| | | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
Manifest *pParent; /* Parsed parent manifest */
Blob mcksum; /* Self-checksum on the manifest */
int bAutoColor = 0; /* Value of "--bgcolor" is "auto" */
if( fossil_strncmp(zColor, "auto", 4)==0 ) {
bAutoColor = 1;
zColor = 0;
}
/* fossil branch new name */
if( zBranch==0 || zBranch[0]==0 ){
zOpt->rcErrMsg = "Branch name may not be null/empty.";
return FSL_JSON_E_INVALID_ARGS;
}
if( db_exists(
"SELECT 1 FROM tagxref"
|
| ︙ | ︙ | |||
333 334 335 336 337 338 339 |
}
if(!opt.zName){
opt.zName = json_command_arg(g.json.dispatchDepth+1);
}
if(!opt.zName){
| | > | 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
}
if(!opt.zName){
opt.zName = json_command_arg(g.json.dispatchDepth+1);
}
if(!opt.zName){
json_set_err(FSL_JSON_E_MISSING_ARGS,
"'name' parameter was not specified." );
return NULL;
}
opt.zColor = json_find_option_cstr("bgColor","bgcolor",NULL);
opt.zBasis = json_find_option_cstr("basis",NULL,NULL);
if(!opt.zBasis && !g.isHTTP){
opt.zBasis = json_command_arg(g.json.dispatchDepth+2);
|
| ︙ | ︙ |
Changes to src/json_config.c.
| ︙ | ︙ | |||
255 256 257 258 259 260 261 |
}
for(i=0; i<nSetting; ++i){
const Setting *pSet = &aSetting[i];
cson_object * jSet;
cson_value * pVal = 0, * pSrc = 0;
jSet = cson_new_object();
cson_object_set(pay, pSet->name, cson_object_value(jSet));
| | | 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
}
for(i=0; i<nSetting; ++i){
const Setting *pSet = &aSetting[i];
cson_object * jSet;
cson_value * pVal = 0, * pSrc = 0;
jSet = cson_new_object();
cson_object_set(pay, pSet->name, cson_object_value(jSet));
cson_object_set(jSet, "versionable",cson_value_new_bool(pSet->versionable));
cson_object_set(jSet, "sensitive", cson_value_new_bool(pSet->sensitive));
cson_object_set(jSet, "defaultValue", (pSet->def && pSet->def[0])
? json_new_string(pSet->def)
: cson_value_null());
if( 0==pSet->sensitive || 0!=g.perm.Setup ){
if( pSet->versionable ){
/* Check to see if this is overridden by a versionable
|
| ︙ | ︙ | |||
290 291 292 293 294 295 296 |
Blob versionedPathname;
blob_zero(&versionedPathname);
blob_appendf(&versionedPathname, "%s.fossil-settings/%s",
g.zLocalRoot, pSet->name);
if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
Blob content;
blob_zero(&content);
| | | 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 |
Blob versionedPathname;
blob_zero(&versionedPathname);
blob_appendf(&versionedPathname, "%s.fossil-settings/%s",
g.zLocalRoot, pSet->name);
if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){
Blob content;
blob_zero(&content);
blob_read_from_file(&content, blob_str(&versionedPathname),ExtFILE);
pSrc = json_new_string("versioned");
pVal = json_new_string(blob_str(&content));
blob_reset(&content);
}
blob_reset(&versionedPathname);
}
}
|
| ︙ | ︙ |
Changes to src/json_finfo.c.
| ︙ | ︙ | |||
39 40 41 42 43 44 45 |
int currentRow = 0;
char const * zCheckin = NULL;
signed char sort = -1;
if(!g.perm.Read){
json_set_err(FSL_JSON_E_DENIED,"Requires 'o' privileges.");
return NULL;
}
| > | | | | | 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 67 68 69 70 71 72 73 74 75 76 77 78 |
int currentRow = 0;
char const * zCheckin = NULL;
signed char sort = -1;
if(!g.perm.Read){
json_set_err(FSL_JSON_E_DENIED,"Requires 'o' privileges.");
return NULL;
}
json_warn( FSL_JSON_W_UNKNOWN,
"Achtung: the output of the finfo command is up for change.");
/* For the "name" argument we have to jump through some hoops to make sure
that we don't get the fossil-internally-assigned "name" option.
*/
zFilename = json_find_option_cstr2("name",NULL,NULL, g.json.dispatchDepth+1);
if(!zFilename || !*zFilename){
json_set_err(FSL_JSON_E_MISSING_ARGS, "Missing 'name' parameter.");
return NULL;
}
if(0==db_int(0,"SELECT 1 FROM filename WHERE name=%Q",zFilename)){
json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND, "File entry not found.");
return NULL;
}
zBefore = json_find_option_cstr("before",NULL,"b");
zAfter = json_find_option_cstr("after",NULL,"a");
limit = json_find_option_int("limit",NULL,"n", -1);
zCheckin = json_find_option_cstr("checkin",NULL,"ci");
blob_append_sql(&sql,
/*0*/ "SELECT b.uuid,"
/*1*/ " ci.uuid,"
/*2*/ " (SELECT uuid FROM blob WHERE rid=mlink.fid),"/* Current file uuid */
/*3*/ " cast(strftime('%%s',event.mtime) AS INTEGER),"
/*4*/ " coalesce(event.euser, event.user),"
/*5*/ " coalesce(event.ecomment, event.comment),"
/*6*/ " (SELECT uuid FROM blob WHERE rid=mlink.pid)," /* Parent file uuid */
/*7*/ " event.bgcolor,"
/*8*/ " b.size,"
/*9*/ " (mlink.pid==0) AS isNew,"
|
| ︙ | ︙ | |||
86 87 88 89 90 91 92 |
);
if( zCheckin && *zCheckin ){
char * zU = NULL;
int rc = name_to_uuid2( zCheckin, "ci", &zU );
/*printf("zCheckin=[%s], zU=[%s]", zCheckin, zU);*/
if(rc<=0){
| | > | > | > | > | | | 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 114 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 |
);
if( zCheckin && *zCheckin ){
char * zU = NULL;
int rc = name_to_uuid2( zCheckin, "ci", &zU );
/*printf("zCheckin=[%s], zU=[%s]", zCheckin, zU);*/
if(rc<=0){
json_set_err((rc<0) ? FSL_JSON_E_AMBIGUOUS_UUID :
FSL_JSON_E_RESOURCE_NOT_FOUND,
"Check-in hash %s.", (rc<0) ? "is ambiguous" : "not found");
blob_reset(&sql);
return NULL;
}
blob_append_sql(&sql, " AND ci.uuid='%q'", zU);
free(zU);
}else{
if( zAfter && *zAfter ){
blob_append_sql(&sql, " AND event.mtime>=julianday('%q')", zAfter);
sort = 1;
}else if( zBefore && *zBefore ){
blob_append_sql(&sql, " AND event.mtime<=julianday('%q')", zBefore);
}
}
blob_append_sql(&sql," ORDER BY event.mtime %s /*sort*/",
(sort>0 ? "ASC" : "DESC"));
/*printf("SQL=\n%s\n",blob_str(&sql));*/
db_prepare(&q, "%s", blob_sql_text(&sql));
blob_reset(&sql);
pay = cson_new_object();
cson_object_set(pay, "name", json_new_string(zFilename));
if( limit > 0 ){
cson_object_set(pay, "limit", json_new_int(limit));
}
checkins = cson_new_array();
cson_object_set(pay, "checkins", cson_array_value(checkins));
while( db_step(&q)==SQLITE_ROW ){
cson_object * row = cson_new_object();
int const isNew = db_column_int(&q,9);
int const isDel = db_column_int(&q,10);
cson_array_append( checkins, cson_object_value(row) );
cson_object_set(row, "checkin", json_new_string( db_column_text(&q,1) ));
cson_object_set(row, "uuid", json_new_string( db_column_text(&q,2) ));
/*cson_object_set(row, "parentArtifact",
json_new_string( db_column_text(&q,6) ));*/
cson_object_set(row, "timestamp", json_new_int( db_column_int64(&q,3) ));
cson_object_set(row, "user", json_new_string( db_column_text(&q,4) ));
cson_object_set(row, "comment", json_new_string( db_column_text(&q,5) ));
/*cson_object_set(row, "bgColor",
json_new_string( db_column_text(&q,7) ));*/
cson_object_set(row, "size", json_new_int( db_column_int64(&q,8) ));
cson_object_set(row, "state", json_new_string(
json_artifact_status_to_string(isNew, isDel)));
if( (0 < limit) && (++currentRow >= limit) ){
break;
}
}
db_finalize(&q);
return pay ? cson_object_value(pay) : NULL;
}
#endif /* FOSSIL_ENABLE_JSON */
|
Changes to src/json_login.c.
| ︙ | ︙ | |||
153 154 155 156 157 158 159 |
}
payload = cson_value_new_object();
po = cson_value_get_object(payload);
cson_object_set(po, "authToken", json_new_string(cookie));
free(cookie);
cson_object_set(po, "name", json_new_string(name));
cap = db_text(NULL, "SELECT cap FROM user WHERE login=%Q", name);
| | > | > | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
}
payload = cson_value_new_object();
po = cson_value_get_object(payload);
cson_object_set(po, "authToken", json_new_string(cookie));
free(cookie);
cson_object_set(po, "name", json_new_string(name));
cap = db_text(NULL, "SELECT cap FROM user WHERE login=%Q", name);
cson_object_set(po, "capabilities",
cap ? json_new_string(cap) : cson_value_null() );
free(cap);
cson_object_set(po, "loginCookieName",
json_new_string( login_cookie_name() ) );
/* TODO: add loginExpiryTime to the payload. To do this properly
we "should" add an ([unsigned] int *) to
login_set_user_cookie() and login_set_anon_cookie(), to which
the expiry time is assigned. (Remember that JSON doesn't do
unsigned int.)
For non-anonymous users we could also simply query the
|
| ︙ | ︙ |
Changes to src/json_tag.c.
| ︙ | ︙ | |||
115 116 117 118 119 120 121 |
cson_object_set(pay, "raw", cson_value_new_bool(fRaw));
{
Blob uu = empty_blob;
int rc;
blob_append(&uu, zName, -1);
rc = name_to_uuid(&uu, 9, "*");
if(0!=rc){
| | > | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
cson_object_set(pay, "raw", cson_value_new_bool(fRaw));
{
Blob uu = empty_blob;
int rc;
blob_append(&uu, zName, -1);
rc = name_to_uuid(&uu, 9, "*");
if(0!=rc){
json_set_err(FSL_JSON_E_UNKNOWN,
"Could not convert name back to artifact hash!");
blob_reset(&uu);
goto error;
}
cson_object_set(pay, "appliedTo", json_new_string(blob_buffer(&uu)));
blob_reset(&uu);
}
|
| ︙ | ︙ |
Changes to src/json_timeline.c.
| ︙ | ︙ | |||
167 168 169 170 171 172 173 |
zUnhide = json_find_option_cstr("unhide",NULL,NULL);
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",
zTag);
if(tagid<=0){
return -1;
}
if(pPayload){
| | > | > | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
zUnhide = json_find_option_cstr("unhide",NULL,NULL);
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'",
zTag);
if(tagid<=0){
return -1;
}
if(pPayload){
cson_object_set( pPayload, zBranch ? "branch" : "tag",
json_new_string(zTag) );
}
blob_appendf(pSql,
" AND ("
" EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)",
tagid);
if(!zUnhide){
blob_appendf(pSql,
" AND NOT EXISTS(SELECT 1 FROM plink "
" JOIN tagxref ON rid=blob.rid"
" WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)",
TAG_HIDDEN);
}
if(zBranch){
/* from "r" flag code in page_timeline().*/
blob_appendf(pSql,
" OR EXISTS(SELECT 1 FROM plink JOIN tagxref ON rid=cid"
|
| ︙ | ︙ | |||
350 351 352 353 354 355 356 |
cson_object_set(row, "uuid", json_new_string(db_column_text(&q,3)));
if(!isNew && (flags & json_get_changed_files_ELIDE_PARENT)){
cson_object_set(row, "parent", json_new_string(db_column_text(&q,4)));
}
cson_object_set(row, "size", json_new_int(db_column_int(&q,5)));
cson_object_set(row, "state",
| | | > | 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
cson_object_set(row, "uuid", json_new_string(db_column_text(&q,3)));
if(!isNew && (flags & json_get_changed_files_ELIDE_PARENT)){
cson_object_set(row, "parent", json_new_string(db_column_text(&q,4)));
}
cson_object_set(row, "size", json_new_int(db_column_int(&q,5)));
cson_object_set(row, "state",
json_new_string(json_artifact_status_to_string(isNew,isDel)));
zDownload = mprintf("/raw/%s?name=%s",
/* reminder: g.zBaseURL is of course not set
for CLI mode. */
db_column_text(&q,2),
db_column_text(&q,3));
cson_object_set(row, "downloadPath", json_new_string(zDownload));
free(zDownload);
}
db_finalize(&q);
return rowsV;
|
| ︙ | ︙ | |||
503 504 505 506 507 508 509 |
int const rid = db_column_int(&q,0);
cson_value * rowV = json_artifact_for_ci(rid, verboseFlag);
cson_object * row = cson_value_get_object(rowV);
if(!row){
if( !warnRowToJsonFailed ){
warnRowToJsonFailed = 1;
json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED,
| | | 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 |
int const rid = db_column_int(&q,0);
cson_value * rowV = json_artifact_for_ci(rid, verboseFlag);
cson_object * row = cson_value_get_object(rowV);
if(!row){
if( !warnRowToJsonFailed ){
warnRowToJsonFailed = 1;
json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED,
"Could not convert at least one timeline result row to JSON." );
}
continue;
}
cson_array_append(list, rowV);
}
#undef SET
goto ok;
|
| ︙ | ︙ | |||
546 547 548 549 550 551 552 |
if(check){
json_set_err(check, "Query initialization failed.");
goto error;
}
#if 0
/* only for testing! */
| | > | > > | 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 |
if(check){
json_set_err(check, "Query initialization failed.");
goto error;
}
#if 0
/* only for testing! */
cson_object_set(pay, "timelineSql", cson_value_new_string(blob_buffer(&sql),
strlen(blob_buffer(&sql))));
#endif
db_multi_exec("%s", blob_buffer(&sql) /*safe-for-%s*/);
blob_reset(&sql);
db_prepare(&q, "SELECT"
/* For events, the name is generally more useful than
the uuid, but the uuid is unambiguous and can be used
with commands like 'artifact'. */
" substr((SELECT tagname FROM tag AS tn "
" WHERE tn.tagid=json_timeline.tagId "
" AND tagname LIKE 'event-%%'),7) AS name,"
" uuid as uuid,"
" mtime AS timestamp,"
" comment AS comment, "
" user AS user,"
" eventType AS eventType"
" FROM json_timeline"
" ORDER BY rowid");
|
| ︙ | ︙ | |||
589 590 591 592 593 594 595 |
cson_value * payV = NULL;
cson_object * pay = NULL;
cson_array * list = NULL;
int check = 0;
Stmt q = empty_Stmt;
Blob sql = empty_blob;
if( !g.perm.RdWiki && !g.perm.Read ){
| | > | > | 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 |
cson_value * payV = NULL;
cson_object * pay = NULL;
cson_array * list = NULL;
int check = 0;
Stmt q = empty_Stmt;
Blob sql = empty_blob;
if( !g.perm.RdWiki && !g.perm.Read ){
json_set_err( FSL_JSON_E_DENIED,
"Wiki timeline requires 'o' or 'j' access.");
return NULL;
}
payV = cson_value_new_object();
pay = cson_value_get_object(payV);
check = json_timeline_setup_sql( "w", &sql, pay );
if(check){
json_set_err(check, "Query initialization failed.");
goto error;
}
#if 0
/* only for testing! */
cson_object_set(pay, "timelineSql", cson_value_new_string(blob_buffer(&sql),
strlen(blob_buffer(&sql))));
#endif
db_multi_exec("%s", blob_buffer(&sql) /*safe-for-%s*/);
blob_reset(&sql);
db_prepare(&q, "SELECT"
" uuid AS uuid,"
" mtime AS timestamp,"
#if 0
|
| ︙ | ︙ | |||
652 653 654 655 656 657 658 |
cson_value * tmp = NULL;
cson_value * listV = NULL;
cson_array * list = NULL;
int check = 0;
Stmt q = empty_Stmt;
Blob sql = empty_blob;
if( !g.perm.RdTkt && !g.perm.Read ){
| | > | 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 |
cson_value * tmp = NULL;
cson_value * listV = NULL;
cson_array * list = NULL;
int check = 0;
Stmt q = empty_Stmt;
Blob sql = empty_blob;
if( !g.perm.RdTkt && !g.perm.Read ){
json_set_err(FSL_JSON_E_DENIED,
"Ticket timeline requires 'o' or 'r' access.");
return NULL;
}
payV = cson_value_new_object();
pay = cson_value_get_object(payV);
check = json_timeline_setup_sql( "t", &sql, pay );
if(check){
json_set_err(check, "Query initialization failed.");
|
| ︙ | ︙ | |||
724 725 726 727 728 729 730 |
}
rowV = cson_sqlite3_row_to_object(q.pStmt);
row = cson_value_get_object(rowV);
if(!row){
manifest_destroy(pMan);
json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED,
| | | 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 |
}
rowV = cson_sqlite3_row_to_object(q.pStmt);
row = cson_value_get_object(rowV);
if(!row){
manifest_destroy(pMan);
json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED,
"Could not convert at least one timeline result row to JSON." );
continue;
}
/* FIXME: certainly there's a more efficient way for use to get
the ticket UUIDs?
*/
cson_object_set(row,"ticketUuid",json_new_string(pMan->zTicketUuid));
manifest_destroy(pMan);
|
| ︙ | ︙ |
Changes to src/json_user.c.
| ︙ | ︙ | |||
168 169 170 171 172 173 174 |
** Requires either Admin, Setup, or Password access. Non-admin/setup
** users can only change their own information. Non-setup users may
** not modify the 's' permission. Admin users without setup
** permissions may not edit any other user who has the 's' permission.
**
*/
int json_user_update_from_json( cson_object * pUser ){
| | > | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
** Requires either Admin, Setup, or Password access. Non-admin/setup
** users can only change their own information. Non-setup users may
** not modify the 's' permission. Admin users without setup
** permissions may not edit any other user who has the 's' permission.
**
*/
int json_user_update_from_json( cson_object * pUser ){
#define CSTR(X) cson_string_cstr(cson_value_get_string( cson_object_get(pUser, \
X ) ))
char const * zName = CSTR("name");
char const * zNameNew = zName;
char * zNameFree = NULL;
char const * zInfo = CSTR("info");
char const * zCap = CSTR("capabilities");
char const * zPW = CSTR("password");
cson_value const * forceLogout = cson_object_get(pUser, "forceLogout");
|
| ︙ | ︙ |
Changes to src/json_wiki.c.
| ︙ | ︙ | |||
161 162 163 164 165 166 167 | } /* ** Searches for the latest version of a wiki page with the given ** name. If found it behaves like json_get_wiki_page_by_rid(theRid, ** contentFormat), else it returns NULL. */ | | > | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
}
/*
** Searches for the latest version of a wiki page with the given
** name. If found it behaves like json_get_wiki_page_by_rid(theRid,
** contentFormat), else it returns NULL.
*/
cson_value * json_get_wiki_page_by_name(char const * zPageName,
int contentFormat){
int rid;
rid = db_int(0,
"SELECT x.rid FROM tag t, tagxref x, blob b"
" WHERE x.tagid=t.tagid AND t.tagname='wiki-%q' "
" AND b.rid=x.rid"
" ORDER BY x.mtime DESC LIMIT 1",
zPageName
|
| ︙ | ︙ | |||
257 258 259 260 261 262 263 |
}
zPageName = json_find_option_cstr2("name",NULL,"n",g.json.dispatchDepth+1);
zSymName = json_find_option_cstr("uuid",NULL,"u");
if((!zPageName||!*zPageName) && (!zSymName || !*zSymName)){
json_set_err(FSL_JSON_E_MISSING_ARGS,
| | | 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
}
zPageName = json_find_option_cstr2("name",NULL,"n",g.json.dispatchDepth+1);
zSymName = json_find_option_cstr("uuid",NULL,"u");
if((!zPageName||!*zPageName) && (!zSymName || !*zSymName)){
json_set_err(FSL_JSON_E_MISSING_ARGS,
"At least one of the 'name' or 'uuid' arguments must be provided.");
return NULL;
}
/* TODO: see if we have a page named zPageName. If not, try to resolve
zPageName as a UUID.
*/
|
| ︙ | ︙ | |||
295 296 297 298 299 300 301 |
zMime = cson_value_get_cstr(cson_object_get(g.json.reqPayload.o,
"mimetype"));
}else{
sContent = cson_value_get_string(g.json.reqPayload.v);
}
if(!sContent) {
json_set_err(FSL_JSON_E_MISSING_ARGS,
| | | | | | > | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 |
zMime = cson_value_get_cstr(cson_object_get(g.json.reqPayload.o,
"mimetype"));
}else{
sContent = cson_value_get_string(g.json.reqPayload.v);
}
if(!sContent) {
json_set_err(FSL_JSON_E_MISSING_ARGS,
"The 'payload' property must be either a string containing the "
"Fossil wiki code to preview or an object with body + mimetype "
"properties.");
return NULL;
}
zContent = cson_string_cstr(sContent);
blob_append( &contentOrig, zContent, (int)cson_string_length_bytes(sContent));
zMime = wiki_filter_mimetypes(zMime);
if( 0==fossil_strcmp(zMime, "text/x-markdown") ){
markdown_to_html(&contentOrig, 0, &contentHtml);
}else if( 0==fossil_strcmp(zMime, "text/plain") ){
blob_append(&contentHtml, "<pre class='textPlain'>", -1);
blob_append(&contentHtml, blob_str(&contentOrig), blob_size(&contentOrig));
blob_append(&contentHtml, "</pre>", -1);
}else{
wiki_convert( &contentOrig, &contentHtml, 0 );
}
blob_reset( &contentOrig );
pay = cson_value_new_string( blob_str(&contentHtml),
(unsigned int)blob_size(&contentHtml));
blob_reset( &contentHtml );
return pay;
}
/*
** Internal impl of /wiki/save and /wiki/create. If createMode is 0
|
| ︙ | ︙ | |||
344 345 346 347 348 349 350 |
char allowCreateIfNotExists){
Blob content = empty_blob; /* wiki page content */
cson_value * nameV; /* wiki page name */
char const * zPageName; /* cstr form of page name */
cson_value * contentV; /* passed-in content */
cson_value * emptyContent = NULL; /* placeholder for empty content. */
cson_value * payV = NULL; /* payload/return value */
| | > | 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
char allowCreateIfNotExists){
Blob content = empty_blob; /* wiki page content */
cson_value * nameV; /* wiki page name */
char const * zPageName; /* cstr form of page name */
cson_value * contentV; /* passed-in content */
cson_value * emptyContent = NULL; /* placeholder for empty content. */
cson_value * payV = NULL; /* payload/return value */
cson_string const * jstr = NULL; /* temp for cson_value-to-cson_string
conversions. */
char const * zMimeType = 0;
unsigned int contentLen = 0;
int rid;
if( (createMode && !g.perm.NewWiki)
|| (!createMode && !g.perm.WrWiki)){
json_set_err(FSL_JSON_E_DENIED,
"Requires '%c' permissions.",
|
| ︙ | ︙ |
Changes to src/login.c.
| ︙ | ︙ | |||
252 253 254 255 256 257 258 |
const char *zLogin = db_column_text(&q,0);
if( (uid = login_search_uid(&zLogin, zPasswd) ) != 0 ){
*pzUsername = fossil_strdup(zLogin);
break;
}
}
db_finalize(&q);
| | | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
const char *zLogin = db_column_text(&q,0);
if( (uid = login_search_uid(&zLogin, zPasswd) ) != 0 ){
*pzUsername = fossil_strdup(zLogin);
break;
}
}
db_finalize(&q);
}
free(zSha1Pw);
return uid;
}
/*
** Generates a login cookie value for a non-anonymous user.
**
|
| ︙ | ︙ | |||
773 774 775 776 777 778 779 |
}else{
zAnonPw = 0;
}
@ <table class="login_out">
if( P("HTTPS")==0 ){
@ <tr><td class="form_label">Warning:</td>
@ <td><span class='securityWarning'>
| | | 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 |
}else{
zAnonPw = 0;
}
@ <table class="login_out">
if( P("HTTPS")==0 ){
@ <tr><td class="form_label">Warning:</td>
@ <td><span class='securityWarning'>
@ Login information, including the password,
@ will be sent in the clear over an unencrypted connection.
if( !g.sslNotAvailable ){
@ Consider logging in at
@ <a href='%s(g.zHttpsURL)'>%h(g.zHttpsURL)</a> instead.
}
@ </span></td></tr>
}
|
| ︙ | ︙ | |||
822 823 824 825 826 827 828 |
@ </tr>
}
@ </table>
if( zAnonPw && !noAnon ){
const char *zDecoded = captcha_decode(uSeed);
int bAutoCaptcha = db_get_boolean("auto-captcha", 0);
char *zCaptcha = captcha_render(zDecoded);
| | | 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 |
@ </tr>
}
@ </table>
if( zAnonPw && !noAnon ){
const char *zDecoded = captcha_decode(uSeed);
int bAutoCaptcha = db_get_boolean("auto-captcha", 0);
char *zCaptcha = captcha_render(zDecoded);
@ <p><input type="hidden" name="cs" value="%u(uSeed)">
@ Visitors may enter <b>anonymous</b> as the user-ID with
@ the 8-character hexadecimal password shown below:</p>
@ <div class="captcha"><table class="captcha"><tr><td>\
@ <pre class="captcha">
@ %h(zCaptcha)
@ </pre></td></tr></table>
|
| ︙ | ︙ | |||
1027 1028 1029 1030 1031 1032 1033 |
uid = login_resetpw_suffix_is_valid(zName);
if( uid==0 ){
@ <p><span class="loginError">
@ This password-reset URL is invalid, probably because it has expired.
@ Password-reset URLs have a short lifespan.
@ </span></p>
style_finish_page();
| | | 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 |
uid = login_resetpw_suffix_is_valid(zName);
if( uid==0 ){
@ <p><span class="loginError">
@ This password-reset URL is invalid, probably because it has expired.
@ Password-reset URLs have a short lifespan.
@ </span></p>
style_finish_page();
sleep(1); /* Introduce a small delay on an invalid suffix as an
** extra defense against search attacks */
return;
}
fossil_redirect_to_https_if_needed(1);
login_set_uid(uid, 0);
if( g.perm.Setup || g.perm.Admin || !g.perm.Password || g.zLogin==0 ){
@ <p><span class="loginError">
|
| ︙ | ︙ | |||
1161 1162 1163 1164 1165 1166 1167 |
pStmt = 0;
rc = sqlite3_prepare_v2(pOther, zSQL, -1, &pStmt, 0);
if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
db_unprotect(PROTECT_USER);
db_multi_exec(
"UPDATE user SET cookie=%Q, cexpire=%.17g"
" WHERE login=%Q",
| | | 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 |
pStmt = 0;
rc = sqlite3_prepare_v2(pOther, zSQL, -1, &pStmt, 0);
if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
db_unprotect(PROTECT_USER);
db_multi_exec(
"UPDATE user SET cookie=%Q, cexpire=%.17g"
" WHERE login=%Q",
zHash,
sqlite3_column_double(pStmt, 0), zLogin
);
db_protect_pop();
nXfer++;
}
sqlite3_finalize(pStmt);
}
|
| ︙ | ︙ | |||
1578 1579 1580 1581 1582 1583 1584 |
case 'a': p->Admin = p->RdTkt = p->WrTkt = p->Zip =
p->RdWiki = p->WrWiki = p->NewWiki =
p->ApndWiki = p->Hyperlink = p->Clone =
p->NewTkt = p->Password = p->RdAddr =
p->TktFmt = p->Attach = p->ApndTkt =
p->ModWiki = p->ModTkt =
p->RdForum = p->WrForum = p->ModForum =
| | | 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 |
case 'a': p->Admin = p->RdTkt = p->WrTkt = p->Zip =
p->RdWiki = p->WrWiki = p->NewWiki =
p->ApndWiki = p->Hyperlink = p->Clone =
p->NewTkt = p->Password = p->RdAddr =
p->TktFmt = p->Attach = p->ApndTkt =
p->ModWiki = p->ModTkt =
p->RdForum = p->WrForum = p->ModForum =
p->WrTForum = p->AdminForum = p->Chat =
p->EmailAlert = p->Announce = p->Debug = 1;
/* Fall thru into Read/Write */
case 'i': p->Read = p->Write = 1; break;
case 'o': p->Read = 1; break;
case 'z': p->Zip = 1; break;
case 'h': p->Hyperlink = 1; break;
|
| ︙ | ︙ | |||
1825 1826 1827 1828 1829 1830 1831 |
*/
void login_insert_csrf_secret(void){
@ <input type="hidden" name="csrf" value="%s(g.zCsrfToken)">
}
/*
** Check to see if the candidate username zUserID is already used.
| | | 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 |
*/
void login_insert_csrf_secret(void){
@ <input type="hidden" name="csrf" value="%s(g.zCsrfToken)">
}
/*
** Check to see if the candidate username zUserID is already used.
** Return 1 if it is already in use. Return 0 if the name is
** available for a self-registeration.
*/
static int login_self_choosen_userid_already_exists(const char *zUserID){
int rc = db_exists(
"SELECT 1 FROM user WHERE login=%Q "
"UNION ALL "
"SELECT 1 FROM event WHERE user=%Q OR euser=%Q",
|
| ︙ | ︙ | |||
1847 1848 1849 1850 1851 1852 1853 |
** searches for a user or subscriber that has that email address. If the
** email address is used no-where in the system, return 0. If the email
** address is assigned to a particular user return the UID for that user.
** If the email address is used, but not by a particular user, return -1.
*/
static int email_address_in_use(const char *zEMail){
int uid;
| | | 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 |
** searches for a user or subscriber that has that email address. If the
** email address is used no-where in the system, return 0. If the email
** address is assigned to a particular user return the UID for that user.
** If the email address is used, but not by a particular user, return -1.
*/
static int email_address_in_use(const char *zEMail){
int uid;
uid = db_int(0,
"SELECT uid FROM user"
" WHERE info LIKE '%%<%q>%%'", zEMail);
if( uid>0 ){
if( db_exists("SELECT 1 FROM user WHERE uid=%d AND ("
" cap GLOB '*[as]*' OR"
" find_emailaddr(info)<>%Q COLLATE nocase)",
uid, zEMail) ){
|
| ︙ | ︙ | |||
1876 1877 1878 1879 1880 1881 1882 | } return uid; } /* ** COMMAND: test-email-used ** Usage: fossil test-email-used EMAIL ... | | | 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 |
}
return uid;
}
/*
** COMMAND: test-email-used
** Usage: fossil test-email-used EMAIL ...
**
** Given a list of email addresses, show the UID and LOGIN associated
** with each one.
*/
void test_email_used(void){
int i;
db_find_and_open_repository(0, 0);
verify_all_options();
|
| ︙ | ︙ | |||
1901 1902 1903 1904 1905 1906 1907 |
}else{
char *zLogin = db_text(0, "SELECT login FROM user WHERE uid=%d", uid);
fossil_print("%s: UID %d (%s)\n", zEMail, uid, zLogin);
fossil_free(zLogin);
}
}
}
| | | 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 |
}else{
char *zLogin = db_text(0, "SELECT login FROM user WHERE uid=%d", uid);
fossil_print("%s: UID %d (%s)\n", zEMail, uid, zLogin);
fossil_free(zLogin);
}
}
}
/*
** Check an email address and confirm that it is valid for self-registration.
** The email address is known already to be well-formed. Return true
** if the email address is on the allowed list.
**
** The default behavior is that any valid email address is accepted.
|
| ︙ | ︙ | |||
1993 1994 1995 1996 1997 1998 1999 |
zErr = "Incorrect CAPTCHA";
}else if( strlen(zUserID)<6 ){
iErrLine = 1;
zErr = "User ID too short. Must be at least 6 characters.";
}else if( sqlite3_strglob("*[^-a-zA-Z0-9_.]*",zUserID)==0 ){
iErrLine = 1;
zErr = "User ID may not contain spaces or special characters.";
| | | 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 |
zErr = "Incorrect CAPTCHA";
}else if( strlen(zUserID)<6 ){
iErrLine = 1;
zErr = "User ID too short. Must be at least 6 characters.";
}else if( sqlite3_strglob("*[^-a-zA-Z0-9_.]*",zUserID)==0 ){
iErrLine = 1;
zErr = "User ID may not contain spaces or special characters.";
}else if( sqlite3_strlike("anonymous%", zUserID, 0)==0
|| sqlite3_strlike("nobody%", zUserID, 0)==0
|| sqlite3_strlike("reader%", zUserID, 0)==0
|| sqlite3_strlike("developer%", zUserID, 0)==0
){
iErrLine = 1;
zErr = "This User ID is reserved. Choose something different.";
}else if( zDName[0]==0 ){
|
| ︙ | ︙ |
Changes to src/lookslike.c.
| ︙ | ︙ | |||
268 269 270 271 272 273 274 |
const WCHAR_T *z = (WCHAR_T *)blob_buffer(pContent);
unsigned int n = blob_size(pContent);
int j, c, flags = LOOK_NONE; /* Assume UTF-16 text, prove otherwise */
if( n%sizeof(WCHAR_T) ){
flags |= LOOK_ODD; /* Odd number of bytes -> binary (UTF-8?) */
}
| | | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
const WCHAR_T *z = (WCHAR_T *)blob_buffer(pContent);
unsigned int n = blob_size(pContent);
int j, c, flags = LOOK_NONE; /* Assume UTF-16 text, prove otherwise */
if( n%sizeof(WCHAR_T) ){
flags |= LOOK_ODD; /* Odd number of bytes -> binary (UTF-8?) */
}
if( n<sizeof(WCHAR_T) ) return flags;/* Zero or One byte -> binary (UTF-8?) */
c = *z;
if( bReverse ){
c = UTF16_SWAP(c);
}
if( c==0 ){
flags |= LOOK_NUL; /* NUL character in a file -> binary */
}else if( c=='\r' ){
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
850 851 852 853 854 855 856 |
zNewArgv[0] = g.argv[0];
zNewArgv[1] = "ui";
zNewArgv[2] = g.argv[1];
zNewArgv[3] = 0;
g.argc = 3;
g.argv = zNewArgv;
#endif
| | | 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 |
zNewArgv[0] = g.argv[0];
zNewArgv[1] = "ui";
zNewArgv[2] = g.argv[1];
zNewArgv[3] = 0;
g.argc = 3;
g.argv = zNewArgv;
#endif
}
zCmdName = g.argv[1];
}
#ifndef _WIN32
/* There is a bug in stunnel4 in which it sometimes starts up client
** processes without first opening file descriptor 2 (standard error).
** If this happens, and a subsequent open() of a database returns file
** descriptor 2, and then an assert() fires and writes on fd 2, that
|
| ︙ | ︙ | |||
1412 1413 1414 1415 1416 1417 1418 |
/* Remove trailing ":443" from the HOST, if any */
if( i>4 && z[i-1]=='3' && z[i-2]=='4' && z[i-3]=='4' && z[i-4]==':' ){
i -= 4;
}
}else{
/* Remove trailing ":80" from the HOST */
if( i>3 && z[i-1]=='0' && z[i-2]=='8' && z[i-3]==':' ) i -= 3;
| | | 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 |
/* Remove trailing ":443" from the HOST, if any */
if( i>4 && z[i-1]=='3' && z[i-2]=='4' && z[i-3]=='4' && z[i-4]==':' ){
i -= 4;
}
}else{
/* Remove trailing ":80" from the HOST */
if( i>3 && z[i-1]=='0' && z[i-2]=='8' && z[i-3]==':' ) i -= 3;
}
if( i && z[i-1]=='.' ) i--;
z[i] = 0;
zCur = PD("SCRIPT_NAME","/");
i = strlen(zCur);
while( i>0 && zCur[i-1]=='/' ) i--;
if( fossil_stricmp(zMode,"on")==0 ){
g.zBaseURL = mprintf("https://%s%.*s", z, i, zCur);
|
| ︙ | ︙ | |||
1612 1613 1614 1615 1616 1617 1618 |
if( db_get_int("redirect-to-https",0)<iLevel ) return 0;
if( P("HTTPS")!=0 ) return 0;
return 1;
}
/*
** Redirect to the equivalent HTTPS request if the current connection is
| | | 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 |
if( db_get_int("redirect-to-https",0)<iLevel ) return 0;
if( P("HTTPS")!=0 ) return 0;
return 1;
}
/*
** Redirect to the equivalent HTTPS request if the current connection is
** insecure and if the redirect-to-https flag greater than or equal to
** iLevel. iLevel is 1 for /login pages and 2 for every other page.
*/
int fossil_redirect_to_https_if_needed(int iLevel){
if( fossil_wants_https(iLevel) ){
const char *zQS = P("QUERY_STRING");
char *zURL;
if( zQS==0 || zQS[0]==0 ){
|
| ︙ | ︙ | |||
1967 1968 1969 1970 1971 1972 1973 |
zPathInfo += 7;
g.nExtraURL += 7;
cgi_replace_parameter("PATH_INFO", zPathInfo);
cgi_replace_parameter("SCRIPT_NAME", zNewScript);
etag_cancel();
}
| | | 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 |
zPathInfo += 7;
g.nExtraURL += 7;
cgi_replace_parameter("PATH_INFO", zPathInfo);
cgi_replace_parameter("SCRIPT_NAME", zNewScript);
etag_cancel();
}
/* If the content type is application/x-fossil or
** application/x-fossil-debug, then a sync/push/pull/clone is
** desired, so default the PATH_INFO to /xfer
*/
if( g.zContentType &&
strncmp(g.zContentType, "application/x-fossil", 20)==0 ){
/* Special case: If the content mimetype shows that it is "fossil sync"
** payload, then pretend that the PATH_INFO is /xfer so that we always
|
| ︙ | ︙ | |||
2783 2784 2785 2786 2787 2788 2789 | ** --nocompress Do not compress HTTP replies ** --nodelay Omit backoffice processing if it would delay ** process exit ** --nojail Drop root privilege but do not enter the chroot jail ** --nossl Do not do http: to https: redirects, regardless of ** the redirect-to-https setting. ** --notfound URL Use URL as the "HTTP 404, object not found" page | | | 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 |
** --nocompress Do not compress HTTP replies
** --nodelay Omit backoffice processing if it would delay
** process exit
** --nojail Drop root privilege but do not enter the chroot jail
** --nossl Do not do http: to https: redirects, regardless of
** the redirect-to-https setting.
** --notfound URL Use URL as the "HTTP 404, object not found" page
** --out FILE Write the HTTP reply to FILE instead of to
** standard output
** --pkey FILE Read the private key used for TLS from FILE
** --repolist If REPOSITORY is directory, URL "/" lists all repos
** --scgi Interpret input as SCGI rather than HTTP
** --skin LABEL Use override skin LABEL. Use an empty string ("")
** to force use of the current local skin config.
** --th-trace Trace TH1 execution (for debugging purposes)
|
| ︙ | ︙ | |||
3173 3174 3175 3176 3177 3178 3179 | int fCreate = 0; /* The --create flag */ int fNoBrowser = 0; /* Do not auto-launch web-browser */ const char *zInitPage = 0; /* Start on this page. --page option */ int findServerArg = 2; /* argv index for find_server_repository() */ char *zRemote = 0; /* Remote host on which to run "fossil ui" */ const char *zJsMode; /* The --jsmode parameter */ const char *zFossilCmd =0; /* Name of "fossil" binary on remote system */ | | | 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 | int fCreate = 0; /* The --create flag */ int fNoBrowser = 0; /* Do not auto-launch web-browser */ const char *zInitPage = 0; /* Start on this page. --page option */ int findServerArg = 2; /* argv index for find_server_repository() */ char *zRemote = 0; /* Remote host on which to run "fossil ui" */ const char *zJsMode; /* The --jsmode parameter */ const char *zFossilCmd =0; /* Name of "fossil" binary on remote system */ #if USE_SEE db_setup_for_saved_encryption_key(); #endif #if defined(_WIN32) const char *zStopperFile; /* Name of file used to terminate server */ |
| ︙ | ︙ | |||
3345 3346 3347 3348 3349 3350 3351 |
** tunnel from the local machine to the remote. */
FILE *sshIn;
Blob ssh;
char zLine[1000];
blob_init(&ssh, 0, 0);
transport_ssh_command(&ssh);
db_close_config();
| | | 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 |
** tunnel from the local machine to the remote. */
FILE *sshIn;
Blob ssh;
char zLine[1000];
blob_init(&ssh, 0, 0);
transport_ssh_command(&ssh);
db_close_config();
blob_appendf(&ssh,
" -t -L 127.0.0.1:%d:127.0.0.1:%d %!$",
iPort, iPort, zRemote
);
if( zFossilCmd==0 ){
blob_appendf(&ssh, " %$ fossil", "PATH=$HOME/bin:$PATH");
}else{
blob_appendf(&ssh, " %$", zFossilCmd);
|
| ︙ | ︙ |
Changes to src/manifest.c.
| ︙ | ︙ | |||
1224 1225 1226 1227 1228 1229 1230 | ** control artifact. Make a copy, and run it through the official ** artifact parser. This is the slow path, but it is rarely taken. */ blob_init(©, 0, 0); blob_init(&errmsg, 0, 0); blob_append(©, zIn, nIn); pManifest = manifest_parse(©, 0, &errmsg); | | | 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 | ** control artifact. Make a copy, and run it through the official ** artifact parser. This is the slow path, but it is rarely taken. */ blob_init(©, 0, 0); blob_init(&errmsg, 0, 0); blob_append(©, zIn, nIn); pManifest = manifest_parse(©, 0, &errmsg); iRes = pManifest!=0; manifest_destroy(pManifest); blob_reset(&errmsg); return iRes; } /* ** COMMAND: test-parse-manifest |
| ︙ | ︙ | |||
1336 1337 1338 1339 1340 1341 1342 |
id, blob_str(&err));
nErr++;
}else if( !isWF && p!=0 ){
fossil_print("%d ERROR: manifest_is_well_formed() reported false "
"but manifest_parse() found nothing wrong.\n", id);
nErr++;
}
| | | 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 |
id, blob_str(&err));
nErr++;
}else if( !isWF && p!=0 ){
fossil_print("%d ERROR: manifest_is_well_formed() reported false "
"but manifest_parse() found nothing wrong.\n", id);
nErr++;
}
}else{
p = manifest_get(id, CFTYPE_ANY, &err);
if( p==0 ){
fossil_print("%d ERROR: %s\n", id, blob_str(&err));
nErr++;
}
}
blob_reset(&err);
|
| ︙ | ︙ | |||
2111 2112 2113 2114 2115 2116 2117 |
** Activate EVENT triggers if they do not already exist.
*/
void manifest_create_event_triggers(void){
if( manifest_event_triggers_are_enabled ){
return; /* Triggers already exists. No-op. */
}
alert_create_trigger();
| | | 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 |
** Activate EVENT triggers if they do not already exist.
*/
void manifest_create_event_triggers(void){
if( manifest_event_triggers_are_enabled ){
return; /* Triggers already exists. No-op. */
}
alert_create_trigger();
manifest_event_triggers_are_enabled = 1;
}
/*
** Disable manifest event triggers. Drop them if they exist, but mark
** them has having been created so that they won't be recreated. This
** is used during "rebuild" to prevent triggers from firing then.
*/
|
| ︙ | ︙ |
Changes to src/markdown.c.
| ︙ | ︙ | |||
62 63 64 65 66 67 68 |
void (*paragraph)(struct Blob *ob, struct Blob *text, void *opaque);
void (*table)(struct Blob *ob, struct Blob *head_row, struct Blob *rows,
void *opaque);
void (*table_cell)(struct Blob *ob, struct Blob *text, int flags,
void *opaque);
void (*table_row)(struct Blob *ob, struct Blob *cells, int flags,
void *opaque);
| | | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
void (*paragraph)(struct Blob *ob, struct Blob *text, void *opaque);
void (*table)(struct Blob *ob, struct Blob *head_row, struct Blob *rows,
void *opaque);
void (*table_cell)(struct Blob *ob, struct Blob *text, int flags,
void *opaque);
void (*table_row)(struct Blob *ob, struct Blob *cells, int flags,
void *opaque);
void (*footnote_item)(struct Blob *ob, const struct Blob *text,
int index, int nUsed, void *opaque);
/* span level callbacks - NULL or return 0 prints the span verbatim */
int (*autolink)(struct Blob *ob, struct Blob *link,
enum mkd_autolink type, void *opaque);
int (*codespan)(struct Blob *ob, struct Blob *text, int nSep, void *opaque);
int (*double_emphasis)(struct Blob *ob, struct Blob *text,
|
| ︙ | ︙ | |||
380 381 382 383 384 385 386 |
/* release the given working buffer back to the cache */
static void release_work_buffer(struct render *rndr, struct Blob *buf){
if( !buf ) return;
rndr->iDepth--;
blob_reset(buf);
| > | | 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 |
/* release the given working buffer back to the cache */
static void release_work_buffer(struct render *rndr, struct Blob *buf){
if( !buf ) return;
rndr->iDepth--;
blob_reset(buf);
if( rndr->nBlobCache <
(int)(sizeof(rndr->aBlobCache)/sizeof(rndr->aBlobCache[0])) ){
rndr->aBlobCache[rndr->nBlobCache++] = buf;
}else{
fossil_free(buf);
}
}
|
| ︙ | ︙ | |||
2368 2369 2370 2371 2372 2373 2374 |
beg += parse_blockcode(ob, rndr, txt_data, end);
}else if( prefix_uli(txt_data, end) ){
beg += parse_list(ob, rndr, txt_data, end, 0);
}else if( prefix_oli(txt_data, end) ){
beg += parse_list(ob, rndr, txt_data, end, MKD_LIST_ORDERED);
}else if( has_table && is_tableline(txt_data, end) ){
beg += parse_table(ob, rndr, txt_data, end);
| | | 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 |
beg += parse_blockcode(ob, rndr, txt_data, end);
}else if( prefix_uli(txt_data, end) ){
beg += parse_list(ob, rndr, txt_data, end, 0);
}else if( prefix_oli(txt_data, end) ){
beg += parse_list(ob, rndr, txt_data, end, MKD_LIST_ORDERED);
}else if( has_table && is_tableline(txt_data, end) ){
beg += parse_table(ob, rndr, txt_data, end);
}else if( prefix_fencedcode(txt_data, end)
&& (i = char_codespan(ob, rndr, txt_data, 0, end))!=0
){
beg += i;
}else{
beg += parse_paragraph(ob, rndr, txt_data, end);
}
}
|
| ︙ | ︙ |
Changes to src/markdown_html.c.
| ︙ | ︙ | |||
778 779 780 781 782 783 784 |
){
char *zLink = blob_buffer(link);
char *zTitle = title!=0 && blob_size(title)>0 ? blob_str(title) : 0;
char zClose[20];
if( zLink==0 || zLink[0]==0 ){
zClose[0] = 0;
| | | | 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 |
){
char *zLink = blob_buffer(link);
char *zTitle = title!=0 && blob_size(title)>0 ? blob_str(title) : 0;
char zClose[20];
if( zLink==0 || zLink[0]==0 ){
zClose[0] = 0;
}else{
static const int flags =
WIKI_NOBADLINKS |
WIKI_MARKDOWNLINKS
;
wiki_resolve_hyperlink(ob, flags, zLink, zClose, sizeof(zClose), 0, zTitle);
}
if( blob_size(content)==0 ){
if( link ) blob_appendb(ob, link);
|
| ︙ | ︙ |
Changes to src/merge.c.
| ︙ | ︙ | |||
266 267 268 269 270 271 272 |
*/
void test_show_vfile_cmd(void){
if( g.argc!=2 ){
fossil_fatal("unknown arguments to the %s command\n", g.argv[1]);
}
verify_all_options();
db_must_be_within_tree();
| | | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
*/
void test_show_vfile_cmd(void){
if( g.argc!=2 ){
fossil_fatal("unknown arguments to the %s command\n", g.argv[1]);
}
verify_all_options();
db_must_be_within_tree();
debug_show_vfile();
}
/*
** COMMAND: merge
** COMMAND: cherry-pick
**
|
| ︙ | ︙ | |||
373 374 375 376 377 378 379 | /* Undocumented --debug and --show-vfile options: ** ** When included on the command-line, --debug causes lots of state ** information to be displayed. This option is undocumented as it ** might change or be eliminated in future releases. ** | | | 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 |
/* Undocumented --debug and --show-vfile options:
**
** When included on the command-line, --debug causes lots of state
** information to be displayed. This option is undocumented as it
** might change or be eliminated in future releases.
**
** The --show-vfile flag does a dump of the VFILE table for reference.
**
** Hints:
** * Combine --debug and --verbose for still more output.
** * The --dry-run option is also useful in combination with --debug.
*/
debugFlag = find_option("debug",0,0)!=0;
if( debugFlag && verboseFlag ) debugFlag = 2;
|
| ︙ | ︙ |
Changes to src/merge3.c.
| ︙ | ︙ | |||
209 210 211 212 213 214 215 | int limit1, limit2; /* Sizes of aC1[] and aC2[] */ int nConflict = 0; /* Number of merge conflicts seen so far */ int useCrLf = 0; int ln1, ln2, lnPivot; /* Line numbers for all files */ DiffConfig DCfg; blob_zero(pOut); /* Merge results stored in pOut */ | | | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
int limit1, limit2; /* Sizes of aC1[] and aC2[] */
int nConflict = 0; /* Number of merge conflicts seen so far */
int useCrLf = 0;
int ln1, ln2, lnPivot; /* Line numbers for all files */
DiffConfig DCfg;
blob_zero(pOut); /* Merge results stored in pOut */
/* If both pV1 and pV2 start with a UTF-8 byte-order-mark (BOM),
** keep it in the output. This should be secure enough not to cause
** unintended changes to the merged file and consistent with what
** users are using in their source files.
*/
if( starts_with_utf8_bom(pV1, 0) && starts_with_utf8_bom(pV2, 0) ){
blob_append(pOut, (char*)get_utf8_bom(0), -1);
|
| ︙ | ︙ |
Changes to src/name.c.
| ︙ | ︙ | |||
511 512 513 514 515 516 517 |
return start_of_branch(rid, 0);
}
/* start:BR -> The first check-in on branch named BR */
if( strncmp(zTag, "start:", 6)==0 ){
rid = symbolic_name_to_rid(zTag+6, zType);
return start_of_branch(rid, 1);
| | | | | 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 |
return start_of_branch(rid, 0);
}
/* start:BR -> The first check-in on branch named BR */
if( strncmp(zTag, "start:", 6)==0 ){
rid = symbolic_name_to_rid(zTag+6, zType);
return start_of_branch(rid, 1);
}
/* merge-in:BR -> Most recent merge-in for the branch named BR */
if( strncmp(zTag, "merge-in:", 9)==0 ){
rid = symbolic_name_to_rid(zTag+9, zType);
return start_of_branch(rid, 2);
}
/* symbolic-name ":" date-time */
nTag = strlen(zTag);
for(i=0; i<nTag-8 && zTag[i]!=':'; i++){}
if( zTag[i]==':'
&& (fossil_isdate(&zTag[i+1]) || fossil_expand_datetime(&zTag[i+1],0)!=0)
){
char *zDate = mprintf("%s", &zTag[i+1]);
char *zTagBase = mprintf("%.*s", i, zTag);
char *zXDate;
int nDate = strlen(zDate);
if( sqlite3_strnicmp(&zDate[nDate-3],"utc",3)==0 ){
|
| ︙ | ︙ | |||
1085 1086 1087 1088 1089 1090 1091 |
" coalesce(euser,user), coalesce(ecomment,comment)"
" FROM mlink, filename, blob, event"
" WHERE mlink.fid=%d"
" AND filename.fnid=mlink.fnid"
" AND event.objid=mlink.mid"
" AND blob.rid=mlink.mid"
" ORDER BY event.mtime %s /*sort*/",
| | | 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 |
" coalesce(euser,user), coalesce(ecomment,comment)"
" FROM mlink, filename, blob, event"
" WHERE mlink.fid=%d"
" AND filename.fnid=mlink.fnid"
" AND event.objid=mlink.mid"
" AND blob.rid=mlink.mid"
" ORDER BY event.mtime %s /*sort*/",
rid,
(flags & WHATIS_BRIEF) ? "LIMIT 1" : "DESC");
while( db_step(&q)==SQLITE_ROW ){
if( flags & WHATIS_BRIEF ){
fossil_print("mtime: %s\n", db_column_text(&q,2));
}
fossil_print("file: %s\n", db_column_text(&q,0));
fossil_print(" part of [%S] by %s on %s\n",
|
| ︙ | ︙ |
Changes to src/patch.c.
| ︙ | ︙ | |||
69 70 71 72 73 74 75 | } /* ** mkdelta(X,Y) ** ** X is an numeric artifact id. Y is a filename. ** | | | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
}
/*
** mkdelta(X,Y)
**
** X is an numeric artifact id. Y is a filename.
**
** Compute a compressed delta that carries X into Y. Or return
** and zero-length blob if X is equal to Y.
*/
static void mkdeltaFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
|
| ︙ | ︙ | |||
160 161 162 163 164 165 166 |
"PRAGMA patch.page_size=512;\n"
"CREATE TABLE patch.chng(\n"
" pathname TEXT,\n" /* Filename */
" origname TEXT,\n" /* Name before rename. NULL if not renamed */
" hash TEXT,\n" /* Baseline hash. NULL for new files. */
" isexe BOOL,\n" /* True if executable */
" islink BOOL,\n" /* True if is a symbolic link */
| | | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
"PRAGMA patch.page_size=512;\n"
"CREATE TABLE patch.chng(\n"
" pathname TEXT,\n" /* Filename */
" origname TEXT,\n" /* Name before rename. NULL if not renamed */
" hash TEXT,\n" /* Baseline hash. NULL for new files. */
" isexe BOOL,\n" /* True if executable */
" islink BOOL,\n" /* True if is a symbolic link */
" delta BLOB\n" /* compressed delta. NULL if deleted.
** length 0 if unchanged */
");"
"CREATE TABLE patch.cfg(\n"
" key TEXT,\n"
" value ANY\n"
");"
);
|
| ︙ | ︙ | |||
194 195 196 197 198 199 200 |
";", vid, g.zLocalRoot, g.zRepositoryName, g.zLogin);
z = fossil_hostname();
if( z ){
db_multi_exec(
"INSERT INTO patch.cfg(key,value)VALUES('hostname',%Q)", z);
fossil_free(z);
}
| | | 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
";", vid, g.zLocalRoot, g.zRepositoryName, g.zLogin);
z = fossil_hostname();
if( z ){
db_multi_exec(
"INSERT INTO patch.cfg(key,value)VALUES('hostname',%Q)", z);
fossil_free(z);
}
/* New files */
db_multi_exec(
"INSERT INTO patch.chng(pathname,hash,isexe,islink,delta)"
" SELECT pathname, NULL, isexe, islink,"
" compress(read_co_file(%Q||pathname))"
" FROM vfile WHERE rid==0;",
g.zLocalRoot
|
| ︙ | ︙ | |||
247 248 249 250 251 252 253 |
fossil_fatal("out of memory");
}
#ifdef _WIN32
fflush(out);
_setmode(_fileno(out), _O_BINARY);
#endif
fwrite(pData, sz, 1, out);
| | | 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
fossil_fatal("out of memory");
}
#ifdef _WIN32
fflush(out);
_setmode(_fileno(out), _O_BINARY);
#endif
fwrite(pData, sz, 1, out);
sqlite3_free(pData);
fflush(out);
}
}
/*
** Attempt to load and validate a patchfile identified by the first
** argument.
|
| ︙ | ︙ | |||
299 300 301 302 303 304 305 |
}
/*
** Show a summary of the content of a patch on standard output
*/
void patch_view(unsigned mFlags){
Stmt q;
| | | | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
}
/*
** Show a summary of the content of a patch on standard output
*/
void patch_view(unsigned mFlags){
Stmt q;
db_prepare(&q,
"WITH nmap(nkey,nm) AS (VALUES"
"('baseline','BASELINE'),"
"('project-name','PROJECT-NAME'))"
"SELECT nm, value FROM nmap, patch.cfg WHERE nkey=key;"
);
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%-12s %s\n", db_column_text(&q,0), db_column_text(&q,1));
}
db_finalize(&q);
if( mFlags & PATCH_VERBOSE ){
db_prepare(&q,
"WITH nmap(nkey,nm,isDate) AS (VALUES"
"('project-code','PROJECT-CODE',0),"
"('date','TIMESTAMP',1),"
"('user','USER',0),"
"('hostname','HOSTNAME',0),"
"('ckout','CHECKOUT',0),"
"('repo','REPOSITORY',0))"
|
| ︙ | ︙ | |||
431 432 433 434 435 436 437 |
blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
if( strcmp(zType,"merge")==0 ){
blob_appendf(&cmd, " merge %s\n", db_column_text(&q,1));
}else{
blob_appendf(&cmd, " merge --%s %s\n", zType, db_column_text(&q,1));
}
if( mFlags & PATCH_VERBOSE ){
| | | 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
if( strcmp(zType,"merge")==0 ){
blob_appendf(&cmd, " merge %s\n", db_column_text(&q,1));
}else{
blob_appendf(&cmd, " merge --%s %s\n", zType, db_column_text(&q,1));
}
if( mFlags & PATCH_VERBOSE ){
fossil_print("%-10s %s\n", db_column_text(&q,2),
db_column_text(&q,0));
}
}
db_finalize(&q);
if( mFlags & PATCH_DRYRUN ){
fossil_print("%s", blob_str(&cmd));
}else{
|
| ︙ | ︙ | |||
559 560 561 562 563 564 565 |
}else{
blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
blob_appendf(&cmd, " add %$\n", zPathname);
if( mFlags & PATCH_VERBOSE ){
fossil_print("%-10s %s\n", "NEW", zPathname);
}
}
| | | 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 |
}else{
blob_append_escaped_arg(&cmd, g.nameOfExe, 1);
blob_appendf(&cmd, " add %$\n", zPathname);
if( mFlags & PATCH_VERBOSE ){
fossil_print("%-10s %s\n", "NEW", zPathname);
}
}
if( (mFlags & PATCH_DRYRUN)==0 ){
if( isLink ){
symlink_create(blob_str(&data), zPathname);
}else{
blob_write_to_file(&data, zPathname);
}
file_setexe(zPathname, isExe);
blob_reset(&data);
|
| ︙ | ︙ | |||
695 696 697 698 699 700 701 |
blob_appendf(&cmd, " -T");
blob_append_escaped_arg(&cmd, zRemote, 0);
blob_init(&remote, 0, 0);
if( zFossilCmd==0 ){
blob_append_escaped_arg(&cmd, "PATH=$HOME/bin:$PATH", 0);
zFossilCmd = "fossil";
}
| | | 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 |
blob_appendf(&cmd, " -T");
blob_append_escaped_arg(&cmd, zRemote, 0);
blob_init(&remote, 0, 0);
if( zFossilCmd==0 ){
blob_append_escaped_arg(&cmd, "PATH=$HOME/bin:$PATH", 0);
zFossilCmd = "fossil";
}
blob_appendf(&remote, "%$ patch %s%s --dir64 %z -",
zFossilCmd, zRemoteCmd, zForce, encode64(zDir, -1));
blob_append_escaped_arg(&cmd, blob_str(&remote), 0);
blob_reset(&remote);
}
fossil_print("%s\n", blob_str(&cmd));
fflush(stdout);
f = popen(blob_str(&cmd), zRW);
|
| ︙ | ︙ | |||
775 776 777 778 779 780 781 |
" FROM patch.chng"
" ORDER BY pathname"
);
while( db_step(&q)==SQLITE_ROW ){
int rid;
const char *zName;
Blob a, b;
| | | 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 |
" FROM patch.chng"
" ORDER BY pathname"
);
while( db_step(&q)==SQLITE_ROW ){
int rid;
const char *zName;
Blob a, b;
if( db_column_type(&q,0)!=SQLITE_INTEGER
&& db_column_type(&q,4)==SQLITE_TEXT
){
char *zUuid = fossil_strdup(db_column_text(&q,4));
char *zName = fossil_strdup(db_column_text(&q,1));
if( mFlags & PATCH_FORCE ){
fossil_print("ERROR cannot find base artifact %S for file \"%s\"\n",
|
| ︙ | ︙ | |||
897 898 899 900 901 902 903 | ** ** Command-line options: ** ** -f|--force Apply the patch even though there are unsaved ** changes in the current check-out. Unsaved ** changes will be reverted and then the patch is ** applied. | | | 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 | ** ** Command-line options: ** ** -f|--force Apply the patch even though there are unsaved ** changes in the current check-out. Unsaved ** changes will be reverted and then the patch is ** applied. ** --fossilcmd EXE Name of the "fossil" executable on the remote ** -n|--dry-run Do nothing, but print what would have happened ** -v|--verbose Extra output explaining what happens ** ** ** > fossil patch pull REMOTE-CHECKOUT ** ** Like "fossil patch push" except that the transfer is from remote |
| ︙ | ︙ | |||
974 975 976 977 978 979 980 |
unsigned flags = 0;
const char *zFossilCmd = find_option("fossilcmd",0,1);
if( find_option("dry-run","n",0) ) flags |= PATCH_DRYRUN;
if( find_option("verbose","v",0) ) flags |= PATCH_VERBOSE;
if( find_option("force","f",0) ) flags |= PATCH_FORCE;
db_must_be_within_tree();
verify_all_options();
| | | 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 |
unsigned flags = 0;
const char *zFossilCmd = find_option("fossilcmd",0,1);
if( find_option("dry-run","n",0) ) flags |= PATCH_DRYRUN;
if( find_option("verbose","v",0) ) flags |= PATCH_VERBOSE;
if( find_option("force","f",0) ) flags |= PATCH_FORCE;
db_must_be_within_tree();
verify_all_options();
pIn = patch_remote_command(flags & (~PATCH_FORCE),
"pull", "create", zFossilCmd, "r");
if( pIn ){
patch_attach(0, pIn);
pclose(pIn);
patch_apply(flags);
}
}else
|
| ︙ | ︙ | |||
1012 1013 1014 1015 1016 1017 1018 |
zIn = g.argv[3];
if( fossil_strcmp(zIn, "-")==0 ) zIn = 0;
patch_attach(zIn, stdin);
patch_view(flags);
}else
{
goto patch_usage;
| | | 1012 1013 1014 1015 1016 1017 1018 1019 1020 |
zIn = g.argv[3];
if( fossil_strcmp(zIn, "-")==0 ) zIn = 0;
patch_attach(zIn, stdin);
patch_view(flags);
}else
{
goto patch_usage;
}
}
|
Changes to src/pikchrshow.c.
| ︙ | ︙ | |||
133 134 135 136 137 138 139 |
) & pikFlags){
pikFlags |= PIKCHR_PROCESS_DIV;
}
if(!(PIKCHR_PROCESS_TH1 & pikFlags)
/* If any TH1_xxx flags are set, set TH1 */
&& (PIKCHR_PROCESS_TH1_NOSVG & pikFlags || thFlags!=0)){
pikFlags |= PIKCHR_PROCESS_TH1;
| | | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
) & pikFlags){
pikFlags |= PIKCHR_PROCESS_DIV;
}
if(!(PIKCHR_PROCESS_TH1 & pikFlags)
/* If any TH1_xxx flags are set, set TH1 */
&& (PIKCHR_PROCESS_TH1_NOSVG & pikFlags || thFlags!=0)){
pikFlags |= PIKCHR_PROCESS_TH1;
}
if(zNonce){
blob_appendf(pOut, "%s\n", zNonce);
}
if(PIKCHR_PROCESS_TH1 & pikFlags){
Blob out = empty_blob;
isErr = Th_RenderToBlob(zIn, &out, thFlags)
? 1 : 0;
|
| ︙ | ︙ | |||
544 545 546 547 548 549 550 | ** ** -div-source Set the 'source' CSS class on the div, which tells ** CSS to hide the SVG and reveal the source by default. ** ** -src Store the input pikchr's source code in the output as ** a separate element adjacent to the SVG one. Implied ** by -div-source. | | | 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 | ** ** -div-source Set the 'source' CSS class on the div, which tells ** CSS to hide the SVG and reveal the source by default. ** ** -src Store the input pikchr's source code in the output as ** a separate element adjacent to the SVG one. Implied ** by -div-source. ** ** ** -th Process the input using TH1 before passing it to pikchr ** ** -th-novar Disable $var and $<var> TH1 processing. Use this if the ** pikchr script uses '$' for its own purposes and that ** causes issues. This only affects parsing of '$' outside ** of TH1 script blocks. Code in such blocks is unaffected. |
| ︙ | ︙ |
Changes to src/rebuild.c.
| ︙ | ︙ | |||
659 660 661 662 663 664 665 | ** --compress Strive to make the database as small as possible ** --compress-only Skip the rebuilding step. Do --compress only ** --force Force the rebuild to complete even if errors are seen ** --ifneeded Only do the rebuild if it would change the schema version ** --index Always add in the full-text search index ** --noverify Skip the verification of changes to the BLOB table ** --noindex Always omit the full-text search index | | | 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 |
** --compress Strive to make the database as small as possible
** --compress-only Skip the rebuilding step. Do --compress only
** --force Force the rebuild to complete even if errors are seen
** --ifneeded Only do the rebuild if it would change the schema version
** --index Always add in the full-text search index
** --noverify Skip the verification of changes to the BLOB table
** --noindex Always omit the full-text search index
** --pagesize N Set the database pagesize to N (512..65536, power of 2)
** --quiet Only show output if there are errors
** --stats Show artifact statistics after rebuilding
** --vacuum Run VACUUM on the database after rebuilding
** --wal Set Write-Ahead-Log journalling mode on the database
*/
void rebuild_database(void){
int forceFlag;
|
| ︙ | ︙ | |||
1393 1394 1395 1396 1397 1398 1399 |
*/
verify_cancel();
db_end_transaction(0);
fossil_print("project-id: %s\n", db_get("project-code", 0));
fossil_print("server-id: %s\n", db_get("server-code", 0));
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
| | > | 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 |
*/
verify_cancel();
db_end_transaction(0);
fossil_print("project-id: %s\n", db_get("project-code", 0));
fossil_print("server-id: %s\n", db_get("server-code", 0));
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
fossil_print("admin-user: %s (initial password is \"%s\")\n", g.zLogin,
zPassword);
hash_user_password(g.zLogin);
}
/*
** COMMAND: deconstruct*
**
** Usage %fossil deconstruct ?OPTIONS? DESTINATION
|
| ︙ | ︙ |
Changes to src/report.c.
| ︙ | ︙ | |||
1124 1125 1126 1127 1128 1129 1130 | char *zClrKey; char *zDesc; char *zMimetype; int tabs; Stmt q; char *zErr1 = 0; char *zErr2 = 0; | | | 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 |
char *zClrKey;
char *zDesc;
char *zMimetype;
int tabs;
Stmt q;
char *zErr1 = 0;
char *zErr2 = 0;
login_check_credentials();
if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
report_update_reportfmt_table();
rn = report_number();
tabs = P("tablist")!=0;
db_prepare(&q,
"SELECT title, sqlcode, owner, cols, rn, jx->>'desc', jx->>'descmt'"
|
| ︙ | ︙ | |||
1366 1367 1368 1369 1370 1371 1372 | Stmt q; char *zSql; char *zErr1 = 0; char *zErr2 = 0; int count = 0; int rn; | | > | 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 |
Stmt q;
char *zSql;
char *zErr1 = 0;
char *zErr2 = 0;
int count = 0;
int rn;
if( !zRep || !strcmp(zRep,zFullTicketRptRn)
|| !strcmp(zRep,zFullTicketRptTitle) ){
zSql = "SELECT * FROM ticket";
}else{
rn = atoi(zRep);
if( rn ){
db_prepare(&q,
"SELECT sqlcode FROM reportfmt WHERE rn=%d", rn);
}else{
|
| ︙ | ︙ |
Changes to src/rss.c.
| ︙ | ︙ | |||
141 142 143 144 145 146 147 |
blob_append_sql( &bSQL, " ORDER BY event.mtime DESC" );
cgi_set_content_type("application/rss+xml");
zProjectName = db_get("project-name", 0);
if( zProjectName==0 ){
| | | | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
blob_append_sql( &bSQL, " ORDER BY event.mtime DESC" );
cgi_set_content_type("application/rss+xml");
zProjectName = db_get("project-name", 0);
if( zProjectName==0 ){
zFreeProjectName = zProjectName =
mprintf("Fossil source repository for: %s", g.zBaseURL);
}
zProjectDescr = db_get("project-description", 0);
if( zProjectDescr==0 ){
zProjectDescr = zProjectName;
}
zPubDate = cgi_rfc822_datestamp(time(NULL));
|
| ︙ | ︙ | |||
256 257 258 259 260 261 262 |
** The default is "URL-PLACEHOLDER" (without quotes).
*/
void cmd_timeline_rss(void){
Stmt q;
int nLine=0;
char *zPubDate, *zProjectName, *zProjectDescr, *zFreeProjectName=0;
Blob bSQL;
| | | 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
** The default is "URL-PLACEHOLDER" (without quotes).
*/
void cmd_timeline_rss(void){
Stmt q;
int nLine=0;
char *zPubDate, *zProjectName, *zProjectDescr, *zFreeProjectName=0;
Blob bSQL;
const char *zType = find_option("type","y",1); /* Type of events;All if NULL*/
const char *zTicketUuid = find_option("tkt",NULL,1);
const char *zTag = find_option("tag",NULL,1);
const char *zFilename = find_option("name",NULL,1);
const char *zWiki = find_option("wiki",NULL,1);
const char *zLimit = find_option("limit", "n",1);
const char *zBaseURL = find_option("url", NULL, 1);
int nLimit = atoi( (zLimit && *zLimit) ? zLimit : "20" );
|
| ︙ | ︙ | |||
330 331 332 333 334 335 336 |
}else if( nTagId!=0 ){
blob_append_sql(&bSQL, " AND (EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=%d AND tagtype>0 AND rid=blob.rid))", nTagId);
}
if( zFilename ){
blob_append_sql(&bSQL,
| | > | | | > | 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 |
}else if( nTagId!=0 ){
blob_append_sql(&bSQL, " AND (EXISTS(SELECT 1 FROM tagxref"
" WHERE tagid=%d AND tagtype>0 AND rid=blob.rid))", nTagId);
}
if( zFilename ){
blob_append_sql(&bSQL,
" AND (SELECT mlink.fnid FROM mlink WHERE event.objid=mlink.mid) "
" IN (SELECT fnid FROM filename WHERE name=%Q %s)",
zFilename, filename_collation()
);
}
blob_append( &bSQL, " ORDER BY event.mtime DESC", -1 );
zProjectName = db_get("project-name", 0);
if( zProjectName==0 ){
zFreeProjectName = zProjectName =
mprintf("Fossil source repository for: %s", zBaseURL);
}
zProjectDescr = db_get("project-description", 0);
if( zProjectDescr==0 ){
zProjectDescr = zProjectName;
}
zPubDate = cgi_rfc822_datestamp(time(NULL));
fossil_print("<?xml version=\"1.0\"?>");
fossil_print("<rss xmlns:dc=\"http://purl.org/dc/elements/1.1/\" "
" version=\"2.0\">");
fossil_print("<channel>\n");
fossil_print("<title>%h</title>\n", zProjectName);
fossil_print("<link>%s</link>\n", zBaseURL);
fossil_print("<description>%h</description>\n", zProjectDescr);
fossil_print("<pubDate>%s</pubDate>\n", zPubDate);
fossil_print("<generator>Fossil version %s %s</generator>\n",
MANIFEST_VERSION, MANIFEST_DATE);
|
| ︙ | ︙ |
Changes to src/search.c.
| ︙ | ︙ | |||
694 695 696 697 698 699 700 |
db_finalize(&q);
blob_reset(&pattern);
}else{
/* Legacy timeline search (the default) */
(void)search_init(blob_str(&pattern),"*","*","...",SRCHFLG_STATIC);
blob_reset(&pattern);
search_sql_setup(g.db);
| | | 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 |
db_finalize(&q);
blob_reset(&pattern);
}else{
/* Legacy timeline search (the default) */
(void)search_init(blob_str(&pattern),"*","*","...",SRCHFLG_STATIC);
blob_reset(&pattern);
search_sql_setup(g.db);
db_multi_exec(
"CREATE TEMP TABLE srch(rid,uuid,date,comment,x);"
"CREATE INDEX srch_idx1 ON srch(x);"
"INSERT INTO srch(rid,uuid,date,comment,x)"
" SELECT blob.rid, uuid, datetime(event.mtime,toLocal()),"
" coalesce(ecomment,comment),"
" search_score()"
|
| ︙ | ︙ | |||
2378 2379 2380 2381 2382 2383 2384 | return rc; } /* ** Argument f should be a flag accepted by matchinfo() (a valid character | | | 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 |
return rc;
}
/*
** Argument f should be a flag accepted by matchinfo() (a valid character
** in the string passed as the second argument). If it is not, -1 is
** returned. Otherwise, if f is a valid matchinfo flag, the value returned
** is the number of 32-bit integers added to the output array if the
** table has nCol columns and the query nPhrase phrases.
*/
static int fts5MatchinfoFlagsize(int nCol, int nPhrase, char f){
int ret = -1;
switch( f ){
|
| ︙ | ︙ |
Changes to src/security_audit.c.
| ︙ | ︙ | |||
334 335 336 337 338 339 340 |
}
/* Anonymous users probably should not be allowed act as moderators
** for wiki or tickets.
*/
if( hasAnyCap(zAnonCap, "lq5") ){
@ <li><p><b>WARNING:</b>
| | | | 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 |
}
/* Anonymous users probably should not be allowed act as moderators
** for wiki or tickets.
*/
if( hasAnyCap(zAnonCap, "lq5") ){
@ <li><p><b>WARNING:</b>
@ Anonymous users can act as moderators for wiki, tickets, or
@ forum posts. This defeats the whole purpose of moderation.
@ Fix this by removing the "Mod-Wiki", "Mod-Tkt", and "Mod-Forum"
@ privileges (<a href="%R/setup_ucap_list">capabilities</a> "fq5")
@ from users "anonymous" and "nobody"
@ on the <a href="setup_ulist">User Configuration</a> page.
}
/* Check to see if any TH1 scripts are configured to run on a sync
*/
if( db_exists("SELECT 1 FROM config WHERE name GLOB 'xfer-*-script'"
" AND length(value)>0") ){
@ <li><p><b>WARNING:</b>
@ TH1 scripts might be configured to run on any sync, push, pull, or
@ clone operation. See the the <a href="%R/xfersetup">/xfersetup</a>
@ page for more information. These TH1 scripts are a potential
@ security concern and so should be carefully audited by a human.
}
/* The strict-manifest-syntax setting should be on. */
if( db_get_boolean("strict-manifest-syntax",1)==0 ){
@ <li><p><b>WARNING:</b>
@ The "strict-manifest-syntax" flag is off. This is a security
@ risk. Turn this setting on (its default) to protect the users
@ of this repository.
|
| ︙ | ︙ | |||
580 581 582 583 584 585 586 |
}else {
double r = atof(db_get("max-loadavg", 0));
if( r<=0.0 ){
@ <li><p>
@ Load average limiting is turned off. This can cause the server
@ to bog down if many requests for expensive services (such as
@ large diffs or tarballs) arrive at about the same time.
| | | 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 |
}else {
double r = atof(db_get("max-loadavg", 0));
if( r<=0.0 ){
@ <li><p>
@ Load average limiting is turned off. This can cause the server
@ to bog down if many requests for expensive services (such as
@ large diffs or tarballs) arrive at about the same time.
@ To fix this, set the
@ <a href='%R/setup_access#slal'>"Server Load Average Limit"</a> on the
@ <a href='%R/setup_access'>Access Control</a> page to the approximate
@ the number of available cores on your server, or maybe just a little
@ less.
}else if( r>=8.0 ){
@ <li><p>
@ The <a href='%R/setup_access#slal'>"Server Load Average Limit"</a> on
|
| ︙ | ︙ | |||
602 603 604 605 606 607 608 |
@ <li><p>
@ The server error log is disabled.
@ To set up an error log,
if( fossil_strcmp(g.zCmdName, "cgi")==0 ){
@ make an entry like "errorlog: <i>FILENAME</i>" in the
@ CGI script at %h(P("SCRIPT_FILENAME")).
}else{
| | | 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 |
@ <li><p>
@ The server error log is disabled.
@ To set up an error log,
if( fossil_strcmp(g.zCmdName, "cgi")==0 ){
@ make an entry like "errorlog: <i>FILENAME</i>" in the
@ CGI script at %h(P("SCRIPT_FILENAME")).
}else{
@ add the "--errorlog <i>FILENAME</i>" option to the
@ "%h(g.argv[0]) %h(g.zCmdName)" command that launched this server.
}
}else{
FILE *pTest = fossil_fopen(g.zErrlog,"a");
if( pTest==0 ){
@ <li><p>
@ <b>Error:</b>
|
| ︙ | ︙ | |||
633 634 635 636 637 638 639 |
@ <li><p> CGI Extensions are enabled with a document root
@ at <a href='%R/extfilelist'>%h(g.zExtRoot)</a> holding
@ %d(nCgi) CGIs and %d(nFile-nCgi) static content and data files.
}
if( fileedit_glob()!=0 ){
@ <li><p><a href='%R/fileedit'>Online File Editing</a> is enabled
| | | | 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 |
@ <li><p> CGI Extensions are enabled with a document root
@ at <a href='%R/extfilelist'>%h(g.zExtRoot)</a> holding
@ %d(nCgi) CGIs and %d(nFile-nCgi) static content and data files.
}
if( fileedit_glob()!=0 ){
@ <li><p><a href='%R/fileedit'>Online File Editing</a> is enabled
@ for this repository. Clear the
@ <a href='%R/setup_settings'>"fileedit-glob" setting</a> to
@ disable online editing.</p>
}
@ <li><p> User capability summary:
capability_summary();
azCSP = parse_content_security_policy();
if( azCSP==0 ){
@ <li><p> WARNING: No Content Security Policy (CSP) is specified in the
@ header. Though not required, a strong CSP is recommended. Fossil will
@ automatically insert an appropriate CSP if you let it generate the
@ HTML <tt><head></tt> element by omitting <tt><body></tt>
@ from the header configuration in your customized skin.
@
}else{
int ii;
@ <li><p> Content Security Policy:
@ <ol type="a">
for(ii=0; azCSP[ii]; ii++){
@ <li>%h(azCSP[ii])
}
|
| ︙ | ︙ | |||
785 786 787 788 789 790 791 |
@ <li><p>
@ If the server is running as CGI, then create a line in the CGI file
@ like this:
@ <blockquote><pre>
@ errorlog: <i>FILENAME</i>
@ </pre></blockquote>
@ <li><p>
| | | 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 |
@ <li><p>
@ If the server is running as CGI, then create a line in the CGI file
@ like this:
@ <blockquote><pre>
@ errorlog: <i>FILENAME</i>
@ </pre></blockquote>
@ <li><p>
@ If the server is running using one of
@ the "fossil http" or "fossil server" commands then add
@ a command-line option "--errorlog <i>FILENAME</i>" to that
@ command.
@ </ol>
style_finish_page();
return;
}
|
| ︙ | ︙ |
Changes to src/setup.c.
| ︙ | ︙ | |||
586 587 588 589 590 591 592 |
@ for users who are not logged in. (Property: "require-captcha")</p>
@ <hr>
entry_attribute("Public pages", 30, "public-pages",
"pubpage", "", 0);
@ <p>A comma-separated list of glob patterns for pages that are accessible
@ without needing a login and using the privileges given by the
| | | 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 |
@ for users who are not logged in. (Property: "require-captcha")</p>
@ <hr>
entry_attribute("Public pages", 30, "public-pages",
"pubpage", "", 0);
@ <p>A comma-separated list of glob patterns for pages that are accessible
@ without needing a login and using the privileges given by the
@ "Default privileges" setting below.
@
@ <p>Example use case: Set this field to "/doc/trunk/www/*" and set
@ the "Default privileges" to include the "o" privilege
@ to give anonymous users read-only permission to the
@ latest version of the embedded documentation in the www/ folder without
@ allowing them to see the rest of the source code.
@ (Property: "public-pages")
|
| ︙ | ︙ | |||
1199 1200 1201 1202 1203 1204 1205 |
@ choices (such as the hamburger button) to the menu that are not shown
@ on this list. (Property: mainmenu)
@ <p>
if(P("resetMenu")!=0){
db_unset("mainmenu", 0);
cgi_delete_parameter("mmenu");
}
| | | 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 |
@ choices (such as the hamburger button) to the menu that are not shown
@ on this list. (Property: mainmenu)
@ <p>
if(P("resetMenu")!=0){
db_unset("mainmenu", 0);
cgi_delete_parameter("mmenu");
}
textarea_attribute("Main Menu", 12, 80,
"mainmenu", "mmenu", style_default_mainmenu(), 0);
@ </p>
@ <p><input type='checkbox' id='cbResetMenu' name='resetMenu' value='1'>
@ <label for='cbResetMenu'>Reset menu to default value</label>
@ </p>
@ <hr>
@ <p>Extra links to appear on the <a href="%R/sitemap">/sitemap</a> page,
|
| ︙ | ︙ | |||
1227 1228 1229 1230 1231 1232 1233 | @ If capexpr evaluates to true, then the entry is shown. If not, @ the entry is omitted. "*" is always true. @ </ol> @ @ <p>The default value is blank, meaning no added entries. @ (Property: sitemap-extra) @ <p> | | | 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 |
@ If capexpr evaluates to true, then the entry is shown. If not,
@ the entry is omitted. "*" is always true.
@ </ol>
@
@ <p>The default value is blank, meaning no added entries.
@ (Property: sitemap-extra)
@ <p>
textarea_attribute("Custom Sitemap Entries", 8, 80,
"sitemap-extra", "smextra", "", 0);
@ <hr>
@ <p><input type="submit" name="submit" value="Apply Changes"></p>
@ </div></form>
db_end_transaction(0);
style_finish_page();
}
|
| ︙ | ︙ |
Changes to src/setupuser.c.
| ︙ | ︙ | |||
808 809 810 811 812 813 814 | @ subscript suffix @ indicates the privileges of <span class="usertype">anonymous</span> that @ are inherited by all logged-in users. @ </p></li> @ @ <li><p> @ The "<span class="ueditInheritDeveloper"><sub>D</sub></span>" | | | 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 | @ subscript suffix @ indicates the privileges of <span class="usertype">anonymous</span> that @ are inherited by all logged-in users. @ </p></li> @ @ <li><p> @ The "<span class="ueditInheritDeveloper"><sub>D</sub></span>" @ subscript suffix indicates the privileges of @ <span class="usertype">developer</span> that @ are inherited by all users with the @ <span class="capability">Developer</span> privilege. @ </p></li> @ @ <li><p> @ The "<span class="ueditInheritReader"><sub>R</sub></span>" subscript suffix |
| ︙ | ︙ |
Changes to src/sha1.c.
| ︙ | ︙ | |||
30 31 32 33 34 35 36 | ** ** Downloaded on 2017-03-01 then repackaged to work with Fossil ** and makeheaders. */ #if FOSSIL_HARDENED_SHA1 #if INTERFACE | | > | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
**
** Downloaded on 2017-03-01 then repackaged to work with Fossil
** and makeheaders.
*/
#if FOSSIL_HARDENED_SHA1
#if INTERFACE
typedef void(*collision_block_callback)(uint64_t, const uint32_t*,
const uint32_t*, const uint32_t*, const uint32_t*);
struct SHA1_CTX {
uint64_t total;
uint32_t ihv[5];
unsigned char buffer[64];
int bigendian;
int found_collision;
int safe_hash;
|
| ︙ | ︙ |
Changes to src/sitemap.c.
| ︙ | ︙ | |||
79 80 81 82 83 84 85 |
g.jsHref = 0;
}
srchFlags = search_restrict(SRCH_ALL);
if( !isPopup ){
style_header("Site Map");
style_adunit_config(ADUNIT_RIGHT_OK);
}
| | | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
g.jsHref = 0;
}
srchFlags = search_restrict(SRCH_ALL);
if( !isPopup ){
style_header("Site Map");
style_adunit_config(ADUNIT_RIGHT_OK);
}
@ <ul id="sitemap" class="columns" style="column-width:20em">
if( (e&1)==0 ){
@ <li>%z(href("%R/home"))Home Page</a>
}
#if 0 /* Removed 2021-01-26 */
for(i=0; i<sizeof(aExtra)/sizeof(aExtra[0]); i++){
|
| ︙ | ︙ | |||
150 151 152 153 154 155 156 |
}
@ <li>%z(href("%R/docsrch"))Documentation Search</a></li>
}
#endif
if( inSublist ){
@ </ul>
| | | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
}
@ <li>%z(href("%R/docsrch"))Documentation Search</a></li>
}
#endif
if( inSublist ){
@ </ul>
inSublist = 0;
}
@ </li>
if( g.perm.Read ){
const char *zEditGlob = db_get("fileedit-glob","");
@ <li>%z(href("%R/tree"))File Browser</a>
@ <ul>
@ <li>%z(href("%R/tree?type=tree&ci=trunk"))Tree-view,
|
| ︙ | ︙ |
Changes to src/skins.c.
| ︙ | ︙ | |||
883 884 885 886 887 888 889 |
DiffConfig DCfg;
construct_diff_flags(1, &DCfg);
DCfg.diffFlags |= DIFF_STRIP_EOLCR;
if( P("sbsdiff")!=0 ) DCfg.diffFlags |= DIFF_SIDEBYSIDE;
blob_init(&to, zContent, -1);
blob_init(&from, skin_file_content(zBasis, zFile), -1);
blob_zero(&out);
| | | 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 |
DiffConfig DCfg;
construct_diff_flags(1, &DCfg);
DCfg.diffFlags |= DIFF_STRIP_EOLCR;
if( P("sbsdiff")!=0 ) DCfg.diffFlags |= DIFF_SIDEBYSIDE;
blob_init(&to, zContent, -1);
blob_init(&from, skin_file_content(zBasis, zFile), -1);
blob_zero(&out);
DCfg.diffFlags |= DIFF_HTML | DIFF_NOTTOOBIG;
if( DCfg.diffFlags & DIFF_SIDEBYSIDE ){
text_diff(&from, &to, &out, &DCfg);
@ %s(blob_str(&out))
}else{
DCfg.diffFlags |= DIFF_LINENO;
text_diff(&from, &to, &out, &DCfg);
@ <pre class="udiff">
|
| ︙ | ︙ | |||
1204 1205 1206 1207 1208 1209 1210 |
}else if( pAltSkin ){
char *zPattern = mprintf("*/skn_%s", pAltSkin->zLabel);
if( sqlite3_strglob(zPattern, zBase)==0 ){
nBase -= strlen(zPattern)-1;
zBase[nBase] = 0;
}
fossil_free(zPattern);
| | | 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 |
}else if( pAltSkin ){
char *zPattern = mprintf("*/skn_%s", pAltSkin->zLabel);
if( sqlite3_strglob(zPattern, zBase)==0 ){
nBase -= strlen(zPattern)-1;
zBase[nBase] = 0;
}
fossil_free(zPattern);
}
login_check_credentials();
style_header("Skins");
if( iDraftSkin || nSkinRank<=1 ){
@ <p class="warning">Warning:
if( iDraftSkin>0 ){
@ you are using a draft skin,
}else{
|
| ︙ | ︙ |
Changes to src/smtp.c.
| ︙ | ︙ | |||
17 18 19 20 21 22 23 | ** ** Implementation of SMTP (Simple Mail Transport Protocol) according ** to RFC 5321. */ #include "config.h" #include "smtp.h" #include <assert.h> | | | | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
**
** Implementation of SMTP (Simple Mail Transport Protocol) according
** to RFC 5321.
*/
#include "config.h"
#include "smtp.h"
#include <assert.h>
#if (HAVE_DN_EXPAND || HAVE___NS_NAME_UNCOMPRESS || HAVE_NS_NAME_UNCOMPRESS) \
&& (HAVE_NS_PARSERR || HAVE___NS_PARSERR) && !defined(FOSSIL_OMIT_DNS)
# include <sys/types.h>
# include <netinet/in.h>
# if defined(HAVE_BIND_RESOLV_H)
# include <bind/resolv.h>
# include <bind/arpa/nameser_compat.h>
# else
# include <arpa/nameser.h>
|
| ︙ | ︙ |
Changes to src/sqlcmd.c.
| ︙ | ︙ | |||
382 383 384 385 386 387 388 |
** files_of_checkin(X) A table-valued function that returns info on
** all files contained in check-in X. Example:
**
** SELECT * FROM files_of_checkin('trunk');
**
** helptext A virtual table with one row for each command,
** webpage, and setting together with the built-in
| | | 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
** files_of_checkin(X) A table-valued function that returns info on
** all files contained in check-in X. Example:
**
** SELECT * FROM files_of_checkin('trunk');
**
** helptext A virtual table with one row for each command,
** webpage, and setting together with the built-in
** help text.
**
** now() Return the number of seconds since 1970.
**
** obscure(T) Obfuscate the text password T so that its
** original value is not readily visible. Fossil
** uses this same algorithm when storing passwords
** of remote URLs.
|
| ︙ | ︙ |
Changes to src/stat.c.
| ︙ | ︙ | |||
555 556 557 558 559 560 561 |
}else{
@ <tr><td width='100%%'>%h(db_column_text(&q,0))</td>
@ <td><nobr>%h(db_column_text(&q,1))</nobr></td></tr>
}
cnt++;
}
db_finalize(&q);
| | | 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 |
}else{
@ <tr><td width='100%%'>%h(db_column_text(&q,0))</td>
@ <td><nobr>%h(db_column_text(&q,1))</nobr></td></tr>
}
cnt++;
}
db_finalize(&q);
if( nOmitted ){
@ <tr><td><a href="urllist?all"><i>Show %d(nOmitted) more...</i></a>
}
if( cnt ){
@ </table>
total += cnt;
}
|
| ︙ | ︙ | |||
713 714 715 716 717 718 719 |
void repo_schema_page(void){
Stmt q;
Blob sql;
const char *zArg = P("n");
login_check_credentials();
if( !g.perm.Admin ){ login_needed(0); return; }
| | | 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 |
void repo_schema_page(void){
Stmt q;
Blob sql;
const char *zArg = P("n");
login_check_credentials();
if( !g.perm.Admin ){ login_needed(0); return; }
if( zArg!=0
&& db_table_exists("repository",zArg)
&& cgi_csrf_safe(1)
){
if( P("analyze")!=0 ){
db_multi_exec("ANALYZE \"%w\"", zArg);
}else if( P("analyze200")!=0 ){
db_multi_exec("PRAGMA analysis_limit=200; ANALYZE \"%w\"", zArg);
|
| ︙ | ︙ | |||
932 933 934 935 936 937 938 |
/*
** Gather statistics on artifact types, counts, and sizes.
**
** Only populate the artstat.atype field if the bWithTypes parameter is true.
*/
void gather_artifact_stats(int bWithTypes){
| | | | | | | | | | | | 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 |
/*
** Gather statistics on artifact types, counts, and sizes.
**
** Only populate the artstat.atype field if the bWithTypes parameter is true.
*/
void gather_artifact_stats(int bWithTypes){
static const char zSql[] =
@ CREATE TEMP TABLE artstat(
@ id INTEGER PRIMARY KEY, -- Corresponds to BLOB.RID
@ atype TEXT, -- 'data', 'manifest', 'tag', 'wiki', etc.
@ isDelta BOOLEAN, -- true if stored as a delta
@ szExp, -- expanded, uncompressed size
@ szCmpr -- size as stored on disk
@ );
@ INSERT INTO artstat(id,atype,isDelta,szExp,szCmpr)
@ SELECT blob.rid, NULL,
@ delta.rid IS NOT NULL,
@ size, octet_length(content)
@ FROM blob LEFT JOIN delta ON blob.rid=delta.rid
@ WHERE content IS NOT NULL;
;
static const char zSql2[] =
@ UPDATE artstat SET atype='file'
@ WHERE +id IN (SELECT fid FROM mlink);
@ UPDATE artstat SET atype='manifest'
@ WHERE id IN (SELECT objid FROM event WHERE type='ci') AND atype IS NULL;
@ UPDATE artstat SET atype='forum'
@ WHERE id IN (SELECT objid FROM event WHERE type='f') AND atype IS NULL;
@ UPDATE artstat SET atype='cluster'
@ WHERE atype IS NULL
@ AND id IN (SELECT rid FROM tagxref
@ WHERE tagid=(SELECT tagid FROM tag
@ WHERE tagname='cluster'));
@ UPDATE artstat SET atype='ticket'
@ WHERE atype IS NULL
@ AND id IN (SELECT rid FROM tagxref
@ WHERE tagid IN (SELECT tagid FROM tag
@ WHERE tagname GLOB 'tkt-*'));
@ UPDATE artstat SET atype='wiki'
@ WHERE atype IS NULL
@ AND id IN (SELECT rid FROM tagxref
@ WHERE tagid IN (SELECT tagid FROM tag
@ WHERE tagname GLOB 'wiki-*'));
@ UPDATE artstat SET atype='technote'
@ WHERE atype IS NULL
@ AND id IN (SELECT rid FROM tagxref
@ WHERE tagid IN (SELECT tagid FROM tag
@ WHERE tagname GLOB 'event-*'));
@ UPDATE artstat SET atype='attachment'
@ WHERE atype IS NULL
@ AND id IN (SELECT attachid FROM attachment UNION
@ SELECT blob.rid FROM attachment JOIN blob ON uuid=src);
@ UPDATE artstat SET atype='tag'
@ WHERE atype IS NULL
@ AND id IN (SELECT srcid FROM tagxref);
@ UPDATE artstat SET atype='tag'
@ WHERE atype IS NULL
@ AND id IN (SELECT objid FROM event WHERE type='g');
@ UPDATE artstat SET atype='unused' WHERE atype IS NULL;
;
db_multi_exec("%s", zSql/*safe-for-%s*/);
if( bWithTypes ){
db_multi_exec("%s", zSql2/*safe-for-%s*/);
}
|
| ︙ | ︙ |
Changes to src/statrep.c.
| ︙ | ︙ | |||
128 129 130 131 132 133 134 |
const char *zNot = rc=='n' ? "NOT" : "";
statsReportTimelineYFlag = "ci";
db_multi_exec(
"CREATE TEMP VIEW v_reports AS "
"SELECT * FROM event WHERE type='ci' AND %s"
" AND objid %s IN (SELECT cid FROM plink WHERE NOT isprim)",
zTimeSpan/*safe-for-%s*/, zNot/*safe-for-%s*/
| | | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
const char *zNot = rc=='n' ? "NOT" : "";
statsReportTimelineYFlag = "ci";
db_multi_exec(
"CREATE TEMP VIEW v_reports AS "
"SELECT * FROM event WHERE type='ci' AND %s"
" AND objid %s IN (SELECT cid FROM plink WHERE NOT isprim)",
zTimeSpan/*safe-for-%s*/, zNot/*safe-for-%s*/
);
}
return statsReportType = rc;
}
/*
** Returns a string suitable (for a given value of suitable) for
** use in a label with the header of the /reports pages, dependent
|
| ︙ | ︙ |
Changes to src/style.c.
| ︙ | ︙ | |||
450 451 452 453 454 455 456 |
** or after any updates to the CSS files
*/
blob_appendf(&url, "?id=%x", skin_id("css"));
if( P("once")!=0 && P("skin")!=0 ){
blob_appendf(&url, "&skin=%s&once", skin_in_use());
}
| | | | 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 |
** or after any updates to the CSS files
*/
blob_appendf(&url, "?id=%x", skin_id("css"));
if( P("once")!=0 && P("skin")!=0 ){
blob_appendf(&url, "&skin=%s&once", skin_in_use());
}
/* Generate the CSS URL variable */
Th_Store("stylesheet_url", blob_str(&url));
blob_reset(&url);
}
/*
** Create a TH1 variable containing the URL for the specified image.
** The resulting variable name will be of the form $[zImageName]_image_url.
** The value will be a URL that includes an id= query parameter that
** changes if the underlying resource changes or if a different skin
** is selected.
*/
static void image_url_var(const char *zImageName){
char *zVarName; /* Name of the new TH1 variable */
char *zResource; /* Name of CONFIG entry holding content */
char *zUrl; /* The URL */
zResource = mprintf("%s-image", zImageName);
zUrl = mprintf("%R/%s?id=%x", zImageName, skin_id(zResource));
free(zResource);
zVarName = mprintf("%s_image_url", zImageName);
Th_Store(zVarName, zUrl);
free(zVarName);
free(zUrl);
}
/*
** Output TEXT with a click-to-copy button next to it. Loads the copybtn.js
|
| ︙ | ︙ | |||
595 596 597 598 599 600 601 |
** The text '$nonce' is replaced by style_nonce() if and whereever it
** occurs in the input string.
**
** The string returned is obtained from fossil_malloc() and
** should be released by the caller.
*/
char *style_csp(int toHeader){
| | | 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 |
** The text '$nonce' is replaced by style_nonce() if and whereever it
** occurs in the input string.
**
** The string returned is obtained from fossil_malloc() and
** should be released by the caller.
*/
char *style_csp(int toHeader){
static const char zBackupCSP[] =
"default-src 'self' data:; "
"script-src 'self' 'nonce-$nonce'; "
"style-src 'self' 'unsafe-inline'; "
"img-src * data:";
const char *zFormat;
Blob csp;
char *zNonce;
|
| ︙ | ︙ | |||
631 632 633 634 635 636 637 | return zCsp; } /* ** Disable content security policy for the current page. ** WARNING: Do not do this lightly! ** | | | | 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 |
return zCsp;
}
/*
** Disable content security policy for the current page.
** WARNING: Do not do this lightly!
**
** This routine must be called before the CSP is sued by
** style_header().
*/
void style_disable_csp(void){
disableCSP = 1;
}
/*
** Default HTML page header text through <body>. If the repository-specific
** header template lacks a <body> tag, then all of the following is
** prepended.
*/
static const char zDfltHeader[] =
@ <html>
@ <head>
@ <meta charset="UTF-8">
@ <base href="$baseurl/$current_page">
@ <meta http-equiv="Content-Security-Policy" content="$default_csp">
@ <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ <title>$<project_name>: $<title></title>
|
| ︙ | ︙ | |||
668 669 670 671 672 673 674 |
const char *get_default_header(){
return zDfltHeader;
}
/*
** The default TCL list that defines the main menu.
*/
| | | 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 |
const char *get_default_header(){
return zDfltHeader;
}
/*
** The default TCL list that defines the main menu.
*/
static const char zDfltMainMenu[] =
@ Home /home * {}
@ Timeline /timeline {o r j} {}
@ Files /dir?ci=tip oh desktoponly
@ Branches /brlist o wideonly
@ Tags /taglist o wideonly
@ Forum /forum {@2 3 4 5 6} wideonly
@ Chat /chat C wideonly
|
| ︙ | ︙ | |||
793 794 795 796 797 798 799 |
if( !login_is_nobody() ){
Th_Store("login", g.zLogin);
}
Th_MaybeStore("current_feature", feature_from_page_path(local_zCurrentPage) );
if( g.ftntsIssues[0] || g.ftntsIssues[1] ||
g.ftntsIssues[2] || g.ftntsIssues[3] ){
char buf[80];
| | | | 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 |
if( !login_is_nobody() ){
Th_Store("login", g.zLogin);
}
Th_MaybeStore("current_feature", feature_from_page_path(local_zCurrentPage) );
if( g.ftntsIssues[0] || g.ftntsIssues[1] ||
g.ftntsIssues[2] || g.ftntsIssues[3] ){
char buf[80];
sqlite3_snprintf(sizeof(buf), buf, "%i %i %i %i", g.ftntsIssues[0],
g.ftntsIssues[1], g.ftntsIssues[2], g.ftntsIssues[3]);
Th_Store("footnotes_issues_counters", buf);
}
}
/*
** Draw the header.
*/
|
| ︙ | ︙ | |||
1283 1284 1285 1286 1287 1288 1289 | ** * $basename ** * $secureurl ** * $home ** * $logo ** * $background ** ** The output from TH1 becomes the style sheet. Fossil always reports | | | 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 |
** * $basename
** * $secureurl
** * $home
** * $logo
** * $background
**
** The output from TH1 becomes the style sheet. Fossil always reports
** that the style sheet is cacheable.
*/
void page_style_css(void){
Blob css = empty_blob;
int i;
const char * zDefaults;
const char *zSkin;
|
| ︙ | ︙ | |||
1323 1324 1325 1326 1327 1328 1329 | /* Tell CGI that the content returned by this page is considered cacheable */ g.isConst = 1; } /* ** All possible capabilities */ | | | 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 |
/* Tell CGI that the content returned by this page is considered cacheable */
g.isConst = 1;
}
/*
** All possible capabilities
*/
static const char allCap[] =
"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKL";
/*
** Compute the current login capabilities
*/
static char *find_capabilities(char *zCap){
int i, j;
|
| ︙ | ︙ | |||
1477 1478 1479 1480 1481 1482 1483 |
break;
}
default: {
@ CSRF safety = unsafe<br>
break;
}
}
| | | 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 |
break;
}
default: {
@ CSRF safety = unsafe<br>
break;
}
}
@ fossil_exe_id() = %h(fossil_exe_id())<br>
if( g.perm.Admin ){
int k;
for(k=0; g.argvOrig[k]; k++){
Blob t;
blob_init(&t, 0, 0);
blob_append_escaped_arg(&t, g.argvOrig[k], 0);
|
| ︙ | ︙ | |||
1649 1650 1651 1652 1653 1654 1655 |
** Example:
**
** style_select_list_int("my-grapes", "my_grapes", "Grapes",
** "Select the number of grapes",
** atoi(PD("my_field","0")),
** "", 1, "2", 2, "Three", 3,
** NULL);
| | | 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 |
** Example:
**
** style_select_list_int("my-grapes", "my_grapes", "Grapes",
** "Select the number of grapes",
** atoi(PD("my_field","0")),
** "", 1, "2", 2, "Three", 3,
** NULL);
**
*/
void style_select_list_int(const char * zWrapperId,
const char *zFieldName, const char * zLabel,
const char * zToolTip, int selectedVal,
... ){
char * zLabelID = style_next_input_id();
va_list vargs;
|
| ︙ | ︙ | |||
1773 1774 1775 1776 1777 1778 1779 |
if( z[0]=='/' || z[0]=='\\' ){
zOrigin = z+1;
}
}
CX("<script nonce='%s'>/* %s:%d */\n", style_nonce(), zOrigin, iLine);
}
| | | 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 |
if( z[0]=='/' || z[0]=='\\' ){
zOrigin = z+1;
}
}
CX("<script nonce='%s'>/* %s:%d */\n", style_nonce(), zOrigin, iLine);
}
/* Generate the closing </script> tag
*/
void style_script_end(void){
CX("</script>\n");
}
/*
** Emits a NOSCRIPT tag with an error message stating that JS is
|
| ︙ | ︙ |
Changes to src/sync.c.
| ︙ | ︙ | |||
126 127 128 129 130 131 132 |
int configSync = 0; /* configuration changes transferred */
if( g.fNoSync ){
return 0;
}
zAutosync = db_get_for_subsystem("autosync", zSubsys);
if( zAutosync==0 ) zAutosync = "on"; /* defend against misconfig */
if( is_false(zAutosync) ) return 0;
| | | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
int configSync = 0; /* configuration changes transferred */
if( g.fNoSync ){
return 0;
}
zAutosync = db_get_for_subsystem("autosync", zSubsys);
if( zAutosync==0 ) zAutosync = "on"; /* defend against misconfig */
if( is_false(zAutosync) ) return 0;
if( db_get_boolean("dont-push",0)
|| sqlite3_strglob("*pull*", zAutosync)==0
){
flags &= ~SYNC_CKIN_LOCK;
if( flags & SYNC_PUSH ) return 0;
}
if( find_option("verbose","v",0)!=0 ) flags |= SYNC_VERBOSE;
url_parse(0, URL_REMEMBER|URL_USE_CONFIG);
|
| ︙ | ︙ | |||
531 532 533 534 535 536 537 | ** ** > fossil remote list|ls ** ** Show all remote repository URLs. ** ** > fossil remote off ** | | | 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 | ** ** > fossil remote list|ls ** ** Show all remote repository URLs. ** ** > fossil remote off ** ** Forget the default URL. This disables autosync. ** ** This is a convenient way to enter "airplane mode". To enter ** airplane mode, first save the current default URL, then turn the ** default off. Perhaps like this: ** ** fossil remote add main default ** fossil remote off |
| ︙ | ︙ | |||
593 594 595 596 597 598 599 | ** ** The last-sync-url is called "default" for the display list. ** ** The last-sync-url might be duplicated into one of the sync-url:NAME ** entries. Thus, when doing a "fossil sync --all" or an autosync with ** autosync=all, each sync-url:NAME entry is checked to see if it is the ** same as last-sync-url and if it is then that entry is skipped. | | | 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 |
**
** The last-sync-url is called "default" for the display list.
**
** The last-sync-url might be duplicated into one of the sync-url:NAME
** entries. Thus, when doing a "fossil sync --all" or an autosync with
** autosync=all, each sync-url:NAME entry is checked to see if it is the
** same as last-sync-url and if it is then that entry is skipped.
*/
if( g.argc==2 ){
/* "fossil remote" with no arguments: Show the last sync URL. */
zUrl = db_get("last-sync-url", 0);
if( zUrl==0 ){
fossil_print("off\n");
}else{
|
| ︙ | ︙ |
Changes to src/tag.c.
| ︙ | ︙ | |||
638 639 640 641 642 643 644 |
const char *zTagPrefix = find_option("prefix","",1);
int nTagType = fRaw ? -1 : 0;
if( zTagType!=0 ){
int l = strlen(zTagType);
if( strncmp(zTagType,"cancel",l)==0 ){
nTagType = 0;
| | | | 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 |
const char *zTagPrefix = find_option("prefix","",1);
int nTagType = fRaw ? -1 : 0;
if( zTagType!=0 ){
int l = strlen(zTagType);
if( strncmp(zTagType,"cancel",l)==0 ){
nTagType = 0;
}else if( strncmp(zTagType,"singleton",l)==0 ){
nTagType = 1;
}else if( strncmp(zTagType,"propagated",l)==0 ){
nTagType = 2;
}else{
fossil_fatal("unrecognized tag type");
}
}
if( g.argc==3 ){
const int nTagPrefix = zTagPrefix ? (int)strlen(zTagPrefix) : 0;
|
| ︙ | ︙ |
Changes to src/tar.c.
| ︙ | ︙ | |||
242 243 244 245 246 247 248 |
n /= 10;
}
/* adding the length extended the length field? */
if(blen > next10){
blen++;
}
/* build the string */
| | > | 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
n /= 10;
}
/* adding the length extended the length field? */
if(blen > next10){
blen++;
}
/* build the string */
blob_appendf(&tball.pax, "%d %s=%*.*s\n",
blen, zField, nValue, nValue, zValue);
/* this _must_ be right */
if((int)blob_size(&tball.pax) != blen){
fossil_panic("internal error: PAX tar header has bad length");
}
}
|
| ︙ | ︙ |
Changes to src/th_main.c.
| ︙ | ︙ | |||
29 30 31 32 33 34 35 | */ #define TH_INIT_NONE ((u32)0x00000000) /* No flags. */ #define TH_INIT_NEED_CONFIG ((u32)0x00000001) /* Open configuration first? */ #define TH_INIT_FORCE_TCL ((u32)0x00000002) /* Force Tcl to be enabled? */ #define TH_INIT_FORCE_RESET ((u32)0x00000004) /* Force TH1 commands re-added? */ #define TH_INIT_FORCE_SETUP ((u32)0x00000008) /* Force eval of setup script? */ #define TH_INIT_NO_REPO ((u32)0x00000010) /* Skip opening repository. */ | | > | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
*/
#define TH_INIT_NONE ((u32)0x00000000) /* No flags. */
#define TH_INIT_NEED_CONFIG ((u32)0x00000001) /* Open configuration first? */
#define TH_INIT_FORCE_TCL ((u32)0x00000002) /* Force Tcl to be enabled? */
#define TH_INIT_FORCE_RESET ((u32)0x00000004) /* Force TH1 commands re-added? */
#define TH_INIT_FORCE_SETUP ((u32)0x00000008) /* Force eval of setup script? */
#define TH_INIT_NO_REPO ((u32)0x00000010) /* Skip opening repository. */
#define TH_INIT_NO_ENCODE ((u32)0x00000020) /* Do not html-encode sendText()*/
/* output. */
#define TH_INIT_MASK ((u32)0x0000003F) /* All possible init flags. */
/*
** Useful and/or "well-known" combinations of flag values.
*/
#define TH_INIT_DEFAULT (TH_INIT_NONE) /* Default flags. */
#define TH_INIT_HOOK (TH_INIT_NEED_CONFIG | TH_INIT_FORCE_SETUP)
|
| ︙ | ︙ |
Changes to src/th_tcl.c.
| ︙ | ︙ | |||
1162 1163 1164 1165 1166 1167 1168 |
Tcl_DeleteInterp(tclInterp); /* TODO: Redundant? */
tclInterp = 0;
return TH_ERROR;
}
tclContext->interp = tclInterp;
if( Tcl_Init(tclInterp)!=TCL_OK ){
Th_ErrorMessage(interp,
| | > | > | 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 |
Tcl_DeleteInterp(tclInterp); /* TODO: Redundant? */
tclInterp = 0;
return TH_ERROR;
}
tclContext->interp = tclInterp;
if( Tcl_Init(tclInterp)!=TCL_OK ){
Th_ErrorMessage(interp,
"Tcl initialization error:",
Tcl_GetString(Tcl_GetObjResult(tclInterp)), -1);
Tcl_DeleteInterp(tclInterp);
tclContext->interp = tclInterp = 0;
return TH_ERROR;
}
if( setTclArguments(tclInterp, argc, argv)!=TCL_OK ){
Th_ErrorMessage(interp,
"Tcl error setting arguments:",
Tcl_GetString(Tcl_GetObjResult(tclInterp)), -1);
Tcl_DeleteInterp(tclInterp);
tclContext->interp = tclInterp = 0;
return TH_ERROR;
}
/*
** Determine (and cache) if an objProc can be called directly for a Tcl
** command invoked via the tclInvoke TH1 command.
|
| ︙ | ︙ | |||
1192 1193 1194 1195 1196 1197 1198 |
Tcl_CallWhenDeleted(tclInterp, Th1DeleteProc, interp);
Tcl_CreateObjCommand(tclInterp, "th1Eval", Th1EvalObjCmd, interp, NULL);
Tcl_CreateObjCommand(tclInterp, "th1Expr", Th1ExprObjCmd, interp, NULL);
/* If necessary, evaluate the custom Tcl setup script. */
setup = tclContext->setup;
if( setup && Tcl_EvalEx(tclInterp, setup, -1, 0)!=TCL_OK ){
Th_ErrorMessage(interp,
| | > | 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 |
Tcl_CallWhenDeleted(tclInterp, Th1DeleteProc, interp);
Tcl_CreateObjCommand(tclInterp, "th1Eval", Th1EvalObjCmd, interp, NULL);
Tcl_CreateObjCommand(tclInterp, "th1Expr", Th1ExprObjCmd, interp, NULL);
/* If necessary, evaluate the custom Tcl setup script. */
setup = tclContext->setup;
if( setup && Tcl_EvalEx(tclInterp, setup, -1, 0)!=TCL_OK ){
Th_ErrorMessage(interp,
"Tcl setup script error:",
Tcl_GetString(Tcl_GetObjResult(tclInterp)), -1);
Tcl_DeleteInterp(tclInterp);
tclContext->interp = tclInterp = 0;
return TH_ERROR;
}
return TH_OK;
}
|
| ︙ | ︙ |
Changes to src/timeline.c.
| ︙ | ︙ | |||
39 40 41 42 43 44 45 |
#define TIMELINE_FMT_ONELINE \
"%h %c"
#define TIMELINE_FMT_MEDIUM \
"Commit: %h%nDate: %d%nAuthor: %a%nComment: %c"
#define TIMELINE_FMT_FULL \
"Commit: %H%nDate: %d%nAuthor: %a%nComment: %c%n"\
| | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
#define TIMELINE_FMT_ONELINE \
"%h %c"
#define TIMELINE_FMT_MEDIUM \
"Commit: %h%nDate: %d%nAuthor: %a%nComment: %c"
#define TIMELINE_FMT_FULL \
"Commit: %H%nDate: %d%nAuthor: %a%nComment: %c%n"\
"Branch: %b%nTags: %t%nPhase: %p"
/*
** Add an appropriate tag to the output if "rid" is unpublished (private)
*/
#define UNPUB_TAG "<em>(unpublished)</em>"
void tag_private_status(int rid){
if( content_is_private(rid) ){
cgi_printf(" %s", UNPUB_TAG);
|
| ︙ | ︙ | |||
151 152 153 154 155 156 157 | db_bind_int(&q, "$rid", rid); res = db_step(&q)==SQLITE_ROW; db_reset(&q); return res; } /* | | | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
db_bind_int(&q, "$rid", rid);
res = db_step(&q)==SQLITE_ROW;
db_reset(&q);
return res;
}
/*
** Return the text of the unformatted
** forum post given by the RID in the argument.
*/
static void forum_post_content_function(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
|
| ︙ | ︙ | |||
364 365 366 367 368 369 370 |
int isClosed = 0;
if( is_ticket(zTktid, &isClosed) && isClosed ){
zExtraClass = " tktTlClosed";
}else{
zExtraClass = " tktTlOpen";
}
fossil_free(zTktid);
| | | 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 |
int isClosed = 0;
if( is_ticket(zTktid, &isClosed) && isClosed ){
zExtraClass = " tktTlClosed";
}else{
zExtraClass = " tktTlOpen";
}
fossil_free(zTktid);
}
}
if( zType[0]=='e' && tagid ){
if( bTimestampLinksToInfo ){
char *zId;
zId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d",
tagid);
zDateLink = href("%R/technote/%s",zId);
|
| ︙ | ︙ | |||
674 675 676 677 678 679 680 |
cgi_printf(" tags: %h", zTagList);
}
}
if( tmFlags & TIMELINE_SHOWRID ){
int srcId = delta_source_rid(rid);
if( srcId ){
| | | 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 |
cgi_printf(" tags: %h", zTagList);
}
}
if( tmFlags & TIMELINE_SHOWRID ){
int srcId = delta_source_rid(rid);
if( srcId ){
cgi_printf(" id: %z%d←%d</a>",
href("%R/deltachain/%d",rid), rid, srcId);
}else{
cgi_printf(" id: %z%d</a>",
href("%R/deltachain/%d",rid), rid);
}
}
tag_private_status(rid);
|
| ︙ | ︙ | |||
2220 2221 2222 2223 2224 2225 2226 |
}
blob_appendf(&desc, " of %z%h</a>",
href("%R/info?name=%h", zCiName), zCiName);
if( ridBackTo ){
if( np==0 ){
blob_reset(&desc);
| | | | 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 |
}
blob_appendf(&desc, " of %z%h</a>",
href("%R/info?name=%h", zCiName), zCiName);
if( ridBackTo ){
if( np==0 ){
blob_reset(&desc);
blob_appendf(&desc,
"Check-in %z%h</a> only (%z%h</a> is not an ancestor)",
href("%R/info?name=%h",zCiName), zCiName,
href("%R/info?name=%h",zBackTo), zBackTo);
}else{
blob_appendf(&desc, " back to %z%h</a>",
href("%R/info?name=%h",zBackTo), zBackTo);
if( ridFwdTo && zFwdTo ){
blob_appendf(&desc, " and up to %z%h</a>",
href("%R/info?name=%h",zFwdTo), zFwdTo);
}
}
}else if( ridFwdTo ){
if( nd==0 ){
blob_reset(&desc);
blob_appendf(&desc,
"Check-in %z%h</a> only (%z%h</a> is not an descendant)",
href("%R/info?name=%h",zCiName), zCiName,
href("%R/info?name=%h",zFwdTo), zFwdTo);
}else{
blob_appendf(&desc, " up to %z%h</a>",
href("%R/info?name=%h",zFwdTo), zFwdTo);
}
|
| ︙ | ︙ | |||
3015 3016 3017 3018 3019 3020 3021 | ** 6. mtime ** 7. branch ** 8. event-type: 'ci', 'w', 't', 'f', and so forth. ** 9. comment ** 10. user ** 11. tags */ | | > > | | > | | 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 |
** 6. mtime
** 7. branch
** 8. event-type: 'ci', 'w', 't', 'f', and so forth.
** 9. comment
** 10. user
** 11. tags
*/
void print_timeline(Stmt *q, int nLimit, int width, const char *zFormat,
int verboseFlag){
int nAbsLimit = (nLimit >= 0) ? nLimit : -nLimit;
int nLine = 0;
int nEntry = 0;
char zPrevDate[20];
const char *zCurrentUuid = 0;
int fchngQueryInit = 0; /* True if fchngQuery is initialized */
Stmt fchngQuery; /* Query for file changes on check-ins */
int rc;
/* True: separate entries with a newline after file listing */
int bVerboseNL = (zFormat &&
(fossil_strcmp(zFormat, TIMELINE_FMT_ONELINE)!=0));
/* True: separate entries with a newline even with no file listing */
int bNoVerboseNL = (zFormat &&
(fossil_strcmp(zFormat, TIMELINE_FMT_MEDIUM)==0 ||
fossil_strcmp(zFormat, TIMELINE_FMT_FULL)==0));
zPrevDate[0] = 0;
if( g.localOpen ){
int rid = db_lget_int("checkout", 0);
zCurrentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
}
|
| ︙ | ︙ | |||
3120 3121 3122 3123 3124 3125 3126 |
if( zFormat ){
char *zEntry;
int nEntryLine = 0;
if( nChild==0 ){
sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*LEAF* ");
}
| | | > | 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 |
if( zFormat ){
char *zEntry;
int nEntryLine = 0;
if( nChild==0 ){
sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*LEAF* ");
}
zEntry = timeline_entry_subst(zFormat, &nEntryLine, zId, zDate,
zUserShort, zComShort, zBranch, zTags,
zPrefix);
nLine += nEntryLine;
fossil_print("%s\n", zEntry);
fossil_free(zEntry);
}
else{
/* record another X lines */
nLine += comment_print(zFree, zCom, 9, width, get_comment_format());
|
| ︙ | ︙ | |||
3165 3166 3167 3168 3169 3170 3171 |
nLine++; /* record another line */
}
db_reset(&fchngQuery);
if( bVerboseNL ) fossil_print("\n");
}else{
if( bNoVerboseNL ) fossil_print("\n");
}
| | | 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 |
nLine++; /* record another line */
}
db_reset(&fchngQuery);
if( bVerboseNL ) fossil_print("\n");
}else{
if( bNoVerboseNL ) fossil_print("\n");
}
nEntry++; /* record another complete entry */
}
if( rc==SQLITE_DONE ){
/* Did the underlying query actually have all entries? */
if( nAbsLimit==0 ){
fossil_print("+++ end of timeline (%d) +++\n", nEntry);
}else{
|
| ︙ | ︙ | |||
3209 3210 3211 3212 3213 3214 3215 |
@ event.type
@ , coalesce(ecomment,comment) AS comment0
@ , coalesce(euser,user,'?') AS user0
@ , (SELECT case when length(x)>0 then x else '' end
@ FROM (SELECT group_concat(substr(tagname,5), ', ') AS x
@ FROM tag, tagxref
@ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid
| | | 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 |
@ event.type
@ , coalesce(ecomment,comment) AS comment0
@ , coalesce(euser,user,'?') AS user0
@ , (SELECT case when length(x)>0 then x else '' end
@ FROM (SELECT group_concat(substr(tagname,5), ', ') AS x
@ FROM tag, tagxref
@ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid
@ AND tagxref.rid=blob.rid AND tagxref.tagtype>0)) AS tags
@ FROM tag CROSS JOIN event CROSS JOIN blob
@ LEFT JOIN tagxref ON tagxref.tagid=tag.tagid
@ AND tagxref.tagtype>0
@ AND tagxref.rid=blob.rid
@ WHERE blob.rid=event.objid
@ AND tag.tagname='branch'
;
|
| ︙ | ︙ | |||
3270 3271 3272 3273 3274 3275 3276 | ** means UTC. ** ** ** Options: ** -b|--branch BRANCH Show only items on the branch named BRANCH ** -c|--current-branch Show only items on the current branch ** -F|--format Entry format. Values "oneline", "medium", and "full" | | | | 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 | ** means UTC. ** ** ** Options: ** -b|--branch BRANCH Show only items on the branch named BRANCH ** -c|--current-branch Show only items on the current branch ** -F|--format Entry format. Values "oneline", "medium", and "full" ** get mapped to the full options below. Otherwise a ** string which can contain these placeholders: ** %n newline ** %% a raw % ** %H commit hash ** %h abbreviated commit hash ** %a author name ** %d date ** %c comment (NL, TAB replaced by space, LF erased) ** %b branch ** %t tags ** %p phase: zero or more of *CURRENT*, *MERGE*, ** *FORK*, *UNPUBLISHED*, *LEAF*, *BRANCH* ** --oneline Show only short hash and comment for each entry ** --medium Medium-verbose entry formatting ** --full Extra verbose entry formatting |
| ︙ | ︙ |
Changes to src/tkt.c.
| ︙ | ︙ | |||
555 556 557 558 559 560 561 |
case SQLITE_CREATE_VIEW:
case SQLITE_CREATE_TABLE: {
if( sqlite3_stricmp(z2,"main")!=0
&& sqlite3_stricmp(z2,"repository")!=0
){
goto ticket_schema_error;
}
| | | 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 |
case SQLITE_CREATE_VIEW:
case SQLITE_CREATE_TABLE: {
if( sqlite3_stricmp(z2,"main")!=0
&& sqlite3_stricmp(z2,"repository")!=0
){
goto ticket_schema_error;
}
if( sqlite3_strnicmp(z0,"ticket",6)!=0
&& sqlite3_strnicmp(z0,"fx_",3)!=0
){
goto ticket_schema_error;
}
break;
}
case SQLITE_DROP_INDEX:
|
| ︙ | ︙ | |||
1211 1212 1213 1214 1215 1216 1217 | } /* ** WEBPAGE: tkttimeline ** URL: /tkttimeline/TICKETUUID ** ** Show the change history for a single ticket in timeline format. | | | 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 |
}
/*
** WEBPAGE: tkttimeline
** URL: /tkttimeline/TICKETUUID
**
** Show the change history for a single ticket in timeline format.
**
** Query parameters:
**
** y=ci Show only check-ins associated with the ticket
*/
void tkttimeline_page(void){
char *zTitle;
const char *zUuid;
|
| ︙ | ︙ |
Changes to src/unicode.c.
| ︙ | ︙ | |||
238 239 240 241 242 243 244 |
iLo = iTest+1;
}else{
iHi = iTest-1;
}
}
assert( key>=aDia[iRes] );
if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
| | > | 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
iLo = iTest+1;
}else{
iHi = iTest-1;
}
}
assert( key>=aDia[iRes] );
if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c :
((int)aChar[iRes] & 0x7F);
}
/*
** Return true if the argument interpreted as a unicode codepoint
** is a diacritical modifier character.
*/
|
| ︙ | ︙ |
Changes to src/update.c.
| ︙ | ︙ | |||
565 566 567 568 569 570 571 |
db_finalize(&q);
db_finalize(&mtimeXfer);
fossil_print("%.79c\n",'-');
if( nUpdate==0 ){
show_common_info(tid, "checkout:", 1, 0);
fossil_print("%-13s None. Already up-to-date\n", "changes:");
}else{
| | | 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 |
db_finalize(&q);
db_finalize(&mtimeXfer);
fossil_print("%.79c\n",'-');
if( nUpdate==0 ){
show_common_info(tid, "checkout:", 1, 0);
fossil_print("%-13s None. Already up-to-date\n", "changes:");
}else{
fossil_print("%-13s %.40s %s\n", "updated-from:", rid_to_uuid(vid),
db_text("", "SELECT datetime(mtime) || ' UTC' FROM event "
" WHERE objid=%d", vid));
show_common_info(tid, "updated-to:", 1, 0);
fossil_print("%-13s %d file%s modified.\n", "changes:",
nUpdate, nUpdate>1 ? "s" : "");
}
|
| ︙ | ︙ |
Changes to src/url.c.
| ︙ | ︙ | |||
87 88 89 90 91 92 93 | ** path Path name for HTTP or HTTPS. ** user Userid. ** passwd Password. ** hostname HOST:PORT or just HOST if port is the default. ** canonical The URL in canonical form, omitting the password ** ** If URL_USECONFIG is set and zUrl is NULL or "default", then parse the | | | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | ** path Path name for HTTP or HTTPS. ** user Userid. ** passwd Password. ** hostname HOST:PORT or just HOST if port is the default. ** canonical The URL in canonical form, omitting the password ** ** If URL_USECONFIG is set and zUrl is NULL or "default", then parse the ** URL stored in last-sync-url and last-sync-pw of the CONFIG table. Or if ** URL_USE_PARENT is also set, then use parent-project-url and ** parent-project-pw from the CONFIG table instead of last-sync-url ** and last-sync-pw. ** ** If URL_USE_CONFIG is set and zUrl is a symbolic name, then look up ** the URL in sync-url:%Q and sync-pw:%Q elements of the CONFIG table where ** %Q is the symbolic name. |
| ︙ | ︙ | |||
315 316 317 318 319 320 321 |
free(zFile);
zFile = 0;
pUrlData->protocol = "file";
pUrlData->path = mprintf("");
pUrlData->name = mprintf("%b", &cfile);
pUrlData->canonical = mprintf("file://%T", pUrlData->name);
blob_reset(&cfile);
| | | 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 |
free(zFile);
zFile = 0;
pUrlData->protocol = "file";
pUrlData->path = mprintf("");
pUrlData->name = mprintf("%b", &cfile);
pUrlData->canonical = mprintf("file://%T", pUrlData->name);
blob_reset(&cfile);
}else if( pUrlData->user!=0 && pUrlData->passwd==0
&& (urlFlags & URL_PROMPT_PW)!=0 ){
url_prompt_for_password_local(pUrlData);
}else if( pUrlData->user!=0 && ( urlFlags & URL_ASK_REMEMBER_PW ) ){
if( isatty(fileno(stdin)) && ( urlFlags & URL_REMEMBER_PW )==0 ){
if( save_password_prompt(pUrlData->passwd) ){
pUrlData->flags = urlFlags |= URL_REMEMBER_PW;
}else{
|
| ︙ | ︙ | |||
789 790 791 792 793 794 795 | ** Given a URL for a remote repository clone point, try to come up with a ** reasonable basename of a local clone of that repository. ** ** * If the URL has a path, use the tail of the path, with any suffix ** elided. ** ** * If the URL is just a domain name, without a path, then use the | | | 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 |
** Given a URL for a remote repository clone point, try to come up with a
** reasonable basename of a local clone of that repository.
**
** * If the URL has a path, use the tail of the path, with any suffix
** elided.
**
** * If the URL is just a domain name, without a path, then use the
** first element of the domain name, except skip over "www." if
** present and if there is a ".com" or ".org" or similar suffix.
**
** The string returned is obtained from fossil_malloc(). NULL might be
** returned if there is an error.
*/
char *url_to_repo_basename(const char *zUrl){
const char *zTail = 0;
|
| ︙ | ︙ |
Changes to src/user.c.
| ︙ | ︙ | |||
397 398 399 400 401 402 403 |
}
if( g.localOpen ){
db_lset("default-user", g.argv[3]);
}else{
db_set("default-user", g.argv[3], 0);
}
}
| | > | 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 |
}
if( g.localOpen ){
db_lset("default-user", g.argv[3]);
}else{
db_set("default-user", g.argv[3], 0);
}
}
}else if(( n>=2 && strncmp(g.argv[2],"list",n)==0 ) ||
( n>=2 && strncmp(g.argv[2],"ls",n)==0 )){
Stmt q;
db_prepare(&q, "SELECT login, info FROM user ORDER BY login");
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%-12s %s\n", db_column_text(&q, 0), db_column_text(&q, 1));
}
db_finalize(&q);
}else if( n>=2 && strncmp(g.argv[2],"password",2)==0 ){
|
| ︙ | ︙ |
Changes to src/vfile.c.
| ︙ | ︙ | |||
408 409 410 411 412 413 414 |
"original",
"output",
};
int i, j, n;
if( sqlite3_strglob("ci-comment-????????????.txt", zName)==0 ) return 1;
for(; zName[0]!=0; zName++){
| > | | 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 |
"original",
"output",
};
int i, j, n;
if( sqlite3_strglob("ci-comment-????????????.txt", zName)==0 ) return 1;
for(; zName[0]!=0; zName++){
if( zName[0]=='/'
&& sqlite3_strglob("/ci-comment-????????????.txt", zName)==0 ){
return 1;
}
if( zName[0]!='-' ) continue;
for(i=0; i<count(azTemp); i++){
n = (int)strlen(azTemp[i]);
if( memcmp(azTemp[i], zName+1, n) ) continue;
if( zName[n+1]==0 ) return 1;
|
| ︙ | ︙ | |||
752 753 754 755 756 757 758 |
md5sum_step_text(" 0\n", -1);
continue;
}
fseek(in, 0L, SEEK_END);
sqlite3_snprintf(sizeof(zBuf), zBuf, " %ld\n", ftell(in));
fseek(in, 0L, SEEK_SET);
md5sum_step_text(zBuf, -1);
| | | 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 |
md5sum_step_text(" 0\n", -1);
continue;
}
fseek(in, 0L, SEEK_END);
sqlite3_snprintf(sizeof(zBuf), zBuf, " %ld\n", ftell(in));
fseek(in, 0L, SEEK_SET);
md5sum_step_text(zBuf, -1);
/*printf("%s %s %s",md5sum_current_state(),zName,zBuf);fflush(stdout);*/
for(;;){
int n;
n = fread(zBuf, 1, sizeof(zBuf), in);
if( n<=0 ) break;
md5sum_step_text(zBuf, n);
}
fclose(in);
|
| ︙ | ︙ | |||
1039 1040 1041 1042 1043 1044 1045 |
/* Add RID values for merged-in files */
db_multi_exec(
"INSERT OR IGNORE INTO idMap(oldrid, newrid)"
" SELECT vfile.mrid, blob.rid FROM vfile, blob"
" WHERE blob.uuid=vfile.mhash;"
);
| | | | 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 |
/* Add RID values for merged-in files */
db_multi_exec(
"INSERT OR IGNORE INTO idMap(oldrid, newrid)"
" SELECT vfile.mrid, blob.rid FROM vfile, blob"
" WHERE blob.uuid=vfile.mhash;"
);
if( dryRun ){
Stmt q;
db_prepare(&q, "SELECT oldrid, newrid, blob.uuid"
" FROM idMap, blob WHERE blob.rid=idMap.newrid");
while( db_step(&q)==SQLITE_ROW ){
fossil_print("%8d -> %8d %.25s\n",
db_column_int(&q,0),
db_column_int(&q,1),
db_column_text(&q,2));
}
db_finalize(&q);
}
|
| ︙ | ︙ |
Changes to src/wiki.c.
| ︙ | ︙ | |||
83 84 85 86 87 88 89 |
}
int wiki_tagid2(const char *zPrefix, const char *zPageName){
return db_int(0, "SELECT tagid FROM tag WHERE tagname='wiki-%q/%q'",
zPrefix, zPageName);
}
/*
| | | 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
}
int wiki_tagid2(const char *zPrefix, const char *zPageName){
return db_int(0, "SELECT tagid FROM tag WHERE tagname='wiki-%q/%q'",
zPrefix, zPageName);
}
/*
** Return the RID of the next or previous version of a wiki page.
** Return 0 if rid is the last/first version.
*/
int wiki_next(int tagid, double mtime){
return db_int(0,
"SELECT srcid FROM tagxref"
" WHERE tagid=%d AND mtime>%.16g"
" ORDER BY mtime ASC LIMIT 1",
|
| ︙ | ︙ | |||
411 412 413 414 415 416 417 |
/*
** Figure out what type of wiki page we are dealing with.
*/
int wiki_page_type(const char *zPageName){
if( db_get_boolean("wiki-about",1)==0 ){
return WIKITYPE_NORMAL;
}else
| | | 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 |
/*
** Figure out what type of wiki page we are dealing with.
*/
int wiki_page_type(const char *zPageName){
if( db_get_boolean("wiki-about",1)==0 ){
return WIKITYPE_NORMAL;
}else
if( sqlite3_strglob("checkin/*", zPageName)==0
&& db_exists("SELECT 1 FROM blob WHERE uuid=%Q",zPageName+8)
){
return WIKITYPE_CHECKIN;
}else
if( sqlite3_strglob("branch/*", zPageName)==0 ){
return WIKITYPE_BRANCH;
}else
|
| ︙ | ︙ | |||
445 446 447 448 449 450 451 | /* ** Add an appropriate style_header() for either the /wiki or /wikiedit page ** for zPageName. zExtra is an empty string for /wiki but has the text ** "Edit: " for /wikiedit. ** ** If the page is /wiki and the page is one of the special times (check-in, | | | 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 | /* ** Add an appropriate style_header() for either the /wiki or /wikiedit page ** for zPageName. zExtra is an empty string for /wiki but has the text ** "Edit: " for /wikiedit. ** ** If the page is /wiki and the page is one of the special times (check-in, ** branch, or tag) and the "p" query parameter is omitted, then do a ** redirect to the display of the check-in, branch, or tag rather than ** continuing to the plain wiki display. */ static int wiki_page_header( int eType, /* Page type. Might be WIKITYPE_UNKNOWN */ const char *zPageName, /* Name of the page */ const char *zExtra /* Extra prefix text on the page header */ |
| ︙ | ︙ | |||
467 468 469 470 471 472 473 |
}
case WIKITYPE_CHECKIN: {
zPageName += 8;
if( zExtra[0]==0 && !P("p") ){
cgi_redirectf("%R/info/%s",zPageName);
}else{
style_header("Notes About Check-in %S", zPageName);
| | > | 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 |
}
case WIKITYPE_CHECKIN: {
zPageName += 8;
if( zExtra[0]==0 && !P("p") ){
cgi_redirectf("%R/info/%s",zPageName);
}else{
style_header("Notes About Check-in %S", zPageName);
style_submenu_element("Check-in Timeline","%R/timeline?f=%s",
zPageName);
style_submenu_element("Check-in Info","%R/info/%s", zPageName);
}
break;
}
case WIKITYPE_BRANCH: {
zPageName += 7;
if( zExtra[0]==0 && !P("p") ){
|
| ︙ | ︙ | |||
741 742 743 744 745 746 747 |
** Note that the sandbox is a special case: it is a pseudo-page with
** no rid and the /wikiajax API does not allow anyone to actually save
** a sandbox page, but it is reported as writable here (with rid 0).
*/
static int wiki_ajax_can_write(const char *zPageName, int * pRid){
int rid = 0;
const char * zErr = 0;
| | | 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 |
** Note that the sandbox is a special case: it is a pseudo-page with
** no rid and the /wikiajax API does not allow anyone to actually save
** a sandbox page, but it is reported as writable here (with rid 0).
*/
static int wiki_ajax_can_write(const char *zPageName, int * pRid){
int rid = 0;
const char * zErr = 0;
if(pRid) *pRid = 0;
if(!zPageName || !*zPageName
|| !wiki_name_is_wellformed((unsigned const char *)zPageName)){
zErr = "Invalid page name.";
}else if(is_sandbox(zPageName)){
return 1;
}else{
|
| ︙ | ︙ | |||
764 765 766 767 768 769 770 |
}else if(!rid && !g.perm.NewWiki){
zErr = "Requires new-wiki permissions.";
}else{
zErr = "Cannot happen! Please report this as a bug.";
}
}
ajax_route_error(403, "%s", zErr);
| | | 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 |
}else if(!rid && !g.perm.NewWiki){
zErr = "Requires new-wiki permissions.";
}else{
zErr = "Cannot happen! Please report this as a bug.";
}
}
ajax_route_error(403, "%s", zErr);
return 0;
}
/*
** Emits an array of attachment info records for the given wiki page
** artifact.
**
|
| ︙ | ︙ | |||
1010 1011 1012 1013 1014 1015 1016 |
**
** Responds with JSON. On error, an object in the form documented by
** ajax_route_error(). On success, an object in the form documented
** for wiki_ajax_emit_page_object().
*/
static void wiki_ajax_route_fetch(void){
const char * zPageName = P("page");
| | | 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 |
**
** Responds with JSON. On error, an object in the form documented by
** ajax_route_error(). On success, an object in the form documented
** for wiki_ajax_emit_page_object().
*/
static void wiki_ajax_route_fetch(void){
const char * zPageName = P("page");
if( zPageName==0 || zPageName[0]==0 ){
ajax_route_error(400,"Missing page name.");
return;
}
cgi_set_content_type("application/json");
wiki_ajax_emit_page_object(zPageName, 1);
}
|
| ︙ | ︙ | |||
1201 1202 1203 1204 1205 1206 1207 | } /* ** WEBPAGE: wikiajax hidden ** ** An internal dispatcher for wiki AJAX operations. Not for direct ** client use. All routes defined by this interface are app-internal, | | | 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 |
}
/*
** WEBPAGE: wikiajax hidden
**
** An internal dispatcher for wiki AJAX operations. Not for direct
** client use. All routes defined by this interface are app-internal,
** subject to change
*/
void wiki_ajax_page(void){
const char * zName = P("name");
AjaxRoute routeName = {0,0,0,0};
const AjaxRoute * pRoute = 0;
const AjaxRoute routes[] = {
/* Keep these sorted by zName (for bsearch()) */
|
| ︙ | ︙ | |||
1341 1342 1343 1344 1345 1346 1347 |
"data-tab-parent='wikiedit-tabs' "
"data-tab-label='Wiki Page List' "
"class='hidden'"
">");
CX("<div>Loading wiki pages list...</div>");
CX("</div>"/*#wikiedit-tab-pages*/);
}
| | | 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 |
"data-tab-parent='wikiedit-tabs' "
"data-tab-label='Wiki Page List' "
"class='hidden'"
">");
CX("<div>Loading wiki pages list...</div>");
CX("</div>"/*#wikiedit-tab-pages*/);
}
/******* Content tab *******/
{
CX("<div id='wikiedit-tab-content' "
"data-tab-parent='wikiedit-tabs' "
"data-tab-label='Editor' "
"class='hidden'"
">");
|
| ︙ | ︙ | |||
1903 1904 1905 1906 1907 1908 1909 | ** wsort Sort names by this label ** wrid rid of the most recent version of the page ** wmtime time most recent version was created ** wcnt Number of versions of this wiki page ** ** The wrid value is zero for deleted wiki pages. */ | | | 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 | ** wsort Sort names by this label ** wrid rid of the most recent version of the page ** wmtime time most recent version was created ** wcnt Number of versions of this wiki page ** ** The wrid value is zero for deleted wiki pages. */ static const char listAllWikiPages[] = @ SELECT @ substr(tag.tagname, 6) AS wname, @ lower(substr(tag.tagname, 6)) AS sortname, @ tagxref.value+0 AS wrid, @ max(tagxref.mtime) AS wmtime, @ count(*) AS wcnt @ FROM |
| ︙ | ︙ | |||
2480 2481 2482 2483 2484 2485 2486 |
}
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
const int wrid = db_column_int(&q, 2);
if(!showAll && !wrid){
continue;
}
| | | 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 |
}
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
const int wrid = db_column_int(&q, 2);
if(!showAll && !wrid){
continue;
}
if( !showCkBr &&
(sqlite3_strglob("checkin/*", zName)==0 ||
sqlite3_strglob("branch/*", zName)==0) ){
continue;
}
if( showIds ){
const char *zUuid = db_column_text(&q, 1);
fossil_print("%s ",zUuid);
|
| ︙ | ︙ |
Changes to src/wikiformat.c.
| ︙ | ︙ | |||
2217 2218 2219 2220 2221 2222 2223 |
iMatchCnt = 1;
}else if( n==1 && zStart[0]=='=' && iMatchCnt==1 ){
iMatchCnt = 2;
}else if( iMatchCnt==2 ){
if( (zStart[0]=='"' || zStart[0]=='\'') && zStart[n-1]==zStart[0] ){
zStart++;
n -= 2;
| | | 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 |
iMatchCnt = 1;
}else if( n==1 && zStart[0]=='=' && iMatchCnt==1 ){
iMatchCnt = 2;
}else if( iMatchCnt==2 ){
if( (zStart[0]=='"' || zStart[0]=='\'') && zStart[n-1]==zStart[0] ){
zStart++;
n -= 2;
}
*pLen = n;
return zStart;
}else{
iMatchCnt = 0;
}
}
return 0;
|
| ︙ | ︙ |
Changes to src/winhttp.c.
| ︙ | ︙ | |||
666 667 668 669 670 671 672 |
fossil_panic("unable to get path to the temporary directory.");
}
/* Use a subdirectory for temp files (can then be excluded from virus scan) */
zTempSubDirPath = mprintf("%s%s\\",fossil_path_to_utf8(zTmpPath),zTempSubDir);
if ( !file_mkdir(zTempSubDirPath, ExtFILE, 0) ||
file_isdir(zTempSubDirPath, ExtFILE)==1 ){
wcscpy(zTmpPath, fossil_utf8_to_path(zTempSubDirPath, 1));
| | | 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 |
fossil_panic("unable to get path to the temporary directory.");
}
/* Use a subdirectory for temp files (can then be excluded from virus scan) */
zTempSubDirPath = mprintf("%s%s\\",fossil_path_to_utf8(zTmpPath),zTempSubDir);
if ( !file_mkdir(zTempSubDirPath, ExtFILE, 0) ||
file_isdir(zTempSubDirPath, ExtFILE)==1 ){
wcscpy(zTmpPath, fossil_utf8_to_path(zTempSubDirPath, 1));
}
if( g.fHttpTrace ){
zTempPrefix = mprintf("httptrace");
}else{
zTempPrefix = mprintf("%sfossil_server_P%d",
fossil_unicode_to_utf8(zTmpPath), iPort);
}
fossil_print("Temporary files: %s*\n", zTempPrefix);
|
| ︙ | ︙ | |||
1370 1371 1372 1373 1374 1375 1376 |
if( !hScm ) winhttp_fatal("start", zSvcName, win32_get_last_errmsg());
hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
SERVICE_ALL_ACCESS);
if( !hSvc ) winhttp_fatal("start", zSvcName, win32_get_last_errmsg());
QueryServiceStatus(hSvc, &sstat);
if( sstat.dwCurrentState!=SERVICE_RUNNING ){
fossil_print("Starting service '%s'", zSvcName);
| | | | | | | | 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 |
if( !hScm ) winhttp_fatal("start", zSvcName, win32_get_last_errmsg());
hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName),
SERVICE_ALL_ACCESS);
if( !hSvc ) winhttp_fatal("start", zSvcName, win32_get_last_errmsg());
QueryServiceStatus(hSvc, &sstat);
if( sstat.dwCurrentState!=SERVICE_RUNNING ){
fossil_print("Starting service '%s'", zSvcName);
if( sstat.dwCurrentState!=SERVICE_START_PENDING ){
if( !StartServiceW(hSvc, 0, NULL) ){
winhttp_fatal("start", zSvcName, win32_get_last_errmsg());
}
QueryServiceStatus(hSvc, &sstat);
}
while( sstat.dwCurrentState==SERVICE_START_PENDING ||
sstat.dwCurrentState==SERVICE_STOPPED ){
Sleep(100);
fossil_print(".");
QueryServiceStatus(hSvc, &sstat);
}
if( sstat.dwCurrentState==SERVICE_RUNNING ){
|
| ︙ | ︙ |
Changes to src/xfer.c.
| ︙ | ︙ | |||
353 354 355 356 357 358 359 |
}
}else{
nullContent = 1;
}
/* The isWriter flag must be true in order to land the new file */
if( !isWriter ){
| | | 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 |
}
}else{
nullContent = 1;
}
/* The isWriter flag must be true in order to land the new file */
if( !isWriter ){
blob_appendf(&pXfer->err,"Write permissions for unversioned files missing");
goto end_accept_unversioned_file;
}
/* Make sure we have a valid g.rcvid marker */
content_rcvid_init(0);
/* Check to see if current content really should be overwritten. Ideally,
|
| ︙ | ︙ | |||
1832 1833 1834 1835 1836 1837 1838 |
const char *zArg = db_column_text(&q, 1);
i64 iMtime = db_column_int64(&q, 2);
memset(&x, 0, sizeof(x));
url_parse_local(zUrl, URL_OMIT_USER, &x);
if( x.name!=0 && sqlite3_strlike("%localhost%", x.name, 0)!=0 ){
@ pragma link %F(x.canonical) %F(zArg) %lld(iMtime)
}
| | | 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 |
const char *zArg = db_column_text(&q, 1);
i64 iMtime = db_column_int64(&q, 2);
memset(&x, 0, sizeof(x));
url_parse_local(zUrl, URL_OMIT_USER, &x);
if( x.name!=0 && sqlite3_strlike("%localhost%", x.name, 0)!=0 ){
@ pragma link %F(x.canonical) %F(zArg) %lld(iMtime)
}
url_unparse(&x);
}
db_finalize(&q);
}
/* Send the server timestamp last, in case prior processing happened
** to use up a significant fraction of our time window.
*/
|
| ︙ | ︙ | |||
1857 1858 1859 1860 1861 1862 1863 | ** ** Usage: %fossil test-xfer ?OPTIONS? XFERFILE ** ** Pass the sync-protocol input file XFERFILE into the server-side sync ** protocol handler. Generate a reply on standard output. ** ** This command was original created to help debug the server side of | | | 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 | ** ** Usage: %fossil test-xfer ?OPTIONS? XFERFILE ** ** Pass the sync-protocol input file XFERFILE into the server-side sync ** protocol handler. Generate a reply on standard output. ** ** This command was original created to help debug the server side of ** sync messages. The XFERFILE is the uncompressed content of an ** "xfer" HTTP request from client to server. This command interprets ** that message and generates the content of an HTTP reply (without any ** encoding and without the HTTP reply headers) and writes that reply ** on standard output. ** ** One possible usages scenario is to capture some XFERFILE examples ** using a command like: |
| ︙ | ︙ | |||
2526 2527 2528 2529 2530 2531 2532 |
if( iStatus>=4 && uvPullOnly==1 ){
fossil_warning(
"Warning: uv-pull-only \n"
" Unable to push unversioned content because you lack\n"
" sufficient permission on the server\n"
);
uvPullOnly = 2;
| | | 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 |
if( iStatus>=4 && uvPullOnly==1 ){
fossil_warning(
"Warning: uv-pull-only \n"
" Unable to push unversioned content because you lack\n"
" sufficient permission on the server\n"
);
uvPullOnly = 2;
}
if( iStatus<=3 || uvPullOnly ){
db_multi_exec("DELETE FROM uv_tosend WHERE name=%Q", zName);
}else if( iStatus==4 ){
db_multi_exec("UPDATE uv_tosend SET mtimeOnly=1 WHERE name=%Q",zName);
}else if( iStatus==5 ){
db_multi_exec("REPLACE INTO uv_tosend(name,mtimeOnly) VALUES(%Q,0)",
zName);
|
| ︙ | ︙ |
Changes to src/zip.c.
| ︙ | ︙ | |||
136 137 138 139 140 141 142 |
return 512;
}
static int archiveDeviceCharacteristics(sqlite3_file *pFile){
return 0;
}
static int archiveOpen(
| | | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
return 512;
}
static int archiveDeviceCharacteristics(sqlite3_file *pFile){
return 0;
}
static int archiveOpen(
sqlite3_vfs *pVfs, const char *zName,
sqlite3_file *pFile, int flags, int *pOutFlags
){
static struct sqlite3_io_methods methods = {
1, /* iVersion */
archiveClose,
archiveRead,
archiveWrite,
|
| ︙ | ︙ | |||
245 246 247 248 249 250 251 | ** Append a single file to a growing ZIP archive. ** ** pFile is the file to be appended. zName is the name ** that the file should be saved as. */ static void zip_add_file_to_zip( Archive *p, | | | | 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
** Append a single file to a growing ZIP archive.
**
** pFile is the file to be appended. zName is the name
** that the file should be saved as.
*/
static void zip_add_file_to_zip(
Archive *p,
const char *zName,
const Blob *pFile,
int mPerm
){
z_stream stream;
int nameLen;
int toOut = 0;
int iStart;
unsigned long iCRC = 0;
|
| ︙ | ︙ | |||
372 373 374 375 376 377 378 | put16(&zExTime[2], 5); blob_append(&toc, zExTime, 9); nEntry++; } static void zip_add_file_to_sqlar( Archive *p, | | | | | | | | 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 |
put16(&zExTime[2], 5);
blob_append(&toc, zExTime, 9);
nEntry++;
}
static void zip_add_file_to_sqlar(
Archive *p,
const char *zName,
const Blob *pFile,
int mPerm
){
int nName = (int)strlen(zName);
if( p->db==0 ){
assert( p->vfs.zName==0 );
p->vfs.zName = (const char*)mprintf("archivevfs%p", (void*)p);
p->vfs.iVersion = 1;
p->vfs.szOsFile = sizeof(ArchiveFile);
p->vfs.mxPathname = 512;
p->vfs.pAppData = (void*)p->pBlob;
p->vfs.xOpen = archiveOpen;
p->vfs.xDelete = archiveDelete;
p->vfs.xAccess = archiveAccess;
p->vfs.xFullPathname = archiveFullPathname;
p->vfs.xRandomness = archiveRandomness;
p->vfs.xSleep = archiveSleep;
p->vfs.xCurrentTime = archiveCurrentTime;
p->vfs.xGetLastError = archiveGetLastError;
sqlite3_vfs_register(&p->vfs, 0);
sqlite3_open_v2("file:xyz.db", &p->db,
SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE, p->vfs.zName
);
assert( p->db );
blob_zero(&p->tmp);
sqlite3_exec(p->db,
"PRAGMA page_size=512;"
"PRAGMA journal_mode = off;"
"PRAGMA cache_spill = off;"
"BEGIN;"
"CREATE TABLE sqlar("
"name TEXT PRIMARY KEY, -- name of the file\n"
"mode INT, -- access permissions\n"
"mtime INT, -- last modification time\n"
"sz INT, -- original file size\n"
"data BLOB -- compressed content\n"
");", 0, 0, 0
);
sqlite3_prepare(p->db,
"INSERT INTO sqlar VALUES(?, ?, ?, ?, ?)", -1,
&p->pInsert, 0
);
assert( p->pInsert );
sqlite3_bind_int64(p->pInsert, 3, unixTime);
blob_zero(p->pBlob);
}
|
| ︙ | ︙ | |||
435 436 437 438 439 440 441 |
sqlite3_bind_int(p->pInsert, 4, 0);
sqlite3_bind_null(p->pInsert, 5);
}else{
sqlite3_bind_text(p->pInsert, 1, zName, nName, SQLITE_STATIC);
if( mPerm==PERM_LNK ){
sqlite3_bind_int(p->pInsert, 2, 0120755);
sqlite3_bind_int(p->pInsert, 4, -1);
| | | | | | | 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 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 |
sqlite3_bind_int(p->pInsert, 4, 0);
sqlite3_bind_null(p->pInsert, 5);
}else{
sqlite3_bind_text(p->pInsert, 1, zName, nName, SQLITE_STATIC);
if( mPerm==PERM_LNK ){
sqlite3_bind_int(p->pInsert, 2, 0120755);
sqlite3_bind_int(p->pInsert, 4, -1);
sqlite3_bind_text(p->pInsert, 5,
blob_buffer(pFile), blob_size(pFile), SQLITE_STATIC
);
}else{
unsigned int nIn = blob_size(pFile);
unsigned long int nOut = nIn;
sqlite3_bind_int(p->pInsert, 2, mPerm==PERM_EXE ? 0100755 : 0100644);
sqlite3_bind_int(p->pInsert, 4, nIn);
zip_blob_minsize(&p->tmp, nIn);
compress( (unsigned char*)
blob_buffer(&p->tmp), &nOut, (unsigned char*)blob_buffer(pFile), nIn
);
if( nOut>=(unsigned long)nIn ){
sqlite3_bind_blob(p->pInsert, 5,
blob_buffer(pFile), blob_size(pFile), SQLITE_STATIC
);
}else{
sqlite3_bind_blob(p->pInsert, 5,
blob_buffer(&p->tmp), nOut, SQLITE_STATIC
);
}
}
}
sqlite3_step(p->pInsert);
sqlite3_reset(p->pInsert);
}
static void zip_add_file(
Archive *p,
const char *zName,
const Blob *pFile,
int mPerm
){
if( p->eType==ARCHIVE_ZIP ){
zip_add_file_to_zip(p, zName, pFile, mPerm);
}else{
zip_add_file_to_sqlar(p, zName, pFile, mPerm);
}
|
| ︙ | ︙ | |||
784 785 786 787 788 789 790 |
" || substr(blob.uuid, 1, 10)"
" FROM event, blob"
" WHERE event.objid=%d"
" AND blob.rid=%d",
db_get("project-name", "unnamed"), rid, rid
);
}
| | | 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 |
" || substr(blob.uuid, 1, 10)"
" FROM event, blob"
" WHERE event.objid=%d"
" AND blob.rid=%d",
db_get("project-name", "unnamed"), rid, rid
);
}
zip_of_checkin(eType, rid, zOut ? &zip : 0,
zName, pInclude, pExclude, listFlag);
glob_free(pInclude);
glob_free(pExclude);
if( zOut ){
blob_write_to_file(&zip, zOut);
blob_reset(&zip);
}
|
| ︙ | ︙ | |||
945 946 947 948 949 950 951 |
zInclude = P("in");
if( zInclude ) pInclude = glob_create(zInclude);
zExclude = P("ex");
if( zExclude ) pExclude = glob_create(zExclude);
if( zInclude==0 && zExclude==0 ){
etag_check_for_invariant_name(z);
}
| | | | 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 |
zInclude = P("in");
if( zInclude ) pInclude = glob_create(zInclude);
zExclude = P("ex");
if( zExclude ) pExclude = glob_create(zExclude);
if( zInclude==0 && zExclude==0 ){
etag_check_for_invariant_name(z);
}
if( eType==ARCHIVE_ZIP
&& nName>4
&& fossil_strcmp(&zName[nName-4], ".zip")==0
){
/* Special case: Remove the ".zip" suffix. */
nName -= 4;
zName[nName] = 0;
}else if( eType==ARCHIVE_SQLAR
&& nName>6
&& fossil_strcmp(&zName[nName-6], ".sqlar")==0
){
/* Special case: Remove the ".sqlar" suffix. */
nName -= 6;
zName[nName] = 0;
}else{
|
| ︙ | ︙ |
Changes to tools/codecheck1.c.
| ︙ | ︙ | |||
602 603 604 605 606 607 608 |
if( (acType[i]=='s' || acType[i]=='z' || acType[i]=='b') ){
const char *zExpr = azArg[fmtArg+i];
if( never_safe(zExpr) ){
printf("%s:%d: Argument %d to %.*s() is not safe for"
" a query parameter\n",
zFilename, lnFCall, i+fmtArg, szFName, zFCall);
nErr++;
| | | 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 |
if( (acType[i]=='s' || acType[i]=='z' || acType[i]=='b') ){
const char *zExpr = azArg[fmtArg+i];
if( never_safe(zExpr) ){
printf("%s:%d: Argument %d to %.*s() is not safe for"
" a query parameter\n",
zFilename, lnFCall, i+fmtArg, szFName, zFCall);
nErr++;
}else if( (fmtFlags & FMT_SQL)!=0 && !is_sql_safe(zExpr) ){
printf("%s:%d: Argument %d to %.*s() not safe for SQL\n",
zFilename, lnFCall, i+fmtArg, szFName, zFCall);
nErr++;
}
}
}
|
| ︙ | ︙ |
Changes to tools/makeheaders.c.
| ︙ | ︙ | |||
36 37 38 39 40 41 42 | #include <stdlib.h> #include <ctype.h> #include <memory.h> #include <sys/stat.h> #include <assert.h> #include <string.h> | | > | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
#include <stdlib.h>
#include <ctype.h>
#include <memory.h>
#include <sys/stat.h>
#include <assert.h>
#include <string.h>
#if defined( __MINGW32__) || defined(__DMC__) || \
defined(_MSC_VER) || defined(__POCC__)
# ifndef WIN32
# define WIN32
# endif
#else
# include <unistd.h>
#endif
|
| ︙ | ︙ | |||
2224 2225 2226 2227 2228 2229 2230 |
if (pToken->zText[pToken->nText-1] == '\r') { nArg--; }
if( nArg==9 && strncmp(zArg,"INTERFACE",9)==0 ){
PushIfMacro(0,0,0,pToken->nLine,PS_Interface);
}else if( nArg==16 && strncmp(zArg,"EXPORT_INTERFACE",16)==0 ){
PushIfMacro(0,0,0,pToken->nLine,PS_Export);
}else if( nArg==15 && strncmp(zArg,"LOCAL_INTERFACE",15)==0 ){
PushIfMacro(0,0,0,pToken->nLine,PS_Local);
| > | | 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 |
if (pToken->zText[pToken->nText-1] == '\r') { nArg--; }
if( nArg==9 && strncmp(zArg,"INTERFACE",9)==0 ){
PushIfMacro(0,0,0,pToken->nLine,PS_Interface);
}else if( nArg==16 && strncmp(zArg,"EXPORT_INTERFACE",16)==0 ){
PushIfMacro(0,0,0,pToken->nLine,PS_Export);
}else if( nArg==15 && strncmp(zArg,"LOCAL_INTERFACE",15)==0 ){
PushIfMacro(0,0,0,pToken->nLine,PS_Local);
}else if( nArg==15 &&
strncmp(zArg,"MAKEHEADERS_STOPLOCAL_INTERFACE",15)==0 ){
PushIfMacro(0,0,0,pToken->nLine,PS_Local);
}else{
PushIfMacro(0,zArg,nArg,pToken->nLine,0);
}
}else if( nCmd==5 && strncmp(zCmd,"ifdef",5)==0 ){
/*
** Push an #ifdef.
|
| ︙ | ︙ |
Changes to tools/mkindex.c.
| ︙ | ︙ | |||
36 37 38 39 40 41 42 | ** legacy commands. Test commands are unsupported commands used for testing ** and analysis only. ** ** Commands are 1st-tier by default. If the command name begins with ** "test-" or if the command name has a "test" argument, then it becomes ** a test command. If the command name has a "2nd-tier" argument or ends ** with a "*" character, it is second tier. If the command name has an "alias" | | | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | ** legacy commands. Test commands are unsupported commands used for testing ** and analysis only. ** ** Commands are 1st-tier by default. If the command name begins with ** "test-" or if the command name has a "test" argument, then it becomes ** a test command. If the command name has a "2nd-tier" argument or ends ** with a "*" character, it is second tier. If the command name has an "alias" ** argument or ends with a "#" character, it is an alias: another name ** (a one-to-one replacement) for a command. Examples: ** ** COMMAND: abcde* ** COMMAND: fghij 2nd-tier ** COMMAND: mnopq# ** COMMAND: rstuv alias ** COMMAND: test-xyzzy |
| ︙ | ︙ |
Changes to tools/skintxt2config.c.
|
| | | 1 2 3 4 5 6 7 8 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 et sw=2 tw=80: */ /* ** Copyright (c) 2021 Stephan Beal (https://wanderinghorse.net/home/stephan/) ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the Simplified BSD License (also ** known as the "2-Clause License" or "FreeBSD License".) |
| ︙ | ︙ | |||
100 101 102 103 104 105 106 |
end:
fclose(f);
if(rc){
free(zMem);
}else{
*zContent = zMem;
*nContent = fpos;
| | | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
end:
fclose(f);
if(rc){
free(zMem);
}else{
*zContent = zMem;
*nContent = fpos;
}
return rc;
}
/*
** Expects zFilename to be one of the conventional skin filename
** parts. This routine converts it to config format and emits it to
** App.ostr.
|
| ︙ | ︙ |
Changes to tools/sqlcompattest.c.
| ︙ | ︙ | |||
51 52 53 54 55 56 57 | #error "Must set -DMINIMUM_SQLITE_VERSION=nn.nn.nn in auto.def" #endif #define QUOTE(VAL) #VAL #define STR(MACRO_VAL) QUOTE(MACRO_VAL) char zMinimumVersionNumber[8]="nn.nn.nn"; | | > | > | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
#error "Must set -DMINIMUM_SQLITE_VERSION=nn.nn.nn in auto.def"
#endif
#define QUOTE(VAL) #VAL
#define STR(MACRO_VAL) QUOTE(MACRO_VAL)
char zMinimumVersionNumber[8]="nn.nn.nn";
strncpy((char *)&zMinimumVersionNumber,STR(MINIMUM_SQLITE_VERSION),
sizeof(zMinimumVersionNumber));
long major, minor, release, version;
sscanf(zMinimumVersionNumber, "%li.%li.%li", &major, &minor, &release);
version=(major*1000000)+(minor*1000)+release;
int i;
static const char *zRequiredOpts[] = {
"ENABLE_FTS4", /* Required for repository search */
"ENABLE_DBSTAT_VTAB", /* Required by /repo-tabsize page */
};
/* Check minimum SQLite version number */
if( sqlite3_libversion_number()<version ){
printf("found system SQLite version %s but need %s or later, "
"consider removing --disable-internal-sqlite\n",
sqlite3_libversion(),STR(MINIMUM_SQLITE_VERSION));
return 1;
}
for(i=0; i<sizeof(zRequiredOpts)/sizeof(zRequiredOpts[0]); i++){
if( !sqlite3_compileoption_used(zRequiredOpts[i]) ){
printf("system SQLite library omits required build option -DSQLITE_%s\n",
|
| ︙ | ︙ |