Fossil SCM
merge trunk "filename contains illegal characters" is now a warning
Commit
d3bee356ba27b957c9ee8751eb462ed63ab26444
Parent
6e9c044e3b726ec…
13 files changed
+2
-1
+2
-1
-1
+1
+35
-10
+1
-1
+1
-1
+1
-1
+1
+2
+23
-10
+2
-16
+10
-2
+2
-1
| --- src/add.c | ||
| +++ src/add.c | ||
| @@ -138,11 +138,12 @@ | ||
| 138 | 138 | int vid, /* Add to this VFILE */ |
| 139 | 139 | int caseSensitive /* True if filenames are case sensitive */ |
| 140 | 140 | ){ |
| 141 | 141 | const char *zCollate = caseSensitive ? "binary" : "nocase"; |
| 142 | 142 | if( !file_is_simple_pathname(zPath) ){ |
| 143 | - fossil_fatal("filename contains illegal characters: %s", zPath); | |
| 143 | + fossil_warning("filename contains illegal characters: %s", zPath); | |
| 144 | + return 0; | |
| 144 | 145 | } |
| 145 | 146 | if( db_exists("SELECT 1 FROM vfile" |
| 146 | 147 | " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){ |
| 147 | 148 | db_multi_exec("UPDATE vfile SET deleted=0" |
| 148 | 149 | " WHERE pathname=%Q COLLATE %s", zPath, zCollate); |
| 149 | 150 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -138,11 +138,12 @@ | |
| 138 | int vid, /* Add to this VFILE */ |
| 139 | int caseSensitive /* True if filenames are case sensitive */ |
| 140 | ){ |
| 141 | const char *zCollate = caseSensitive ? "binary" : "nocase"; |
| 142 | if( !file_is_simple_pathname(zPath) ){ |
| 143 | fossil_fatal("filename contains illegal characters: %s", zPath); |
| 144 | } |
| 145 | if( db_exists("SELECT 1 FROM vfile" |
| 146 | " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){ |
| 147 | db_multi_exec("UPDATE vfile SET deleted=0" |
| 148 | " WHERE pathname=%Q COLLATE %s", zPath, zCollate); |
| 149 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -138,11 +138,12 @@ | |
| 138 | int vid, /* Add to this VFILE */ |
| 139 | int caseSensitive /* True if filenames are case sensitive */ |
| 140 | ){ |
| 141 | const char *zCollate = caseSensitive ? "binary" : "nocase"; |
| 142 | if( !file_is_simple_pathname(zPath) ){ |
| 143 | fossil_warning("filename contains illegal characters: %s", zPath); |
| 144 | return 0; |
| 145 | } |
| 146 | if( db_exists("SELECT 1 FROM vfile" |
| 147 | " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){ |
| 148 | db_multi_exec("UPDATE vfile SET deleted=0" |
| 149 | " WHERE pathname=%Q COLLATE %s", zPath, zCollate); |
| 150 |
+2
-1
| --- src/add.c | ||
| +++ src/add.c | ||
| @@ -138,11 +138,12 @@ | ||
| 138 | 138 | int vid, /* Add to this VFILE */ |
| 139 | 139 | int caseSensitive /* True if filenames are case sensitive */ |
| 140 | 140 | ){ |
| 141 | 141 | const char *zCollate = caseSensitive ? "binary" : "nocase"; |
| 142 | 142 | if( !file_is_simple_pathname(zPath) ){ |
| 143 | - fossil_fatal("filename contains illegal characters: %s", zPath); | |
| 143 | + fossil_warning("filename contains illegal characters: %s", zPath); | |
| 144 | + return 0; | |
| 144 | 145 | } |
| 145 | 146 | if( db_exists("SELECT 1 FROM vfile" |
| 146 | 147 | " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){ |
| 147 | 148 | db_multi_exec("UPDATE vfile SET deleted=0" |
| 148 | 149 | " WHERE pathname=%Q COLLATE %s", zPath, zCollate); |
| 149 | 150 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -138,11 +138,12 @@ | |
| 138 | int vid, /* Add to this VFILE */ |
| 139 | int caseSensitive /* True if filenames are case sensitive */ |
| 140 | ){ |
| 141 | const char *zCollate = caseSensitive ? "binary" : "nocase"; |
| 142 | if( !file_is_simple_pathname(zPath) ){ |
| 143 | fossil_fatal("filename contains illegal characters: %s", zPath); |
| 144 | } |
| 145 | if( db_exists("SELECT 1 FROM vfile" |
| 146 | " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){ |
| 147 | db_multi_exec("UPDATE vfile SET deleted=0" |
| 148 | " WHERE pathname=%Q COLLATE %s", zPath, zCollate); |
| 149 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -138,11 +138,12 @@ | |
| 138 | int vid, /* Add to this VFILE */ |
| 139 | int caseSensitive /* True if filenames are case sensitive */ |
| 140 | ){ |
| 141 | const char *zCollate = caseSensitive ? "binary" : "nocase"; |
| 142 | if( !file_is_simple_pathname(zPath) ){ |
| 143 | fossil_warning("filename contains illegal characters: %s", zPath); |
| 144 | return 0; |
| 145 | } |
| 146 | if( db_exists("SELECT 1 FROM vfile" |
| 147 | " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){ |
| 148 | db_multi_exec("UPDATE vfile SET deleted=0" |
| 149 | " WHERE pathname=%Q COLLATE %s", zPath, zCollate); |
| 150 |
-1
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -581,11 +581,10 @@ | ||
| 581 | 581 | blob_init(&prompt, zInit, -1); |
| 582 | 582 | #endif |
| 583 | 583 | blob_append(&prompt, |
| 584 | 584 | "\n" |
| 585 | 585 | "# Enter comments on this check-in. Lines beginning with # are ignored.\n" |
| 586 | - "# The check-in comment follows wiki formatting rules.\n" | |
| 587 | 586 | "#\n", -1 |
| 588 | 587 | ); |
| 589 | 588 | blob_appendf(&prompt, "# user: %s\n", zUserOvrd ? zUserOvrd : g.zLogin); |
| 590 | 589 | if( zBranch && zBranch[0] ){ |
| 591 | 590 | blob_appendf(&prompt, "# tags: %s\n#\n", zBranch); |
| 592 | 591 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -581,11 +581,10 @@ | |
| 581 | blob_init(&prompt, zInit, -1); |
| 582 | #endif |
| 583 | blob_append(&prompt, |
| 584 | "\n" |
| 585 | "# Enter comments on this check-in. Lines beginning with # are ignored.\n" |
| 586 | "# The check-in comment follows wiki formatting rules.\n" |
| 587 | "#\n", -1 |
| 588 | ); |
| 589 | blob_appendf(&prompt, "# user: %s\n", zUserOvrd ? zUserOvrd : g.zLogin); |
| 590 | if( zBranch && zBranch[0] ){ |
| 591 | blob_appendf(&prompt, "# tags: %s\n#\n", zBranch); |
| 592 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -581,11 +581,10 @@ | |
| 581 | blob_init(&prompt, zInit, -1); |
| 582 | #endif |
| 583 | blob_append(&prompt, |
| 584 | "\n" |
| 585 | "# Enter comments on this check-in. Lines beginning with # are ignored.\n" |
| 586 | "#\n", -1 |
| 587 | ); |
| 588 | blob_appendf(&prompt, "# user: %s\n", zUserOvrd ? zUserOvrd : g.zLogin); |
| 589 | if( zBranch && zBranch[0] ){ |
| 590 | blob_appendf(&prompt, "# tags: %s\n#\n", zBranch); |
| 591 |
+1
| --- src/configure.c | ||
| +++ src/configure.c | ||
| @@ -86,10 +86,11 @@ | ||
| 86 | 86 | { "background-mimetype", CONFIGSET_SKIN }, |
| 87 | 87 | { "background-image", CONFIGSET_SKIN }, |
| 88 | 88 | { "index-page", CONFIGSET_SKIN }, |
| 89 | 89 | { "timeline-block-markup", CONFIGSET_SKIN }, |
| 90 | 90 | { "timeline-max-comment", CONFIGSET_SKIN }, |
| 91 | + { "timeline-plaintext", CONFIGSET_SKIN }, | |
| 91 | 92 | { "adunit", CONFIGSET_SKIN }, |
| 92 | 93 | { "adunit-omit-if-admin", CONFIGSET_SKIN }, |
| 93 | 94 | { "adunit-omit-if-user", CONFIGSET_SKIN }, |
| 94 | 95 | { "th1-setup", CONFIGSET_ALL }, |
| 95 | 96 | |
| 96 | 97 |
| --- src/configure.c | |
| +++ src/configure.c | |
| @@ -86,10 +86,11 @@ | |
| 86 | { "background-mimetype", CONFIGSET_SKIN }, |
| 87 | { "background-image", CONFIGSET_SKIN }, |
| 88 | { "index-page", CONFIGSET_SKIN }, |
| 89 | { "timeline-block-markup", CONFIGSET_SKIN }, |
| 90 | { "timeline-max-comment", CONFIGSET_SKIN }, |
| 91 | { "adunit", CONFIGSET_SKIN }, |
| 92 | { "adunit-omit-if-admin", CONFIGSET_SKIN }, |
| 93 | { "adunit-omit-if-user", CONFIGSET_SKIN }, |
| 94 | { "th1-setup", CONFIGSET_ALL }, |
| 95 | |
| 96 |
| --- src/configure.c | |
| +++ src/configure.c | |
| @@ -86,10 +86,11 @@ | |
| 86 | { "background-mimetype", CONFIGSET_SKIN }, |
| 87 | { "background-image", CONFIGSET_SKIN }, |
| 88 | { "index-page", CONFIGSET_SKIN }, |
| 89 | { "timeline-block-markup", CONFIGSET_SKIN }, |
| 90 | { "timeline-max-comment", CONFIGSET_SKIN }, |
| 91 | { "timeline-plaintext", CONFIGSET_SKIN }, |
| 92 | { "adunit", CONFIGSET_SKIN }, |
| 93 | { "adunit-omit-if-admin", CONFIGSET_SKIN }, |
| 94 | { "adunit-omit-if-user", CONFIGSET_SKIN }, |
| 95 | { "th1-setup", CONFIGSET_ALL }, |
| 96 | |
| 97 |
M
src/db.c
+35
-10
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -740,17 +740,25 @@ | ||
| 740 | 740 | /* |
| 741 | 741 | ** zDbName is the name of a database file. If no other database |
| 742 | 742 | ** file is open, then open this one. If another database file is |
| 743 | 743 | ** already open, then attach zDbName using the name zLabel. |
| 744 | 744 | */ |
| 745 | -void db_open_or_attach(const char *zDbName, const char *zLabel){ | |
| 745 | +void db_open_or_attach( | |
| 746 | + const char *zDbName, | |
| 747 | + const char *zLabel, | |
| 748 | + int *pWasAttached | |
| 749 | +){ | |
| 746 | 750 | if( !g.db ){ |
| 751 | + assert( g.zMainDbType==0 ); | |
| 747 | 752 | g.db = openDatabase(zDbName); |
| 748 | 753 | g.zMainDbType = zLabel; |
| 749 | 754 | db_connection_init(); |
| 755 | + if ( pWasAttached ) *pWasAttached = 0; | |
| 750 | 756 | }else{ |
| 757 | + assert( g.zMainDbType!=0 ); | |
| 751 | 758 | db_attach(zDbName, zLabel); |
| 759 | + if ( pWasAttached ) *pWasAttached = 1; | |
| 752 | 760 | } |
| 753 | 761 | } |
| 754 | 762 | |
| 755 | 763 | /* |
| 756 | 764 | ** Open the user database in "~/.fossil". Create the database anew if |
| @@ -806,16 +814,18 @@ | ||
| 806 | 814 | zDbName = mprintf("%s/.fossil", zHome); |
| 807 | 815 | #endif |
| 808 | 816 | if( file_size(zDbName)<1024*3 ){ |
| 809 | 817 | db_init_database(zDbName, zConfigSchema, (char*)0); |
| 810 | 818 | } |
| 811 | - g.useAttach = useAttach; | |
| 812 | 819 | if( useAttach ){ |
| 813 | - db_open_or_attach(zDbName, "configdb"); | |
| 820 | + db_open_or_attach(zDbName, "configdb", &g.useAttach); | |
| 814 | 821 | g.dbConfig = 0; |
| 822 | + g.zConfigDbType = 0; | |
| 815 | 823 | }else{ |
| 824 | + g.useAttach = 0; | |
| 816 | 825 | g.dbConfig = openDatabase(zDbName); |
| 826 | + g.zConfigDbType = "configdb"; | |
| 817 | 827 | } |
| 818 | 828 | g.configOpen = 1; |
| 819 | 829 | free(zDbName); |
| 820 | 830 | } |
| 821 | 831 | |
| @@ -850,11 +860,11 @@ | ||
| 850 | 860 | char *zVFileDef; |
| 851 | 861 | |
| 852 | 862 | if( file_access(zDbName, F_OK) ) return 0; |
| 853 | 863 | lsize = file_size(zDbName); |
| 854 | 864 | if( lsize%1024!=0 || lsize<4096 ) return 0; |
| 855 | - db_open_or_attach(zDbName, "localdb"); | |
| 865 | + db_open_or_attach(zDbName, "localdb", 0); | |
| 856 | 866 | zVFileDef = db_text(0, "SELECT sql FROM %s.sqlite_master" |
| 857 | 867 | " WHERE name=='vfile'", db_name("localdb")); |
| 858 | 868 | |
| 859 | 869 | /* If the "isexe" column is missing from the vfile table, then |
| 860 | 870 | ** add it now. This code added on 2010-03-06. After all users have |
| @@ -986,11 +996,11 @@ | ||
| 986 | 996 | g.json.resultCode = FSL_JSON_E_DB_NOT_VALID; |
| 987 | 997 | #endif |
| 988 | 998 | fossil_panic("not a valid repository: %s", zDbName); |
| 989 | 999 | } |
| 990 | 1000 | } |
| 991 | - db_open_or_attach(zDbName, "repository"); | |
| 1001 | + db_open_or_attach(zDbName, "repository", 0); | |
| 992 | 1002 | g.repositoryOpen = 1; |
| 993 | 1003 | g.zRepositoryName = mprintf("%s", zDbName); |
| 994 | 1004 | /* Cache "allow-symlinks" option, because we'll need it on every stat call */ |
| 995 | 1005 | g.allowSymlinks = db_get_boolean("allow-symlinks", 0); |
| 996 | 1006 | } |
| @@ -1109,11 +1119,11 @@ | ||
| 1109 | 1119 | file_canonical_name(g.argv[2], &repo, 0); |
| 1110 | 1120 | zRepo = blob_str(&repo); |
| 1111 | 1121 | if( file_access(zRepo, 0) ){ |
| 1112 | 1122 | fossil_fatal("no such file: %s", zRepo); |
| 1113 | 1123 | } |
| 1114 | - db_open_or_attach(zRepo, "test_repo"); | |
| 1124 | + db_open_or_attach(zRepo, "test_repo", 0); | |
| 1115 | 1125 | db_lset("repository", blob_str(&repo)); |
| 1116 | 1126 | db_close(1); |
| 1117 | 1127 | } |
| 1118 | 1128 | |
| 1119 | 1129 | |
| @@ -1177,13 +1187,15 @@ | ||
| 1177 | 1187 | g.localOpen = 0; |
| 1178 | 1188 | g.configOpen = 0; |
| 1179 | 1189 | sqlite3_wal_checkpoint(g.db, 0); |
| 1180 | 1190 | sqlite3_close(g.db); |
| 1181 | 1191 | g.db = 0; |
| 1192 | + g.zMainDbType = 0; | |
| 1182 | 1193 | if( g.dbConfig ){ |
| 1183 | 1194 | sqlite3_close(g.dbConfig); |
| 1184 | 1195 | g.dbConfig = 0; |
| 1196 | + g.zConfigDbType = 0; | |
| 1185 | 1197 | } |
| 1186 | 1198 | } |
| 1187 | 1199 | |
| 1188 | 1200 | |
| 1189 | 1201 | /* |
| @@ -1630,19 +1642,32 @@ | ||
| 1630 | 1642 | /* |
| 1631 | 1643 | ** Swap the g.db and g.dbConfig connections so that the various db_* routines |
| 1632 | 1644 | ** work on the ~/.fossil database instead of on the repository database. |
| 1633 | 1645 | ** Be sure to swap them back after doing the operation. |
| 1634 | 1646 | ** |
| 1635 | -** If g.useAttach that means the ~/.fossil database was opened with | |
| 1636 | -** the useAttach flag set to 1. In that case no connection swap is required | |
| 1637 | -** so this routine is a no-op. | |
| 1647 | +** If the ~/.fossil database has already been opened as the main database or | |
| 1648 | +** is attached to the main database, no connection swaps are required so this | |
| 1649 | +** routine is a no-op. | |
| 1638 | 1650 | */ |
| 1639 | 1651 | void db_swap_connections(void){ |
| 1640 | - if( !g.useAttach ){ | |
| 1652 | + /* | |
| 1653 | + ** When swapping the main database connection with the config database | |
| 1654 | + ** connection, the config database connection must be open (not simply | |
| 1655 | + ** attached); otherwise, the swap would end up leaving the main database | |
| 1656 | + ** connection invalid, defeating the very purpose of this routine. This | |
| 1657 | + ** same constraint also holds true when restoring the previously swapped | |
| 1658 | + ** database connection; otherwise, it means that no swap was performed | |
| 1659 | + ** because the main database connection was already pointing to the config | |
| 1660 | + ** database. | |
| 1661 | + */ | |
| 1662 | + if( g.dbConfig ){ | |
| 1641 | 1663 | sqlite3 *dbTemp = g.db; |
| 1664 | + const char *zTempDbType = g.zMainDbType; | |
| 1642 | 1665 | g.db = g.dbConfig; |
| 1666 | + g.zMainDbType = g.zConfigDbType; | |
| 1643 | 1667 | g.dbConfig = dbTemp; |
| 1668 | + g.zConfigDbType = zTempDbType; | |
| 1644 | 1669 | } |
| 1645 | 1670 | } |
| 1646 | 1671 | |
| 1647 | 1672 | /* |
| 1648 | 1673 | ** Logic for reading potentially versioned settings from |
| 1649 | 1674 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -740,17 +740,25 @@ | |
| 740 | /* |
| 741 | ** zDbName is the name of a database file. If no other database |
| 742 | ** file is open, then open this one. If another database file is |
| 743 | ** already open, then attach zDbName using the name zLabel. |
| 744 | */ |
| 745 | void db_open_or_attach(const char *zDbName, const char *zLabel){ |
| 746 | if( !g.db ){ |
| 747 | g.db = openDatabase(zDbName); |
| 748 | g.zMainDbType = zLabel; |
| 749 | db_connection_init(); |
| 750 | }else{ |
| 751 | db_attach(zDbName, zLabel); |
| 752 | } |
| 753 | } |
| 754 | |
| 755 | /* |
| 756 | ** Open the user database in "~/.fossil". Create the database anew if |
| @@ -806,16 +814,18 @@ | |
| 806 | zDbName = mprintf("%s/.fossil", zHome); |
| 807 | #endif |
| 808 | if( file_size(zDbName)<1024*3 ){ |
| 809 | db_init_database(zDbName, zConfigSchema, (char*)0); |
| 810 | } |
| 811 | g.useAttach = useAttach; |
| 812 | if( useAttach ){ |
| 813 | db_open_or_attach(zDbName, "configdb"); |
| 814 | g.dbConfig = 0; |
| 815 | }else{ |
| 816 | g.dbConfig = openDatabase(zDbName); |
| 817 | } |
| 818 | g.configOpen = 1; |
| 819 | free(zDbName); |
| 820 | } |
| 821 | |
| @@ -850,11 +860,11 @@ | |
| 850 | char *zVFileDef; |
| 851 | |
| 852 | if( file_access(zDbName, F_OK) ) return 0; |
| 853 | lsize = file_size(zDbName); |
| 854 | if( lsize%1024!=0 || lsize<4096 ) return 0; |
| 855 | db_open_or_attach(zDbName, "localdb"); |
| 856 | zVFileDef = db_text(0, "SELECT sql FROM %s.sqlite_master" |
| 857 | " WHERE name=='vfile'", db_name("localdb")); |
| 858 | |
| 859 | /* If the "isexe" column is missing from the vfile table, then |
| 860 | ** add it now. This code added on 2010-03-06. After all users have |
| @@ -986,11 +996,11 @@ | |
| 986 | g.json.resultCode = FSL_JSON_E_DB_NOT_VALID; |
| 987 | #endif |
| 988 | fossil_panic("not a valid repository: %s", zDbName); |
| 989 | } |
| 990 | } |
| 991 | db_open_or_attach(zDbName, "repository"); |
| 992 | g.repositoryOpen = 1; |
| 993 | g.zRepositoryName = mprintf("%s", zDbName); |
| 994 | /* Cache "allow-symlinks" option, because we'll need it on every stat call */ |
| 995 | g.allowSymlinks = db_get_boolean("allow-symlinks", 0); |
| 996 | } |
| @@ -1109,11 +1119,11 @@ | |
| 1109 | file_canonical_name(g.argv[2], &repo, 0); |
| 1110 | zRepo = blob_str(&repo); |
| 1111 | if( file_access(zRepo, 0) ){ |
| 1112 | fossil_fatal("no such file: %s", zRepo); |
| 1113 | } |
| 1114 | db_open_or_attach(zRepo, "test_repo"); |
| 1115 | db_lset("repository", blob_str(&repo)); |
| 1116 | db_close(1); |
| 1117 | } |
| 1118 | |
| 1119 | |
| @@ -1177,13 +1187,15 @@ | |
| 1177 | g.localOpen = 0; |
| 1178 | g.configOpen = 0; |
| 1179 | sqlite3_wal_checkpoint(g.db, 0); |
| 1180 | sqlite3_close(g.db); |
| 1181 | g.db = 0; |
| 1182 | if( g.dbConfig ){ |
| 1183 | sqlite3_close(g.dbConfig); |
| 1184 | g.dbConfig = 0; |
| 1185 | } |
| 1186 | } |
| 1187 | |
| 1188 | |
| 1189 | /* |
| @@ -1630,19 +1642,32 @@ | |
| 1630 | /* |
| 1631 | ** Swap the g.db and g.dbConfig connections so that the various db_* routines |
| 1632 | ** work on the ~/.fossil database instead of on the repository database. |
| 1633 | ** Be sure to swap them back after doing the operation. |
| 1634 | ** |
| 1635 | ** If g.useAttach that means the ~/.fossil database was opened with |
| 1636 | ** the useAttach flag set to 1. In that case no connection swap is required |
| 1637 | ** so this routine is a no-op. |
| 1638 | */ |
| 1639 | void db_swap_connections(void){ |
| 1640 | if( !g.useAttach ){ |
| 1641 | sqlite3 *dbTemp = g.db; |
| 1642 | g.db = g.dbConfig; |
| 1643 | g.dbConfig = dbTemp; |
| 1644 | } |
| 1645 | } |
| 1646 | |
| 1647 | /* |
| 1648 | ** Logic for reading potentially versioned settings from |
| 1649 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -740,17 +740,25 @@ | |
| 740 | /* |
| 741 | ** zDbName is the name of a database file. If no other database |
| 742 | ** file is open, then open this one. If another database file is |
| 743 | ** already open, then attach zDbName using the name zLabel. |
| 744 | */ |
| 745 | void db_open_or_attach( |
| 746 | const char *zDbName, |
| 747 | const char *zLabel, |
| 748 | int *pWasAttached |
| 749 | ){ |
| 750 | if( !g.db ){ |
| 751 | assert( g.zMainDbType==0 ); |
| 752 | g.db = openDatabase(zDbName); |
| 753 | g.zMainDbType = zLabel; |
| 754 | db_connection_init(); |
| 755 | if ( pWasAttached ) *pWasAttached = 0; |
| 756 | }else{ |
| 757 | assert( g.zMainDbType!=0 ); |
| 758 | db_attach(zDbName, zLabel); |
| 759 | if ( pWasAttached ) *pWasAttached = 1; |
| 760 | } |
| 761 | } |
| 762 | |
| 763 | /* |
| 764 | ** Open the user database in "~/.fossil". Create the database anew if |
| @@ -806,16 +814,18 @@ | |
| 814 | zDbName = mprintf("%s/.fossil", zHome); |
| 815 | #endif |
| 816 | if( file_size(zDbName)<1024*3 ){ |
| 817 | db_init_database(zDbName, zConfigSchema, (char*)0); |
| 818 | } |
| 819 | if( useAttach ){ |
| 820 | db_open_or_attach(zDbName, "configdb", &g.useAttach); |
| 821 | g.dbConfig = 0; |
| 822 | g.zConfigDbType = 0; |
| 823 | }else{ |
| 824 | g.useAttach = 0; |
| 825 | g.dbConfig = openDatabase(zDbName); |
| 826 | g.zConfigDbType = "configdb"; |
| 827 | } |
| 828 | g.configOpen = 1; |
| 829 | free(zDbName); |
| 830 | } |
| 831 | |
| @@ -850,11 +860,11 @@ | |
| 860 | char *zVFileDef; |
| 861 | |
| 862 | if( file_access(zDbName, F_OK) ) return 0; |
| 863 | lsize = file_size(zDbName); |
| 864 | if( lsize%1024!=0 || lsize<4096 ) return 0; |
| 865 | db_open_or_attach(zDbName, "localdb", 0); |
| 866 | zVFileDef = db_text(0, "SELECT sql FROM %s.sqlite_master" |
| 867 | " WHERE name=='vfile'", db_name("localdb")); |
| 868 | |
| 869 | /* If the "isexe" column is missing from the vfile table, then |
| 870 | ** add it now. This code added on 2010-03-06. After all users have |
| @@ -986,11 +996,11 @@ | |
| 996 | g.json.resultCode = FSL_JSON_E_DB_NOT_VALID; |
| 997 | #endif |
| 998 | fossil_panic("not a valid repository: %s", zDbName); |
| 999 | } |
| 1000 | } |
| 1001 | db_open_or_attach(zDbName, "repository", 0); |
| 1002 | g.repositoryOpen = 1; |
| 1003 | g.zRepositoryName = mprintf("%s", zDbName); |
| 1004 | /* Cache "allow-symlinks" option, because we'll need it on every stat call */ |
| 1005 | g.allowSymlinks = db_get_boolean("allow-symlinks", 0); |
| 1006 | } |
| @@ -1109,11 +1119,11 @@ | |
| 1119 | file_canonical_name(g.argv[2], &repo, 0); |
| 1120 | zRepo = blob_str(&repo); |
| 1121 | if( file_access(zRepo, 0) ){ |
| 1122 | fossil_fatal("no such file: %s", zRepo); |
| 1123 | } |
| 1124 | db_open_or_attach(zRepo, "test_repo", 0); |
| 1125 | db_lset("repository", blob_str(&repo)); |
| 1126 | db_close(1); |
| 1127 | } |
| 1128 | |
| 1129 | |
| @@ -1177,13 +1187,15 @@ | |
| 1187 | g.localOpen = 0; |
| 1188 | g.configOpen = 0; |
| 1189 | sqlite3_wal_checkpoint(g.db, 0); |
| 1190 | sqlite3_close(g.db); |
| 1191 | g.db = 0; |
| 1192 | g.zMainDbType = 0; |
| 1193 | if( g.dbConfig ){ |
| 1194 | sqlite3_close(g.dbConfig); |
| 1195 | g.dbConfig = 0; |
| 1196 | g.zConfigDbType = 0; |
| 1197 | } |
| 1198 | } |
| 1199 | |
| 1200 | |
| 1201 | /* |
| @@ -1630,19 +1642,32 @@ | |
| 1642 | /* |
| 1643 | ** Swap the g.db and g.dbConfig connections so that the various db_* routines |
| 1644 | ** work on the ~/.fossil database instead of on the repository database. |
| 1645 | ** Be sure to swap them back after doing the operation. |
| 1646 | ** |
| 1647 | ** If the ~/.fossil database has already been opened as the main database or |
| 1648 | ** is attached to the main database, no connection swaps are required so this |
| 1649 | ** routine is a no-op. |
| 1650 | */ |
| 1651 | void db_swap_connections(void){ |
| 1652 | /* |
| 1653 | ** When swapping the main database connection with the config database |
| 1654 | ** connection, the config database connection must be open (not simply |
| 1655 | ** attached); otherwise, the swap would end up leaving the main database |
| 1656 | ** connection invalid, defeating the very purpose of this routine. This |
| 1657 | ** same constraint also holds true when restoring the previously swapped |
| 1658 | ** database connection; otherwise, it means that no swap was performed |
| 1659 | ** because the main database connection was already pointing to the config |
| 1660 | ** database. |
| 1661 | */ |
| 1662 | if( g.dbConfig ){ |
| 1663 | sqlite3 *dbTemp = g.db; |
| 1664 | const char *zTempDbType = g.zMainDbType; |
| 1665 | g.db = g.dbConfig; |
| 1666 | g.zMainDbType = g.zConfigDbType; |
| 1667 | g.dbConfig = dbTemp; |
| 1668 | g.zConfigDbType = zTempDbType; |
| 1669 | } |
| 1670 | } |
| 1671 | |
| 1672 | /* |
| 1673 | ** Logic for reading potentially versioned settings from |
| 1674 |
+1
-1
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -425,11 +425,11 @@ | ||
| 425 | 425 | char *zDate; |
| 426 | 426 | i64 iMTime; |
| 427 | 427 | if( g.argc!=4 ){ |
| 428 | 428 | usage("test-set-mtime FILENAME DATE/TIME"); |
| 429 | 429 | } |
| 430 | - db_open_or_attach(":memory:", "mem"); | |
| 430 | + db_open_or_attach(":memory:", "mem", 0); | |
| 431 | 431 | iMTime = db_int64(0, "SELECT strftime('%%s',%Q)", g.argv[3]); |
| 432 | 432 | zFile = g.argv[2]; |
| 433 | 433 | file_set_mtime(zFile, iMTime); |
| 434 | 434 | iMTime = file_wd_mtime(zFile); |
| 435 | 435 | zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMTime); |
| 436 | 436 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -425,11 +425,11 @@ | |
| 425 | char *zDate; |
| 426 | i64 iMTime; |
| 427 | if( g.argc!=4 ){ |
| 428 | usage("test-set-mtime FILENAME DATE/TIME"); |
| 429 | } |
| 430 | db_open_or_attach(":memory:", "mem"); |
| 431 | iMTime = db_int64(0, "SELECT strftime('%%s',%Q)", g.argv[3]); |
| 432 | zFile = g.argv[2]; |
| 433 | file_set_mtime(zFile, iMTime); |
| 434 | iMTime = file_wd_mtime(zFile); |
| 435 | zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMTime); |
| 436 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -425,11 +425,11 @@ | |
| 425 | char *zDate; |
| 426 | i64 iMTime; |
| 427 | if( g.argc!=4 ){ |
| 428 | usage("test-set-mtime FILENAME DATE/TIME"); |
| 429 | } |
| 430 | db_open_or_attach(":memory:", "mem", 0); |
| 431 | iMTime = db_int64(0, "SELECT strftime('%%s',%Q)", g.argv[3]); |
| 432 | zFile = g.argv[2]; |
| 433 | file_set_mtime(zFile, iMTime); |
| 434 | iMTime = file_wd_mtime(zFile); |
| 435 | zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMTime); |
| 436 |
+1
-1
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -425,11 +425,11 @@ | ||
| 425 | 425 | char *zDate; |
| 426 | 426 | i64 iMTime; |
| 427 | 427 | if( g.argc!=4 ){ |
| 428 | 428 | usage("test-set-mtime FILENAME DATE/TIME"); |
| 429 | 429 | } |
| 430 | - db_open_or_attach(":memory:", "mem"); | |
| 430 | + db_open_or_attach(":memory:", "mem", 0); | |
| 431 | 431 | iMTime = db_int64(0, "SELECT strftime('%%s',%Q)", g.argv[3]); |
| 432 | 432 | zFile = g.argv[2]; |
| 433 | 433 | file_set_mtime(zFile, iMTime); |
| 434 | 434 | iMTime = file_wd_mtime(zFile); |
| 435 | 435 | zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMTime); |
| 436 | 436 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -425,11 +425,11 @@ | |
| 425 | char *zDate; |
| 426 | i64 iMTime; |
| 427 | if( g.argc!=4 ){ |
| 428 | usage("test-set-mtime FILENAME DATE/TIME"); |
| 429 | } |
| 430 | db_open_or_attach(":memory:", "mem"); |
| 431 | iMTime = db_int64(0, "SELECT strftime('%%s',%Q)", g.argv[3]); |
| 432 | zFile = g.argv[2]; |
| 433 | file_set_mtime(zFile, iMTime); |
| 434 | iMTime = file_wd_mtime(zFile); |
| 435 | zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMTime); |
| 436 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -425,11 +425,11 @@ | |
| 425 | char *zDate; |
| 426 | i64 iMTime; |
| 427 | if( g.argc!=4 ){ |
| 428 | usage("test-set-mtime FILENAME DATE/TIME"); |
| 429 | } |
| 430 | db_open_or_attach(":memory:", "mem", 0); |
| 431 | iMTime = db_int64(0, "SELECT strftime('%%s',%Q)", g.argv[3]); |
| 432 | zFile = g.argv[2]; |
| 433 | file_set_mtime(zFile, iMTime); |
| 434 | iMTime = file_wd_mtime(zFile); |
| 435 | zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", iMTime); |
| 436 |
+1
-1
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -2153,11 +2153,11 @@ | ||
| 2153 | 2153 | if( zNewColor && zNewColor[0] ){ |
| 2154 | 2154 | @ <tr><td style="background-color: %h(zNewColor);"> |
| 2155 | 2155 | }else{ |
| 2156 | 2156 | @ <tr><td> |
| 2157 | 2157 | } |
| 2158 | - wiki_convert(&comment, 0, WIKI_INLINE|WIKI_NOBADLINKS); | |
| 2158 | + @ %w(blob_str(&comment)) | |
| 2159 | 2159 | blob_zero(&suffix); |
| 2160 | 2160 | blob_appendf(&suffix, "(user: %h", zNewUser); |
| 2161 | 2161 | db_prepare(&q, "SELECT substr(tagname,5) FROM tagxref, tag" |
| 2162 | 2162 | " WHERE tagname GLOB 'sym-*' AND tagxref.rid=%d" |
| 2163 | 2163 | " AND tagtype>1 AND tag.tagid=tagxref.tagid", |
| 2164 | 2164 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -2153,11 +2153,11 @@ | |
| 2153 | if( zNewColor && zNewColor[0] ){ |
| 2154 | @ <tr><td style="background-color: %h(zNewColor);"> |
| 2155 | }else{ |
| 2156 | @ <tr><td> |
| 2157 | } |
| 2158 | wiki_convert(&comment, 0, WIKI_INLINE|WIKI_NOBADLINKS); |
| 2159 | blob_zero(&suffix); |
| 2160 | blob_appendf(&suffix, "(user: %h", zNewUser); |
| 2161 | db_prepare(&q, "SELECT substr(tagname,5) FROM tagxref, tag" |
| 2162 | " WHERE tagname GLOB 'sym-*' AND tagxref.rid=%d" |
| 2163 | " AND tagtype>1 AND tag.tagid=tagxref.tagid", |
| 2164 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -2153,11 +2153,11 @@ | |
| 2153 | if( zNewColor && zNewColor[0] ){ |
| 2154 | @ <tr><td style="background-color: %h(zNewColor);"> |
| 2155 | }else{ |
| 2156 | @ <tr><td> |
| 2157 | } |
| 2158 | @ %w(blob_str(&comment)) |
| 2159 | blob_zero(&suffix); |
| 2160 | blob_appendf(&suffix, "(user: %h", zNewUser); |
| 2161 | db_prepare(&q, "SELECT substr(tagname,5) FROM tagxref, tag" |
| 2162 | " WHERE tagname GLOB 'sym-*' AND tagxref.rid=%d" |
| 2163 | " AND tagtype>1 AND tag.tagid=tagxref.tagid", |
| 2164 |
+1
| --- src/json.c | ||
| +++ src/json.c | ||
| @@ -1409,10 +1409,11 @@ | ||
| 1409 | 1409 | INT(g, isHome); |
| 1410 | 1410 | INT(g, nAux); |
| 1411 | 1411 | INT(g, allowSymlinks); |
| 1412 | 1412 | |
| 1413 | 1413 | CSTR(g, zMainDbType); |
| 1414 | + CSTR(g, zConfigDbType); | |
| 1414 | 1415 | CSTR(g, zHome); |
| 1415 | 1416 | CSTR(g, zLocalRoot); |
| 1416 | 1417 | CSTR(g, zPath); |
| 1417 | 1418 | CSTR(g, zExtra); |
| 1418 | 1419 | CSTR(g, zBaseURL); |
| 1419 | 1420 |
| --- src/json.c | |
| +++ src/json.c | |
| @@ -1409,10 +1409,11 @@ | |
| 1409 | INT(g, isHome); |
| 1410 | INT(g, nAux); |
| 1411 | INT(g, allowSymlinks); |
| 1412 | |
| 1413 | CSTR(g, zMainDbType); |
| 1414 | CSTR(g, zHome); |
| 1415 | CSTR(g, zLocalRoot); |
| 1416 | CSTR(g, zPath); |
| 1417 | CSTR(g, zExtra); |
| 1418 | CSTR(g, zBaseURL); |
| 1419 |
| --- src/json.c | |
| +++ src/json.c | |
| @@ -1409,10 +1409,11 @@ | |
| 1409 | INT(g, isHome); |
| 1410 | INT(g, nAux); |
| 1411 | INT(g, allowSymlinks); |
| 1412 | |
| 1413 | CSTR(g, zMainDbType); |
| 1414 | CSTR(g, zConfigDbType); |
| 1415 | CSTR(g, zHome); |
| 1416 | CSTR(g, zLocalRoot); |
| 1417 | CSTR(g, zPath); |
| 1418 | CSTR(g, zExtra); |
| 1419 | CSTR(g, zBaseURL); |
| 1420 |
+2
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -119,10 +119,11 @@ | ||
| 119 | 119 | int configOpen; /* True if the config database is open */ |
| 120 | 120 | sqlite3_int64 now; /* Seconds since 1970 */ |
| 121 | 121 | int repositoryOpen; /* True if the main repository database is open */ |
| 122 | 122 | char *zRepositoryName; /* Name of the repository database */ |
| 123 | 123 | const char *zMainDbType;/* "configdb", "localdb", or "repository" */ |
| 124 | + const char *zConfigDbType; /* "configdb", "localdb", or "repository" */ | |
| 124 | 125 | const char *zHome; /* Name of user home directory */ |
| 125 | 126 | int localOpen; /* True if the local database is open */ |
| 126 | 127 | char *zLocalRoot; /* The directory holding the local database */ |
| 127 | 128 | int minPrefix; /* Number of digits needed for a distinct UUID */ |
| 128 | 129 | int fSqlTrace; /* True if --sqltrace flag is present */ |
| @@ -152,10 +153,11 @@ | ||
| 152 | 153 | int xlinkClusterOnly; /* Set when cloning. Only process clusters */ |
| 153 | 154 | int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ |
| 154 | 155 | int *aCommitFile; /* Array of files to be committed */ |
| 155 | 156 | int markPrivate; /* All new artifacts are private if true */ |
| 156 | 157 | int clockSkewSeen; /* True if clocks on client and server out of sync */ |
| 158 | + int wikiFlags; /* Wiki conversion flags applied to %w and %W */ | |
| 157 | 159 | char isHTTP; /* True if server/CGI modes, else assume CLI. */ |
| 158 | 160 | char javascriptHyperlink; /* If true, set href= using script, not HTML */ |
| 159 | 161 | |
| 160 | 162 | int urlIsFile; /* True if a "file:" url */ |
| 161 | 163 | int urlIsHttps; /* True if a "https:" url */ |
| 162 | 164 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -119,10 +119,11 @@ | |
| 119 | int configOpen; /* True if the config database is open */ |
| 120 | sqlite3_int64 now; /* Seconds since 1970 */ |
| 121 | int repositoryOpen; /* True if the main repository database is open */ |
| 122 | char *zRepositoryName; /* Name of the repository database */ |
| 123 | const char *zMainDbType;/* "configdb", "localdb", or "repository" */ |
| 124 | const char *zHome; /* Name of user home directory */ |
| 125 | int localOpen; /* True if the local database is open */ |
| 126 | char *zLocalRoot; /* The directory holding the local database */ |
| 127 | int minPrefix; /* Number of digits needed for a distinct UUID */ |
| 128 | int fSqlTrace; /* True if --sqltrace flag is present */ |
| @@ -152,10 +153,11 @@ | |
| 152 | int xlinkClusterOnly; /* Set when cloning. Only process clusters */ |
| 153 | int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ |
| 154 | int *aCommitFile; /* Array of files to be committed */ |
| 155 | int markPrivate; /* All new artifacts are private if true */ |
| 156 | int clockSkewSeen; /* True if clocks on client and server out of sync */ |
| 157 | char isHTTP; /* True if server/CGI modes, else assume CLI. */ |
| 158 | char javascriptHyperlink; /* If true, set href= using script, not HTML */ |
| 159 | |
| 160 | int urlIsFile; /* True if a "file:" url */ |
| 161 | int urlIsHttps; /* True if a "https:" url */ |
| 162 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -119,10 +119,11 @@ | |
| 119 | int configOpen; /* True if the config database is open */ |
| 120 | sqlite3_int64 now; /* Seconds since 1970 */ |
| 121 | int repositoryOpen; /* True if the main repository database is open */ |
| 122 | char *zRepositoryName; /* Name of the repository database */ |
| 123 | const char *zMainDbType;/* "configdb", "localdb", or "repository" */ |
| 124 | const char *zConfigDbType; /* "configdb", "localdb", or "repository" */ |
| 125 | const char *zHome; /* Name of user home directory */ |
| 126 | int localOpen; /* True if the local database is open */ |
| 127 | char *zLocalRoot; /* The directory holding the local database */ |
| 128 | int minPrefix; /* Number of digits needed for a distinct UUID */ |
| 129 | int fSqlTrace; /* True if --sqltrace flag is present */ |
| @@ -152,10 +153,11 @@ | |
| 153 | int xlinkClusterOnly; /* Set when cloning. Only process clusters */ |
| 154 | int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ |
| 155 | int *aCommitFile; /* Array of files to be committed */ |
| 156 | int markPrivate; /* All new artifacts are private if true */ |
| 157 | int clockSkewSeen; /* True if clocks on client and server out of sync */ |
| 158 | int wikiFlags; /* Wiki conversion flags applied to %w and %W */ |
| 159 | char isHTTP; /* True if server/CGI modes, else assume CLI. */ |
| 160 | char javascriptHyperlink; /* If true, set href= using script, not HTML */ |
| 161 | |
| 162 | int urlIsFile; /* True if a "file:" url */ |
| 163 | int urlIsHttps; /* True if a "https:" url */ |
| 164 |
+23
-10
| --- src/printf.c | ||
| +++ src/printf.c | ||
| @@ -44,12 +44,11 @@ | ||
| 44 | 44 | #define etHTMLIZE 16 /* Make text safe for HTML */ |
| 45 | 45 | #define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */ |
| 46 | 46 | #define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */ |
| 47 | 47 | #define etFOSSILIZE 19 /* The fossil header encoding format. */ |
| 48 | 48 | #define etPATH 20 /* Path type */ |
| 49 | -#define etWIKISTR 21 /* Wiki text rendered from a char*: %w */ | |
| 50 | -#define etWIKIBLOB 22 /* Wiki text rendered from a Blob*: %W */ | |
| 49 | +#define etWIKISTR 21 /* Timeline comment text rendered from a char*: %w */ | |
| 51 | 50 | #define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */ |
| 52 | 51 | #define etROOT 24 /* String value of g.zTop: % */ |
| 53 | 52 | |
| 54 | 53 | |
| 55 | 54 | /* |
| @@ -92,11 +91,10 @@ | ||
| 92 | 91 | { 'q', 0, 4, etSQLESCAPE, 0, 0 }, |
| 93 | 92 | { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, |
| 94 | 93 | { 'b', 0, 2, etBLOB, 0, 0 }, |
| 95 | 94 | { 'B', 0, 2, etBLOBSQL, 0, 0 }, |
| 96 | 95 | { 'w', 0, 2, etWIKISTR, 0, 0 }, |
| 97 | - { 'W', 0, 2, etWIKIBLOB, 0, 0 }, | |
| 98 | 96 | { 'h', 0, 4, etHTMLIZE, 0, 0 }, |
| 99 | 97 | { 'R', 0, 0, etROOT, 0, 0 }, |
| 100 | 98 | { 't', 0, 4, etHTTPIZE, 0, 0 }, /* "/" -> "%2F" */ |
| 101 | 99 | { 'T', 0, 4, etURLIZE, 0, 0 }, /* "/" unchanged */ |
| 102 | 100 | { 'F', 0, 4, etFOSSILIZE, 0, 0 }, |
| @@ -156,10 +154,31 @@ | ||
| 156 | 154 | static int StrNLen32(const char *z, int N){ |
| 157 | 155 | int n = 0; |
| 158 | 156 | while( (N-- != 0) && *(z++)!=0 ){ n++; } |
| 159 | 157 | return n; |
| 160 | 158 | } |
| 159 | + | |
| 160 | +/* | |
| 161 | +** Return an appropriate set of flags for wiki_convert() for displaying | |
| 162 | +** comments on a timeline. These flag settings are determined by | |
| 163 | +** configuration parameters. | |
| 164 | +*/ | |
| 165 | +static int wiki_convert_flags(void){ | |
| 166 | + static int wikiFlags = 0; | |
| 167 | + if( wikiFlags==0 ){ | |
| 168 | + if( db_get_boolean("timeline-block-markup", 0) ){ | |
| 169 | + wikiFlags = WIKI_INLINE | WIKI_NOBADLINKS; | |
| 170 | + }else{ | |
| 171 | + wikiFlags = WIKI_INLINE | WIKI_NOBLOCK | WIKI_NOBADLINKS; | |
| 172 | + } | |
| 173 | + if( db_get_boolean("timeline-plaintext", 0) ){ | |
| 174 | + wikiFlags |= WIKI_LINKSONLY; | |
| 175 | + } | |
| 176 | + } | |
| 177 | + return wikiFlags; | |
| 178 | +} | |
| 179 | + | |
| 161 | 180 | |
| 162 | 181 | |
| 163 | 182 | /* |
| 164 | 183 | ** The root program. All variations call this core. |
| 165 | 184 | ** |
| @@ -698,21 +717,15 @@ | ||
| 698 | 717 | case etWIKISTR: { |
| 699 | 718 | int limit = flag_alternateform ? va_arg(ap,int) : -1; |
| 700 | 719 | char *zWiki = va_arg(ap, char*); |
| 701 | 720 | Blob wiki; |
| 702 | 721 | blob_init(&wiki, zWiki, limit); |
| 703 | - wiki_convert(&wiki, pBlob, WIKI_INLINE); | |
| 722 | + wiki_convert(&wiki, pBlob, wiki_convert_flags()); | |
| 704 | 723 | blob_reset(&wiki); |
| 705 | 724 | length = width = 0; |
| 706 | 725 | break; |
| 707 | 726 | } |
| 708 | - case etWIKIBLOB: { | |
| 709 | - Blob *pWiki = va_arg(ap, Blob*); | |
| 710 | - wiki_convert(pWiki, pBlob, WIKI_INLINE); | |
| 711 | - length = width = 0; | |
| 712 | - break; | |
| 713 | - } | |
| 714 | 727 | case etERROR: |
| 715 | 728 | buf[0] = '%'; |
| 716 | 729 | buf[1] = c; |
| 717 | 730 | errorflag = 0; |
| 718 | 731 | idx = 1+(c!=0); |
| 719 | 732 |
| --- src/printf.c | |
| +++ src/printf.c | |
| @@ -44,12 +44,11 @@ | |
| 44 | #define etHTMLIZE 16 /* Make text safe for HTML */ |
| 45 | #define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */ |
| 46 | #define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */ |
| 47 | #define etFOSSILIZE 19 /* The fossil header encoding format. */ |
| 48 | #define etPATH 20 /* Path type */ |
| 49 | #define etWIKISTR 21 /* Wiki text rendered from a char*: %w */ |
| 50 | #define etWIKIBLOB 22 /* Wiki text rendered from a Blob*: %W */ |
| 51 | #define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */ |
| 52 | #define etROOT 24 /* String value of g.zTop: % */ |
| 53 | |
| 54 | |
| 55 | /* |
| @@ -92,11 +91,10 @@ | |
| 92 | { 'q', 0, 4, etSQLESCAPE, 0, 0 }, |
| 93 | { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, |
| 94 | { 'b', 0, 2, etBLOB, 0, 0 }, |
| 95 | { 'B', 0, 2, etBLOBSQL, 0, 0 }, |
| 96 | { 'w', 0, 2, etWIKISTR, 0, 0 }, |
| 97 | { 'W', 0, 2, etWIKIBLOB, 0, 0 }, |
| 98 | { 'h', 0, 4, etHTMLIZE, 0, 0 }, |
| 99 | { 'R', 0, 0, etROOT, 0, 0 }, |
| 100 | { 't', 0, 4, etHTTPIZE, 0, 0 }, /* "/" -> "%2F" */ |
| 101 | { 'T', 0, 4, etURLIZE, 0, 0 }, /* "/" unchanged */ |
| 102 | { 'F', 0, 4, etFOSSILIZE, 0, 0 }, |
| @@ -156,10 +154,31 @@ | |
| 156 | static int StrNLen32(const char *z, int N){ |
| 157 | int n = 0; |
| 158 | while( (N-- != 0) && *(z++)!=0 ){ n++; } |
| 159 | return n; |
| 160 | } |
| 161 | |
| 162 | |
| 163 | /* |
| 164 | ** The root program. All variations call this core. |
| 165 | ** |
| @@ -698,21 +717,15 @@ | |
| 698 | case etWIKISTR: { |
| 699 | int limit = flag_alternateform ? va_arg(ap,int) : -1; |
| 700 | char *zWiki = va_arg(ap, char*); |
| 701 | Blob wiki; |
| 702 | blob_init(&wiki, zWiki, limit); |
| 703 | wiki_convert(&wiki, pBlob, WIKI_INLINE); |
| 704 | blob_reset(&wiki); |
| 705 | length = width = 0; |
| 706 | break; |
| 707 | } |
| 708 | case etWIKIBLOB: { |
| 709 | Blob *pWiki = va_arg(ap, Blob*); |
| 710 | wiki_convert(pWiki, pBlob, WIKI_INLINE); |
| 711 | length = width = 0; |
| 712 | break; |
| 713 | } |
| 714 | case etERROR: |
| 715 | buf[0] = '%'; |
| 716 | buf[1] = c; |
| 717 | errorflag = 0; |
| 718 | idx = 1+(c!=0); |
| 719 |
| --- src/printf.c | |
| +++ src/printf.c | |
| @@ -44,12 +44,11 @@ | |
| 44 | #define etHTMLIZE 16 /* Make text safe for HTML */ |
| 45 | #define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */ |
| 46 | #define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */ |
| 47 | #define etFOSSILIZE 19 /* The fossil header encoding format. */ |
| 48 | #define etPATH 20 /* Path type */ |
| 49 | #define etWIKISTR 21 /* Timeline comment text rendered from a char*: %w */ |
| 50 | #define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */ |
| 51 | #define etROOT 24 /* String value of g.zTop: % */ |
| 52 | |
| 53 | |
| 54 | /* |
| @@ -92,11 +91,10 @@ | |
| 91 | { 'q', 0, 4, etSQLESCAPE, 0, 0 }, |
| 92 | { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, |
| 93 | { 'b', 0, 2, etBLOB, 0, 0 }, |
| 94 | { 'B', 0, 2, etBLOBSQL, 0, 0 }, |
| 95 | { 'w', 0, 2, etWIKISTR, 0, 0 }, |
| 96 | { 'h', 0, 4, etHTMLIZE, 0, 0 }, |
| 97 | { 'R', 0, 0, etROOT, 0, 0 }, |
| 98 | { 't', 0, 4, etHTTPIZE, 0, 0 }, /* "/" -> "%2F" */ |
| 99 | { 'T', 0, 4, etURLIZE, 0, 0 }, /* "/" unchanged */ |
| 100 | { 'F', 0, 4, etFOSSILIZE, 0, 0 }, |
| @@ -156,10 +154,31 @@ | |
| 154 | static int StrNLen32(const char *z, int N){ |
| 155 | int n = 0; |
| 156 | while( (N-- != 0) && *(z++)!=0 ){ n++; } |
| 157 | return n; |
| 158 | } |
| 159 | |
| 160 | /* |
| 161 | ** Return an appropriate set of flags for wiki_convert() for displaying |
| 162 | ** comments on a timeline. These flag settings are determined by |
| 163 | ** configuration parameters. |
| 164 | */ |
| 165 | static int wiki_convert_flags(void){ |
| 166 | static int wikiFlags = 0; |
| 167 | if( wikiFlags==0 ){ |
| 168 | if( db_get_boolean("timeline-block-markup", 0) ){ |
| 169 | wikiFlags = WIKI_INLINE | WIKI_NOBADLINKS; |
| 170 | }else{ |
| 171 | wikiFlags = WIKI_INLINE | WIKI_NOBLOCK | WIKI_NOBADLINKS; |
| 172 | } |
| 173 | if( db_get_boolean("timeline-plaintext", 0) ){ |
| 174 | wikiFlags |= WIKI_LINKSONLY; |
| 175 | } |
| 176 | } |
| 177 | return wikiFlags; |
| 178 | } |
| 179 | |
| 180 | |
| 181 | |
| 182 | /* |
| 183 | ** The root program. All variations call this core. |
| 184 | ** |
| @@ -698,21 +717,15 @@ | |
| 717 | case etWIKISTR: { |
| 718 | int limit = flag_alternateform ? va_arg(ap,int) : -1; |
| 719 | char *zWiki = va_arg(ap, char*); |
| 720 | Blob wiki; |
| 721 | blob_init(&wiki, zWiki, limit); |
| 722 | wiki_convert(&wiki, pBlob, wiki_convert_flags()); |
| 723 | blob_reset(&wiki); |
| 724 | length = width = 0; |
| 725 | break; |
| 726 | } |
| 727 | case etERROR: |
| 728 | buf[0] = '%'; |
| 729 | buf[1] = c; |
| 730 | errorflag = 0; |
| 731 | idx = 1+(c!=0); |
| 732 |
+2
-16
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -192,12 +192,10 @@ | ||
| 192 | 192 | int tmFlags, /* Flags controlling display behavior */ |
| 193 | 193 | const char *zThisUser, /* Suppress links to this user */ |
| 194 | 194 | const char *zThisTag, /* Suppress links to this tag */ |
| 195 | 195 | void (*xExtra)(int) /* Routine to call on each line of display */ |
| 196 | 196 | ){ |
| 197 | - int wikiFlags; | |
| 198 | - int plainText; | |
| 199 | 197 | int mxWikiLen; |
| 200 | 198 | Blob comment; |
| 201 | 199 | int prevTagid = 0; |
| 202 | 200 | int suppressCnt = 0; |
| 203 | 201 | char zPrevDate[20]; |
| @@ -207,17 +205,11 @@ | ||
| 207 | 205 | Stmt fchngQuery; /* Query for file changes on check-ins */ |
| 208 | 206 | static Stmt qbranch; |
| 209 | 207 | int pendingEndTr = 0; /* True if a </td></tr> is needed */ |
| 210 | 208 | |
| 211 | 209 | zPrevDate[0] = 0; |
| 212 | - plainText = db_get_int("timeline-plaintext", 0); | |
| 213 | 210 | mxWikiLen = db_get_int("timeline-max-comment", 0); |
| 214 | - if( db_get_boolean("timeline-block-markup", 0) ){ | |
| 215 | - wikiFlags = WIKI_INLINE | WIKI_NOBADLINKS; | |
| 216 | - }else{ | |
| 217 | - wikiFlags = WIKI_INLINE | WIKI_NOBLOCK | WIKI_NOBADLINKS; | |
| 218 | - } | |
| 219 | 211 | if( tmFlags & TIMELINE_GRAPH ){ |
| 220 | 212 | pGraph = graph_init(); |
| 221 | 213 | /* style is not moved to css, because this is |
| 222 | 214 | ** a technical div for the timeline graph |
| 223 | 215 | */ |
| @@ -357,20 +349,14 @@ | ||
| 357 | 349 | if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){ |
| 358 | 350 | Blob truncated; |
| 359 | 351 | blob_zero(&truncated); |
| 360 | 352 | blob_append(&truncated, blob_buffer(&comment), mxWikiLen); |
| 361 | 353 | blob_append(&truncated, "...", 3); |
| 362 | - if( plainText ){ | |
| 363 | - @ %h(blob_str(&truncated)) | |
| 364 | - }else{ | |
| 365 | - wiki_convert(&truncated, 0, wikiFlags); | |
| 366 | - } | |
| 354 | + @ %w(blob_str(&truncated)) | |
| 367 | 355 | blob_reset(&truncated); |
| 368 | - }else if( plainText ){ | |
| 369 | - @ %h(blob_str(&comment)); | |
| 370 | 356 | }else{ |
| 371 | - wiki_convert(&comment, 0, wikiFlags); | |
| 357 | + @ %w(blob_str(&comment)) | |
| 372 | 358 | } |
| 373 | 359 | blob_reset(&comment); |
| 374 | 360 | |
| 375 | 361 | /* Generate the "user: USERNAME" at the end of the comment, together |
| 376 | 362 | ** with a hyperlink to another timeline for that user. |
| 377 | 363 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -192,12 +192,10 @@ | |
| 192 | int tmFlags, /* Flags controlling display behavior */ |
| 193 | const char *zThisUser, /* Suppress links to this user */ |
| 194 | const char *zThisTag, /* Suppress links to this tag */ |
| 195 | void (*xExtra)(int) /* Routine to call on each line of display */ |
| 196 | ){ |
| 197 | int wikiFlags; |
| 198 | int plainText; |
| 199 | int mxWikiLen; |
| 200 | Blob comment; |
| 201 | int prevTagid = 0; |
| 202 | int suppressCnt = 0; |
| 203 | char zPrevDate[20]; |
| @@ -207,17 +205,11 @@ | |
| 207 | Stmt fchngQuery; /* Query for file changes on check-ins */ |
| 208 | static Stmt qbranch; |
| 209 | int pendingEndTr = 0; /* True if a </td></tr> is needed */ |
| 210 | |
| 211 | zPrevDate[0] = 0; |
| 212 | plainText = db_get_int("timeline-plaintext", 0); |
| 213 | mxWikiLen = db_get_int("timeline-max-comment", 0); |
| 214 | if( db_get_boolean("timeline-block-markup", 0) ){ |
| 215 | wikiFlags = WIKI_INLINE | WIKI_NOBADLINKS; |
| 216 | }else{ |
| 217 | wikiFlags = WIKI_INLINE | WIKI_NOBLOCK | WIKI_NOBADLINKS; |
| 218 | } |
| 219 | if( tmFlags & TIMELINE_GRAPH ){ |
| 220 | pGraph = graph_init(); |
| 221 | /* style is not moved to css, because this is |
| 222 | ** a technical div for the timeline graph |
| 223 | */ |
| @@ -357,20 +349,14 @@ | |
| 357 | if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){ |
| 358 | Blob truncated; |
| 359 | blob_zero(&truncated); |
| 360 | blob_append(&truncated, blob_buffer(&comment), mxWikiLen); |
| 361 | blob_append(&truncated, "...", 3); |
| 362 | if( plainText ){ |
| 363 | @ %h(blob_str(&truncated)) |
| 364 | }else{ |
| 365 | wiki_convert(&truncated, 0, wikiFlags); |
| 366 | } |
| 367 | blob_reset(&truncated); |
| 368 | }else if( plainText ){ |
| 369 | @ %h(blob_str(&comment)); |
| 370 | }else{ |
| 371 | wiki_convert(&comment, 0, wikiFlags); |
| 372 | } |
| 373 | blob_reset(&comment); |
| 374 | |
| 375 | /* Generate the "user: USERNAME" at the end of the comment, together |
| 376 | ** with a hyperlink to another timeline for that user. |
| 377 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -192,12 +192,10 @@ | |
| 192 | int tmFlags, /* Flags controlling display behavior */ |
| 193 | const char *zThisUser, /* Suppress links to this user */ |
| 194 | const char *zThisTag, /* Suppress links to this tag */ |
| 195 | void (*xExtra)(int) /* Routine to call on each line of display */ |
| 196 | ){ |
| 197 | int mxWikiLen; |
| 198 | Blob comment; |
| 199 | int prevTagid = 0; |
| 200 | int suppressCnt = 0; |
| 201 | char zPrevDate[20]; |
| @@ -207,17 +205,11 @@ | |
| 205 | Stmt fchngQuery; /* Query for file changes on check-ins */ |
| 206 | static Stmt qbranch; |
| 207 | int pendingEndTr = 0; /* True if a </td></tr> is needed */ |
| 208 | |
| 209 | zPrevDate[0] = 0; |
| 210 | mxWikiLen = db_get_int("timeline-max-comment", 0); |
| 211 | if( tmFlags & TIMELINE_GRAPH ){ |
| 212 | pGraph = graph_init(); |
| 213 | /* style is not moved to css, because this is |
| 214 | ** a technical div for the timeline graph |
| 215 | */ |
| @@ -357,20 +349,14 @@ | |
| 349 | if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){ |
| 350 | Blob truncated; |
| 351 | blob_zero(&truncated); |
| 352 | blob_append(&truncated, blob_buffer(&comment), mxWikiLen); |
| 353 | blob_append(&truncated, "...", 3); |
| 354 | @ %w(blob_str(&truncated)) |
| 355 | blob_reset(&truncated); |
| 356 | }else{ |
| 357 | @ %w(blob_str(&comment)) |
| 358 | } |
| 359 | blob_reset(&comment); |
| 360 | |
| 361 | /* Generate the "user: USERNAME" at the end of the comment, together |
| 362 | ** with a hyperlink to another timeline for that user. |
| 363 |
+10
-2
| --- src/wikiformat.c | ||
| +++ src/wikiformat.c | ||
| @@ -1635,20 +1635,28 @@ | ||
| 1635 | 1635 | }else{ |
| 1636 | 1636 | renderer.pOut = cgi_output_blob(); |
| 1637 | 1637 | } |
| 1638 | 1638 | |
| 1639 | 1639 | blob_strip_bom(pIn, 0); |
| 1640 | - if( flags & WIKI_LINKSONLY ) blob_append(renderer.pOut, "<pre>", 5); | |
| 1641 | 1640 | wiki_render(&renderer, blob_str(pIn)); |
| 1642 | 1641 | endAutoParagraph(&renderer); |
| 1643 | 1642 | while( renderer.nStack ){ |
| 1644 | 1643 | popStack(&renderer); |
| 1645 | 1644 | } |
| 1646 | - if( flags & WIKI_LINKSONLY ) blob_append(renderer.pOut, "</pre>", 5); | |
| 1647 | 1645 | blob_append(renderer.pOut, "\n", 1); |
| 1648 | 1646 | free(renderer.aStack); |
| 1649 | 1647 | } |
| 1648 | + | |
| 1649 | +/* | |
| 1650 | +** Send a string as wiki to CGI output. | |
| 1651 | +*/ | |
| 1652 | +void wiki_write(const char *zIn, int flags){ | |
| 1653 | + Blob in; | |
| 1654 | + blob_init(&in, zIn, -1); | |
| 1655 | + wiki_convert(&in, 0, flags); | |
| 1656 | + blob_reset(&in); | |
| 1657 | +} | |
| 1650 | 1658 | |
| 1651 | 1659 | /* |
| 1652 | 1660 | ** COMMAND: test-wiki-render |
| 1653 | 1661 | ** |
| 1654 | 1662 | ** %fossil test-wiki-render FILE [OPTIONS] |
| 1655 | 1663 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -1635,20 +1635,28 @@ | |
| 1635 | }else{ |
| 1636 | renderer.pOut = cgi_output_blob(); |
| 1637 | } |
| 1638 | |
| 1639 | blob_strip_bom(pIn, 0); |
| 1640 | if( flags & WIKI_LINKSONLY ) blob_append(renderer.pOut, "<pre>", 5); |
| 1641 | wiki_render(&renderer, blob_str(pIn)); |
| 1642 | endAutoParagraph(&renderer); |
| 1643 | while( renderer.nStack ){ |
| 1644 | popStack(&renderer); |
| 1645 | } |
| 1646 | if( flags & WIKI_LINKSONLY ) blob_append(renderer.pOut, "</pre>", 5); |
| 1647 | blob_append(renderer.pOut, "\n", 1); |
| 1648 | free(renderer.aStack); |
| 1649 | } |
| 1650 | |
| 1651 | /* |
| 1652 | ** COMMAND: test-wiki-render |
| 1653 | ** |
| 1654 | ** %fossil test-wiki-render FILE [OPTIONS] |
| 1655 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -1635,20 +1635,28 @@ | |
| 1635 | }else{ |
| 1636 | renderer.pOut = cgi_output_blob(); |
| 1637 | } |
| 1638 | |
| 1639 | blob_strip_bom(pIn, 0); |
| 1640 | wiki_render(&renderer, blob_str(pIn)); |
| 1641 | endAutoParagraph(&renderer); |
| 1642 | while( renderer.nStack ){ |
| 1643 | popStack(&renderer); |
| 1644 | } |
| 1645 | blob_append(renderer.pOut, "\n", 1); |
| 1646 | free(renderer.aStack); |
| 1647 | } |
| 1648 | |
| 1649 | /* |
| 1650 | ** Send a string as wiki to CGI output. |
| 1651 | */ |
| 1652 | void wiki_write(const char *zIn, int flags){ |
| 1653 | Blob in; |
| 1654 | blob_init(&in, zIn, -1); |
| 1655 | wiki_convert(&in, 0, flags); |
| 1656 | blob_reset(&in); |
| 1657 | } |
| 1658 | |
| 1659 | /* |
| 1660 | ** COMMAND: test-wiki-render |
| 1661 | ** |
| 1662 | ** %fossil test-wiki-render FILE [OPTIONS] |
| 1663 |