Fossil SCM
Enable search over the forum.
Commit
b3c1ba372e7687121298ea5e6edc03dd427d10d80d7b545c3430c814f3613818
Parent
009ca1f74e48b23…
2 files changed
+63
-4
+2
+63
-4
| --- src/search.c | ||
| +++ src/search.c | ||
| @@ -638,11 +638,12 @@ | ||
| 638 | 638 | #define SRCH_CKIN 0x0001 /* Search over check-in comments */ |
| 639 | 639 | #define SRCH_DOC 0x0002 /* Search over embedded documents */ |
| 640 | 640 | #define SRCH_TKT 0x0004 /* Search over tickets */ |
| 641 | 641 | #define SRCH_WIKI 0x0008 /* Search over wiki */ |
| 642 | 642 | #define SRCH_TECHNOTE 0x0010 /* Search over tech notes */ |
| 643 | -#define SRCH_ALL 0x001f /* Search over everything */ | |
| 643 | +#define SRCH_FORUM 0x0020 /* Search over forum messages */ | |
| 644 | +#define SRCH_ALL 0x003f /* Search over everything */ | |
| 644 | 645 | #endif |
| 645 | 646 | |
| 646 | 647 | /* |
| 647 | 648 | ** Remove bits from srchFlags which are disallowed by either the |
| 648 | 649 | ** current server configuration or by user permissions. |
| @@ -654,15 +655,17 @@ | ||
| 654 | 655 | { SRCH_CKIN, "search-ci" }, |
| 655 | 656 | { SRCH_DOC, "search-doc" }, |
| 656 | 657 | { SRCH_TKT, "search-tkt" }, |
| 657 | 658 | { SRCH_WIKI, "search-wiki" }, |
| 658 | 659 | { SRCH_TECHNOTE, "search-technote" }, |
| 660 | + { SRCH_FORUM, "search-forum" }, | |
| 659 | 661 | }; |
| 660 | 662 | int i; |
| 661 | 663 | if( g.perm.Read==0 ) srchFlags &= ~(SRCH_CKIN|SRCH_DOC|SRCH_TECHNOTE); |
| 662 | 664 | if( g.perm.RdTkt==0 ) srchFlags &= ~(SRCH_TKT); |
| 663 | 665 | if( g.perm.RdWiki==0 ) srchFlags &= ~(SRCH_WIKI); |
| 666 | + if( g.perm.RdForum==0) srchFlags &= ~(SRCH_FORUM); | |
| 664 | 667 | for(i=0; i<count(aSetng); i++){ |
| 665 | 668 | unsigned int m = aSetng[i].m; |
| 666 | 669 | if( (srchFlags & m)==0 ) continue; |
| 667 | 670 | if( ((knownGood|knownBad) & m)!=0 ) continue; |
| 668 | 671 | if( db_get_boolean(aSetng[i].zKey,0) ){ |
| @@ -793,10 +796,23 @@ | ||
| 793 | 796 | " search_snippet()" |
| 794 | 797 | " FROM technote" |
| 795 | 798 | " WHERE search_match('',body('e',rid,NULL));" |
| 796 | 799 | ); |
| 797 | 800 | } |
| 801 | + if( (srchFlags & SRCH_FORUM)!=0 ){ | |
| 802 | + db_multi_exec( | |
| 803 | + "INSERT INTO x(label,url,score,id,date,snip)" | |
| 804 | + " SELECT 'Forum '||comment," | |
| 805 | + " '/forumpost/'||uuid," | |
| 806 | + " search_score()," | |
| 807 | + " 'f'||rid," | |
| 808 | + " datetime(event.mtime)," | |
| 809 | + " search_snippet()" | |
| 810 | + " FROM event JOIN blob on event.objid=blob.rid" | |
| 811 | + " WHERE search_match('',body('f',rid,NULL));" | |
| 812 | + ); | |
| 813 | + } | |
| 798 | 814 | } |
| 799 | 815 | |
| 800 | 816 | /* |
| 801 | 817 | ** Number of significant bits in a u32 |
| 802 | 818 | */ |
| @@ -913,10 +929,11 @@ | ||
| 913 | 929 | { SRCH_CKIN, 'c' }, |
| 914 | 930 | { SRCH_DOC, 'd' }, |
| 915 | 931 | { SRCH_TKT, 't' }, |
| 916 | 932 | { SRCH_WIKI, 'w' }, |
| 917 | 933 | { SRCH_TECHNOTE, 'e' }, |
| 934 | + { SRCH_FORUM, 'f' }, | |
| 918 | 935 | }; |
| 919 | 936 | int i; |
| 920 | 937 | for(i=0; i<count(aMask); i++){ |
| 921 | 938 | if( srchFlags & aMask[i].m ){ |
| 922 | 939 | blob_appendf(&sql, "%sftsdocs.type='%c'", zSep, aMask[i].c); |
| @@ -1066,10 +1083,11 @@ | ||
| 1066 | 1083 | case SRCH_CKIN: zType = " Check-ins"; zClass = "Ckin"; break; |
| 1067 | 1084 | case SRCH_DOC: zType = " Docs"; zClass = "Doc"; break; |
| 1068 | 1085 | case SRCH_TKT: zType = " Tickets"; zClass = "Tkt"; break; |
| 1069 | 1086 | case SRCH_WIKI: zType = " Wiki"; zClass = "Wiki"; break; |
| 1070 | 1087 | case SRCH_TECHNOTE: zType = " Tech Notes"; zClass = "Note"; break; |
| 1088 | + case SRCH_FORUM: zType = " Forum"; zClass = "Frm"; break; | |
| 1071 | 1089 | } |
| 1072 | 1090 | if( srchFlags==0 ){ |
| 1073 | 1091 | zDisable1 = " disabled"; |
| 1074 | 1092 | zDisable2 = " disabled"; |
| 1075 | 1093 | zPattern = ""; |
| @@ -1091,10 +1109,11 @@ | ||
| 1091 | 1109 | { "c", "Check-ins", SRCH_CKIN }, |
| 1092 | 1110 | { "d", "Docs", SRCH_DOC }, |
| 1093 | 1111 | { "t", "Tickets", SRCH_TKT }, |
| 1094 | 1112 | { "w", "Wiki", SRCH_WIKI }, |
| 1095 | 1113 | { "e", "Tech Notes", SRCH_TECHNOTE }, |
| 1114 | + { "f", "Forum", SRCH_FORUM }, | |
| 1096 | 1115 | }; |
| 1097 | 1116 | const char *zY = PD("y","all"); |
| 1098 | 1117 | unsigned newFlags = srchFlags; |
| 1099 | 1118 | int i; |
| 1100 | 1119 | @ <select size='1' name='y'> |
| @@ -1143,10 +1162,11 @@ | ||
| 1143 | 1162 | ** c -> check-ins |
| 1144 | 1163 | ** d -> documentation |
| 1145 | 1164 | ** t -> tickets |
| 1146 | 1165 | ** w -> wiki |
| 1147 | 1166 | ** e -> tech notes |
| 1167 | +** f -> forum | |
| 1148 | 1168 | ** all -> everything |
| 1149 | 1169 | */ |
| 1150 | 1170 | void search_page(void){ |
| 1151 | 1171 | login_check_credentials(); |
| 1152 | 1172 | style_header("Search"); |
| @@ -1250,10 +1270,11 @@ | ||
| 1250 | 1270 | ** cType: d Embedded documentation |
| 1251 | 1271 | ** w Wiki page |
| 1252 | 1272 | ** c Check-in comment |
| 1253 | 1273 | ** t Ticket text |
| 1254 | 1274 | ** e Tech note |
| 1275 | +** f Forum | |
| 1255 | 1276 | ** |
| 1256 | 1277 | ** rid The RID of an artifact that defines the object |
| 1257 | 1278 | ** being searched. |
| 1258 | 1279 | ** |
| 1259 | 1280 | ** zName Name of the object being searched. This is used |
| @@ -1275,17 +1296,27 @@ | ||
| 1275 | 1296 | blob_to_utf8_no_bom(&doc, 0); |
| 1276 | 1297 | get_stext_by_mimetype(&doc, mimetype_from_name(zName), pOut); |
| 1277 | 1298 | blob_reset(&doc); |
| 1278 | 1299 | break; |
| 1279 | 1300 | } |
| 1301 | + case 'f': /* Forum messages */ | |
| 1280 | 1302 | case 'e': /* Tech Notes */ |
| 1281 | 1303 | case 'w': { /* Wiki */ |
| 1282 | 1304 | Manifest *pWiki = manifest_get(rid, |
| 1283 | - cType == 'e' ? CFTYPE_EVENT : CFTYPE_WIKI, 0); | |
| 1305 | + cType == 'e' ? CFTYPE_EVENT : | |
| 1306 | + cType == 'f' ? CFTYPE_FORUM : CFTYPE_WIKI, 0); | |
| 1284 | 1307 | Blob wiki; |
| 1285 | 1308 | if( pWiki==0 ) break; |
| 1286 | - blob_init(&wiki, pWiki->zWiki, -1); | |
| 1309 | + if( cType=='f' ){ | |
| 1310 | + blob_init(&wiki, 0, 0); | |
| 1311 | + if( pWiki->zThreadTitle ){ | |
| 1312 | + blob_appendf(&wiki, "<h1>%h</h1>\n", pWiki->zThreadTitle); | |
| 1313 | + } | |
| 1314 | + blob_appendf(&wiki, "From %s:\n\n%s", pWiki->zUser, pWiki->zWiki); | |
| 1315 | + }else{ | |
| 1316 | + blob_init(&wiki, pWiki->zWiki, -1); | |
| 1317 | + } | |
| 1287 | 1318 | get_stext_by_mimetype(&wiki, wiki_filter_mimetypes(pWiki->zMimetype), |
| 1288 | 1319 | pOut); |
| 1289 | 1320 | blob_reset(&wiki); |
| 1290 | 1321 | manifest_destroy(pWiki); |
| 1291 | 1322 | break; |
| @@ -1516,11 +1547,11 @@ | ||
| 1516 | 1547 | "INSERT OR IGNORE INTO ftsdocs(type,rid,idxed)" |
| 1517 | 1548 | " SELECT 't', tkt_id, 0 FROM ticket;" |
| 1518 | 1549 | ); |
| 1519 | 1550 | db_multi_exec( |
| 1520 | 1551 | "INSERT OR IGNORE INTO ftsdocs(type,rid,name,idxed)" |
| 1521 | - " SELECT 'e', objid, comment, 0 FROM event WHERE type='e';" | |
| 1552 | + " SELECT type, objid, comment, 0 FROM event WHERE type IN ('e','f');" | |
| 1522 | 1553 | ); |
| 1523 | 1554 | } |
| 1524 | 1555 | |
| 1525 | 1556 | /* |
| 1526 | 1557 | ** The document described by cType,rid,zName is about to be added or |
| @@ -1553,10 +1584,11 @@ | ||
| 1553 | 1584 | db_multi_exec( |
| 1554 | 1585 | "DELETE FROM ftsdocs WHERE type='%c' AND name=%Q AND rid!=%d", |
| 1555 | 1586 | cType, zName, rid |
| 1556 | 1587 | ); |
| 1557 | 1588 | } |
| 1589 | + /* All forum posts are always indexed */ | |
| 1558 | 1590 | } |
| 1559 | 1591 | } |
| 1560 | 1592 | |
| 1561 | 1593 | /* |
| 1562 | 1594 | ** If the doc-glob and doc-br settings are valid for document search |
| @@ -1681,10 +1713,33 @@ | ||
| 1681 | 1713 | " tagxref.mtime" |
| 1682 | 1714 | " FROM tagxref WHERE tagxref.rid=ftsdocs.rid)" |
| 1683 | 1715 | " WHERE ftsdocs.type='w' AND NOT ftsdocs.idxed" |
| 1684 | 1716 | ); |
| 1685 | 1717 | } |
| 1718 | + | |
| 1719 | +/* | |
| 1720 | +** Deal with all of the unindexed 'f' terms in FTSDOCS | |
| 1721 | +*/ | |
| 1722 | +static void search_update_forum_index(void){ | |
| 1723 | + db_multi_exec( | |
| 1724 | + "INSERT INTO ftsidx(docid,title,body)" | |
| 1725 | + " SELECT rowid, title('f',rid,NULL),body('f',rid,NULL) FROM ftsdocs" | |
| 1726 | + " WHERE type='f' AND NOT idxed;" | |
| 1727 | + ); | |
| 1728 | + if( db_changes()==0 ) return; | |
| 1729 | + db_multi_exec( | |
| 1730 | + "UPDATE ftsdocs SET idxed=1, name=NULL," | |
| 1731 | + " (label,url,mtime) = " | |
| 1732 | + " (SELECT 'Forum '||event.comment," | |
| 1733 | + " '/forumpost/'||blob.uuid," | |
| 1734 | + " event.mtime" | |
| 1735 | + " FROM event, blob" | |
| 1736 | + " WHERE event.objid=ftsdocs.rid" | |
| 1737 | + " AND blob.rid=ftsdocs.rid)" | |
| 1738 | + "WHERE ftsdocs.type='f' AND NOT ftsdocs.idxed" | |
| 1739 | + ); | |
| 1740 | +} | |
| 1686 | 1741 | |
| 1687 | 1742 | /* |
| 1688 | 1743 | ** Deal with all of the unindexed 'e' terms in FTSDOCS |
| 1689 | 1744 | */ |
| 1690 | 1745 | static void search_update_technote_index(void){ |
| @@ -1728,10 +1783,13 @@ | ||
| 1728 | 1783 | search_update_wiki_index(); |
| 1729 | 1784 | } |
| 1730 | 1785 | if( srchFlags & SRCH_TECHNOTE ){ |
| 1731 | 1786 | search_update_technote_index(); |
| 1732 | 1787 | } |
| 1788 | + if( srchFlags & SRCH_FORUM ){ | |
| 1789 | + search_update_forum_index(); | |
| 1790 | + } | |
| 1733 | 1791 | } |
| 1734 | 1792 | |
| 1735 | 1793 | /* |
| 1736 | 1794 | ** Construct, prepopulate, and then update the full-text index. |
| 1737 | 1795 | */ |
| @@ -1780,10 +1838,11 @@ | ||
| 1780 | 1838 | { "search-ci", "check-in search:", "c" }, |
| 1781 | 1839 | { "search-doc", "document search:", "d" }, |
| 1782 | 1840 | { "search-tkt", "ticket search:", "t" }, |
| 1783 | 1841 | { "search-wiki", "wiki search:", "w" }, |
| 1784 | 1842 | { "search-technote", "tech note search:", "e" }, |
| 1843 | + { "search-forum", "forum search:", "f" }, | |
| 1785 | 1844 | }; |
| 1786 | 1845 | char *zSubCmd = 0; |
| 1787 | 1846 | int i, j, n; |
| 1788 | 1847 | int iCmd = 0; |
| 1789 | 1848 | int iAction = 0; |
| 1790 | 1849 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -638,11 +638,12 @@ | |
| 638 | #define SRCH_CKIN 0x0001 /* Search over check-in comments */ |
| 639 | #define SRCH_DOC 0x0002 /* Search over embedded documents */ |
| 640 | #define SRCH_TKT 0x0004 /* Search over tickets */ |
| 641 | #define SRCH_WIKI 0x0008 /* Search over wiki */ |
| 642 | #define SRCH_TECHNOTE 0x0010 /* Search over tech notes */ |
| 643 | #define SRCH_ALL 0x001f /* Search over everything */ |
| 644 | #endif |
| 645 | |
| 646 | /* |
| 647 | ** Remove bits from srchFlags which are disallowed by either the |
| 648 | ** current server configuration or by user permissions. |
| @@ -654,15 +655,17 @@ | |
| 654 | { SRCH_CKIN, "search-ci" }, |
| 655 | { SRCH_DOC, "search-doc" }, |
| 656 | { SRCH_TKT, "search-tkt" }, |
| 657 | { SRCH_WIKI, "search-wiki" }, |
| 658 | { SRCH_TECHNOTE, "search-technote" }, |
| 659 | }; |
| 660 | int i; |
| 661 | if( g.perm.Read==0 ) srchFlags &= ~(SRCH_CKIN|SRCH_DOC|SRCH_TECHNOTE); |
| 662 | if( g.perm.RdTkt==0 ) srchFlags &= ~(SRCH_TKT); |
| 663 | if( g.perm.RdWiki==0 ) srchFlags &= ~(SRCH_WIKI); |
| 664 | for(i=0; i<count(aSetng); i++){ |
| 665 | unsigned int m = aSetng[i].m; |
| 666 | if( (srchFlags & m)==0 ) continue; |
| 667 | if( ((knownGood|knownBad) & m)!=0 ) continue; |
| 668 | if( db_get_boolean(aSetng[i].zKey,0) ){ |
| @@ -793,10 +796,23 @@ | |
| 793 | " search_snippet()" |
| 794 | " FROM technote" |
| 795 | " WHERE search_match('',body('e',rid,NULL));" |
| 796 | ); |
| 797 | } |
| 798 | } |
| 799 | |
| 800 | /* |
| 801 | ** Number of significant bits in a u32 |
| 802 | */ |
| @@ -913,10 +929,11 @@ | |
| 913 | { SRCH_CKIN, 'c' }, |
| 914 | { SRCH_DOC, 'd' }, |
| 915 | { SRCH_TKT, 't' }, |
| 916 | { SRCH_WIKI, 'w' }, |
| 917 | { SRCH_TECHNOTE, 'e' }, |
| 918 | }; |
| 919 | int i; |
| 920 | for(i=0; i<count(aMask); i++){ |
| 921 | if( srchFlags & aMask[i].m ){ |
| 922 | blob_appendf(&sql, "%sftsdocs.type='%c'", zSep, aMask[i].c); |
| @@ -1066,10 +1083,11 @@ | |
| 1066 | case SRCH_CKIN: zType = " Check-ins"; zClass = "Ckin"; break; |
| 1067 | case SRCH_DOC: zType = " Docs"; zClass = "Doc"; break; |
| 1068 | case SRCH_TKT: zType = " Tickets"; zClass = "Tkt"; break; |
| 1069 | case SRCH_WIKI: zType = " Wiki"; zClass = "Wiki"; break; |
| 1070 | case SRCH_TECHNOTE: zType = " Tech Notes"; zClass = "Note"; break; |
| 1071 | } |
| 1072 | if( srchFlags==0 ){ |
| 1073 | zDisable1 = " disabled"; |
| 1074 | zDisable2 = " disabled"; |
| 1075 | zPattern = ""; |
| @@ -1091,10 +1109,11 @@ | |
| 1091 | { "c", "Check-ins", SRCH_CKIN }, |
| 1092 | { "d", "Docs", SRCH_DOC }, |
| 1093 | { "t", "Tickets", SRCH_TKT }, |
| 1094 | { "w", "Wiki", SRCH_WIKI }, |
| 1095 | { "e", "Tech Notes", SRCH_TECHNOTE }, |
| 1096 | }; |
| 1097 | const char *zY = PD("y","all"); |
| 1098 | unsigned newFlags = srchFlags; |
| 1099 | int i; |
| 1100 | @ <select size='1' name='y'> |
| @@ -1143,10 +1162,11 @@ | |
| 1143 | ** c -> check-ins |
| 1144 | ** d -> documentation |
| 1145 | ** t -> tickets |
| 1146 | ** w -> wiki |
| 1147 | ** e -> tech notes |
| 1148 | ** all -> everything |
| 1149 | */ |
| 1150 | void search_page(void){ |
| 1151 | login_check_credentials(); |
| 1152 | style_header("Search"); |
| @@ -1250,10 +1270,11 @@ | |
| 1250 | ** cType: d Embedded documentation |
| 1251 | ** w Wiki page |
| 1252 | ** c Check-in comment |
| 1253 | ** t Ticket text |
| 1254 | ** e Tech note |
| 1255 | ** |
| 1256 | ** rid The RID of an artifact that defines the object |
| 1257 | ** being searched. |
| 1258 | ** |
| 1259 | ** zName Name of the object being searched. This is used |
| @@ -1275,17 +1296,27 @@ | |
| 1275 | blob_to_utf8_no_bom(&doc, 0); |
| 1276 | get_stext_by_mimetype(&doc, mimetype_from_name(zName), pOut); |
| 1277 | blob_reset(&doc); |
| 1278 | break; |
| 1279 | } |
| 1280 | case 'e': /* Tech Notes */ |
| 1281 | case 'w': { /* Wiki */ |
| 1282 | Manifest *pWiki = manifest_get(rid, |
| 1283 | cType == 'e' ? CFTYPE_EVENT : CFTYPE_WIKI, 0); |
| 1284 | Blob wiki; |
| 1285 | if( pWiki==0 ) break; |
| 1286 | blob_init(&wiki, pWiki->zWiki, -1); |
| 1287 | get_stext_by_mimetype(&wiki, wiki_filter_mimetypes(pWiki->zMimetype), |
| 1288 | pOut); |
| 1289 | blob_reset(&wiki); |
| 1290 | manifest_destroy(pWiki); |
| 1291 | break; |
| @@ -1516,11 +1547,11 @@ | |
| 1516 | "INSERT OR IGNORE INTO ftsdocs(type,rid,idxed)" |
| 1517 | " SELECT 't', tkt_id, 0 FROM ticket;" |
| 1518 | ); |
| 1519 | db_multi_exec( |
| 1520 | "INSERT OR IGNORE INTO ftsdocs(type,rid,name,idxed)" |
| 1521 | " SELECT 'e', objid, comment, 0 FROM event WHERE type='e';" |
| 1522 | ); |
| 1523 | } |
| 1524 | |
| 1525 | /* |
| 1526 | ** The document described by cType,rid,zName is about to be added or |
| @@ -1553,10 +1584,11 @@ | |
| 1553 | db_multi_exec( |
| 1554 | "DELETE FROM ftsdocs WHERE type='%c' AND name=%Q AND rid!=%d", |
| 1555 | cType, zName, rid |
| 1556 | ); |
| 1557 | } |
| 1558 | } |
| 1559 | } |
| 1560 | |
| 1561 | /* |
| 1562 | ** If the doc-glob and doc-br settings are valid for document search |
| @@ -1681,10 +1713,33 @@ | |
| 1681 | " tagxref.mtime" |
| 1682 | " FROM tagxref WHERE tagxref.rid=ftsdocs.rid)" |
| 1683 | " WHERE ftsdocs.type='w' AND NOT ftsdocs.idxed" |
| 1684 | ); |
| 1685 | } |
| 1686 | |
| 1687 | /* |
| 1688 | ** Deal with all of the unindexed 'e' terms in FTSDOCS |
| 1689 | */ |
| 1690 | static void search_update_technote_index(void){ |
| @@ -1728,10 +1783,13 @@ | |
| 1728 | search_update_wiki_index(); |
| 1729 | } |
| 1730 | if( srchFlags & SRCH_TECHNOTE ){ |
| 1731 | search_update_technote_index(); |
| 1732 | } |
| 1733 | } |
| 1734 | |
| 1735 | /* |
| 1736 | ** Construct, prepopulate, and then update the full-text index. |
| 1737 | */ |
| @@ -1780,10 +1838,11 @@ | |
| 1780 | { "search-ci", "check-in search:", "c" }, |
| 1781 | { "search-doc", "document search:", "d" }, |
| 1782 | { "search-tkt", "ticket search:", "t" }, |
| 1783 | { "search-wiki", "wiki search:", "w" }, |
| 1784 | { "search-technote", "tech note search:", "e" }, |
| 1785 | }; |
| 1786 | char *zSubCmd = 0; |
| 1787 | int i, j, n; |
| 1788 | int iCmd = 0; |
| 1789 | int iAction = 0; |
| 1790 |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -638,11 +638,12 @@ | |
| 638 | #define SRCH_CKIN 0x0001 /* Search over check-in comments */ |
| 639 | #define SRCH_DOC 0x0002 /* Search over embedded documents */ |
| 640 | #define SRCH_TKT 0x0004 /* Search over tickets */ |
| 641 | #define SRCH_WIKI 0x0008 /* Search over wiki */ |
| 642 | #define SRCH_TECHNOTE 0x0010 /* Search over tech notes */ |
| 643 | #define SRCH_FORUM 0x0020 /* Search over forum messages */ |
| 644 | #define SRCH_ALL 0x003f /* Search over everything */ |
| 645 | #endif |
| 646 | |
| 647 | /* |
| 648 | ** Remove bits from srchFlags which are disallowed by either the |
| 649 | ** current server configuration or by user permissions. |
| @@ -654,15 +655,17 @@ | |
| 655 | { SRCH_CKIN, "search-ci" }, |
| 656 | { SRCH_DOC, "search-doc" }, |
| 657 | { SRCH_TKT, "search-tkt" }, |
| 658 | { SRCH_WIKI, "search-wiki" }, |
| 659 | { SRCH_TECHNOTE, "search-technote" }, |
| 660 | { SRCH_FORUM, "search-forum" }, |
| 661 | }; |
| 662 | int i; |
| 663 | if( g.perm.Read==0 ) srchFlags &= ~(SRCH_CKIN|SRCH_DOC|SRCH_TECHNOTE); |
| 664 | if( g.perm.RdTkt==0 ) srchFlags &= ~(SRCH_TKT); |
| 665 | if( g.perm.RdWiki==0 ) srchFlags &= ~(SRCH_WIKI); |
| 666 | if( g.perm.RdForum==0) srchFlags &= ~(SRCH_FORUM); |
| 667 | for(i=0; i<count(aSetng); i++){ |
| 668 | unsigned int m = aSetng[i].m; |
| 669 | if( (srchFlags & m)==0 ) continue; |
| 670 | if( ((knownGood|knownBad) & m)!=0 ) continue; |
| 671 | if( db_get_boolean(aSetng[i].zKey,0) ){ |
| @@ -793,10 +796,23 @@ | |
| 796 | " search_snippet()" |
| 797 | " FROM technote" |
| 798 | " WHERE search_match('',body('e',rid,NULL));" |
| 799 | ); |
| 800 | } |
| 801 | if( (srchFlags & SRCH_FORUM)!=0 ){ |
| 802 | db_multi_exec( |
| 803 | "INSERT INTO x(label,url,score,id,date,snip)" |
| 804 | " SELECT 'Forum '||comment," |
| 805 | " '/forumpost/'||uuid," |
| 806 | " search_score()," |
| 807 | " 'f'||rid," |
| 808 | " datetime(event.mtime)," |
| 809 | " search_snippet()" |
| 810 | " FROM event JOIN blob on event.objid=blob.rid" |
| 811 | " WHERE search_match('',body('f',rid,NULL));" |
| 812 | ); |
| 813 | } |
| 814 | } |
| 815 | |
| 816 | /* |
| 817 | ** Number of significant bits in a u32 |
| 818 | */ |
| @@ -913,10 +929,11 @@ | |
| 929 | { SRCH_CKIN, 'c' }, |
| 930 | { SRCH_DOC, 'd' }, |
| 931 | { SRCH_TKT, 't' }, |
| 932 | { SRCH_WIKI, 'w' }, |
| 933 | { SRCH_TECHNOTE, 'e' }, |
| 934 | { SRCH_FORUM, 'f' }, |
| 935 | }; |
| 936 | int i; |
| 937 | for(i=0; i<count(aMask); i++){ |
| 938 | if( srchFlags & aMask[i].m ){ |
| 939 | blob_appendf(&sql, "%sftsdocs.type='%c'", zSep, aMask[i].c); |
| @@ -1066,10 +1083,11 @@ | |
| 1083 | case SRCH_CKIN: zType = " Check-ins"; zClass = "Ckin"; break; |
| 1084 | case SRCH_DOC: zType = " Docs"; zClass = "Doc"; break; |
| 1085 | case SRCH_TKT: zType = " Tickets"; zClass = "Tkt"; break; |
| 1086 | case SRCH_WIKI: zType = " Wiki"; zClass = "Wiki"; break; |
| 1087 | case SRCH_TECHNOTE: zType = " Tech Notes"; zClass = "Note"; break; |
| 1088 | case SRCH_FORUM: zType = " Forum"; zClass = "Frm"; break; |
| 1089 | } |
| 1090 | if( srchFlags==0 ){ |
| 1091 | zDisable1 = " disabled"; |
| 1092 | zDisable2 = " disabled"; |
| 1093 | zPattern = ""; |
| @@ -1091,10 +1109,11 @@ | |
| 1109 | { "c", "Check-ins", SRCH_CKIN }, |
| 1110 | { "d", "Docs", SRCH_DOC }, |
| 1111 | { "t", "Tickets", SRCH_TKT }, |
| 1112 | { "w", "Wiki", SRCH_WIKI }, |
| 1113 | { "e", "Tech Notes", SRCH_TECHNOTE }, |
| 1114 | { "f", "Forum", SRCH_FORUM }, |
| 1115 | }; |
| 1116 | const char *zY = PD("y","all"); |
| 1117 | unsigned newFlags = srchFlags; |
| 1118 | int i; |
| 1119 | @ <select size='1' name='y'> |
| @@ -1143,10 +1162,11 @@ | |
| 1162 | ** c -> check-ins |
| 1163 | ** d -> documentation |
| 1164 | ** t -> tickets |
| 1165 | ** w -> wiki |
| 1166 | ** e -> tech notes |
| 1167 | ** f -> forum |
| 1168 | ** all -> everything |
| 1169 | */ |
| 1170 | void search_page(void){ |
| 1171 | login_check_credentials(); |
| 1172 | style_header("Search"); |
| @@ -1250,10 +1270,11 @@ | |
| 1270 | ** cType: d Embedded documentation |
| 1271 | ** w Wiki page |
| 1272 | ** c Check-in comment |
| 1273 | ** t Ticket text |
| 1274 | ** e Tech note |
| 1275 | ** f Forum |
| 1276 | ** |
| 1277 | ** rid The RID of an artifact that defines the object |
| 1278 | ** being searched. |
| 1279 | ** |
| 1280 | ** zName Name of the object being searched. This is used |
| @@ -1275,17 +1296,27 @@ | |
| 1296 | blob_to_utf8_no_bom(&doc, 0); |
| 1297 | get_stext_by_mimetype(&doc, mimetype_from_name(zName), pOut); |
| 1298 | blob_reset(&doc); |
| 1299 | break; |
| 1300 | } |
| 1301 | case 'f': /* Forum messages */ |
| 1302 | case 'e': /* Tech Notes */ |
| 1303 | case 'w': { /* Wiki */ |
| 1304 | Manifest *pWiki = manifest_get(rid, |
| 1305 | cType == 'e' ? CFTYPE_EVENT : |
| 1306 | cType == 'f' ? CFTYPE_FORUM : CFTYPE_WIKI, 0); |
| 1307 | Blob wiki; |
| 1308 | if( pWiki==0 ) break; |
| 1309 | if( cType=='f' ){ |
| 1310 | blob_init(&wiki, 0, 0); |
| 1311 | if( pWiki->zThreadTitle ){ |
| 1312 | blob_appendf(&wiki, "<h1>%h</h1>\n", pWiki->zThreadTitle); |
| 1313 | } |
| 1314 | blob_appendf(&wiki, "From %s:\n\n%s", pWiki->zUser, pWiki->zWiki); |
| 1315 | }else{ |
| 1316 | blob_init(&wiki, pWiki->zWiki, -1); |
| 1317 | } |
| 1318 | get_stext_by_mimetype(&wiki, wiki_filter_mimetypes(pWiki->zMimetype), |
| 1319 | pOut); |
| 1320 | blob_reset(&wiki); |
| 1321 | manifest_destroy(pWiki); |
| 1322 | break; |
| @@ -1516,11 +1547,11 @@ | |
| 1547 | "INSERT OR IGNORE INTO ftsdocs(type,rid,idxed)" |
| 1548 | " SELECT 't', tkt_id, 0 FROM ticket;" |
| 1549 | ); |
| 1550 | db_multi_exec( |
| 1551 | "INSERT OR IGNORE INTO ftsdocs(type,rid,name,idxed)" |
| 1552 | " SELECT type, objid, comment, 0 FROM event WHERE type IN ('e','f');" |
| 1553 | ); |
| 1554 | } |
| 1555 | |
| 1556 | /* |
| 1557 | ** The document described by cType,rid,zName is about to be added or |
| @@ -1553,10 +1584,11 @@ | |
| 1584 | db_multi_exec( |
| 1585 | "DELETE FROM ftsdocs WHERE type='%c' AND name=%Q AND rid!=%d", |
| 1586 | cType, zName, rid |
| 1587 | ); |
| 1588 | } |
| 1589 | /* All forum posts are always indexed */ |
| 1590 | } |
| 1591 | } |
| 1592 | |
| 1593 | /* |
| 1594 | ** If the doc-glob and doc-br settings are valid for document search |
| @@ -1681,10 +1713,33 @@ | |
| 1713 | " tagxref.mtime" |
| 1714 | " FROM tagxref WHERE tagxref.rid=ftsdocs.rid)" |
| 1715 | " WHERE ftsdocs.type='w' AND NOT ftsdocs.idxed" |
| 1716 | ); |
| 1717 | } |
| 1718 | |
| 1719 | /* |
| 1720 | ** Deal with all of the unindexed 'f' terms in FTSDOCS |
| 1721 | */ |
| 1722 | static void search_update_forum_index(void){ |
| 1723 | db_multi_exec( |
| 1724 | "INSERT INTO ftsidx(docid,title,body)" |
| 1725 | " SELECT rowid, title('f',rid,NULL),body('f',rid,NULL) FROM ftsdocs" |
| 1726 | " WHERE type='f' AND NOT idxed;" |
| 1727 | ); |
| 1728 | if( db_changes()==0 ) return; |
| 1729 | db_multi_exec( |
| 1730 | "UPDATE ftsdocs SET idxed=1, name=NULL," |
| 1731 | " (label,url,mtime) = " |
| 1732 | " (SELECT 'Forum '||event.comment," |
| 1733 | " '/forumpost/'||blob.uuid," |
| 1734 | " event.mtime" |
| 1735 | " FROM event, blob" |
| 1736 | " WHERE event.objid=ftsdocs.rid" |
| 1737 | " AND blob.rid=ftsdocs.rid)" |
| 1738 | "WHERE ftsdocs.type='f' AND NOT ftsdocs.idxed" |
| 1739 | ); |
| 1740 | } |
| 1741 | |
| 1742 | /* |
| 1743 | ** Deal with all of the unindexed 'e' terms in FTSDOCS |
| 1744 | */ |
| 1745 | static void search_update_technote_index(void){ |
| @@ -1728,10 +1783,13 @@ | |
| 1783 | search_update_wiki_index(); |
| 1784 | } |
| 1785 | if( srchFlags & SRCH_TECHNOTE ){ |
| 1786 | search_update_technote_index(); |
| 1787 | } |
| 1788 | if( srchFlags & SRCH_FORUM ){ |
| 1789 | search_update_forum_index(); |
| 1790 | } |
| 1791 | } |
| 1792 | |
| 1793 | /* |
| 1794 | ** Construct, prepopulate, and then update the full-text index. |
| 1795 | */ |
| @@ -1780,10 +1838,11 @@ | |
| 1838 | { "search-ci", "check-in search:", "c" }, |
| 1839 | { "search-doc", "document search:", "d" }, |
| 1840 | { "search-tkt", "ticket search:", "t" }, |
| 1841 | { "search-wiki", "wiki search:", "w" }, |
| 1842 | { "search-technote", "tech note search:", "e" }, |
| 1843 | { "search-forum", "forum search:", "f" }, |
| 1844 | }; |
| 1845 | char *zSubCmd = 0; |
| 1846 | int i, j, n; |
| 1847 | int iCmd = 0; |
| 1848 | int iAction = 0; |
| 1849 |
+2
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -2233,10 +2233,12 @@ | ||
| 2233 | 2233 | onoff_attribute("Search Tickets", "search-tkt", "st", 0, 0); |
| 2234 | 2234 | @ <br /> |
| 2235 | 2235 | onoff_attribute("Search Wiki", "search-wiki", "sw", 0, 0); |
| 2236 | 2236 | @ <br /> |
| 2237 | 2237 | onoff_attribute("Search Tech Notes", "search-technote", "se", 0, 0); |
| 2238 | + @ <br /> | |
| 2239 | + onoff_attribute("Search Forum", "search-forum", "sf", 0, 0); | |
| 2238 | 2240 | @ <hr /> |
| 2239 | 2241 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 2240 | 2242 | @ <hr /> |
| 2241 | 2243 | if( P("fts0") ){ |
| 2242 | 2244 | search_drop_index(); |
| 2243 | 2245 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -2233,10 +2233,12 @@ | |
| 2233 | onoff_attribute("Search Tickets", "search-tkt", "st", 0, 0); |
| 2234 | @ <br /> |
| 2235 | onoff_attribute("Search Wiki", "search-wiki", "sw", 0, 0); |
| 2236 | @ <br /> |
| 2237 | onoff_attribute("Search Tech Notes", "search-technote", "se", 0, 0); |
| 2238 | @ <hr /> |
| 2239 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 2240 | @ <hr /> |
| 2241 | if( P("fts0") ){ |
| 2242 | search_drop_index(); |
| 2243 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -2233,10 +2233,12 @@ | |
| 2233 | onoff_attribute("Search Tickets", "search-tkt", "st", 0, 0); |
| 2234 | @ <br /> |
| 2235 | onoff_attribute("Search Wiki", "search-wiki", "sw", 0, 0); |
| 2236 | @ <br /> |
| 2237 | onoff_attribute("Search Tech Notes", "search-technote", "se", 0, 0); |
| 2238 | @ <br /> |
| 2239 | onoff_attribute("Search Forum", "search-forum", "sf", 0, 0); |
| 2240 | @ <hr /> |
| 2241 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 2242 | @ <hr /> |
| 2243 | if( P("fts0") ){ |
| 2244 | search_drop_index(); |
| 2245 |