Changes On Branch exp-search
Not logged in

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

Changes In Branch exp-search Excluding Merge-Ins

This is equivalent to a diff from 3343450e64 to 0fd61810c4

2010-06-10
19:19
Change the title of the home page from "Fossil Home Page" to simply "Home Page". Leaf check-in: 0fd61810c4 user: drh tags: exp-search
18:50
Use the qoute() function to encode setting value for the "configure export" command. This allows the binary logo image to be exported. check-in: 59fcfb777d user: drh tags: exp-search
2010-05-22
11:28
Fix memory leaks associated with the cgi_rfc822_datestamp() function. check-in: 99dcff4d28 user: drh tags: trunk
2010-05-21
21:05
adding code, wiki, tickets, checkins search functionality check-in: 73d274360c user: Zach tags: exp-search
16:21
Fix issues with attachments on tickets. In the artifact viewer, do a better job of detecting JPEG images from the content prefix. check-in: 3343450e64 user: drh tags: trunk, release
15:16
Fix an unterminated string in the information viewer for attachments. check-in: 65d2067247 user: drh tags: trunk

Changes to src/configure.c.

   346    346       db_text(0, "SELECT datetime('now')")
   347    347     );
   348    348     for(i=0; i<count(aConfig); i++){
   349    349       if( (aConfig[i].groupMask & mask)!=0 ){
   350    350         const char *zName = aConfig[i].zName;
   351    351         if( zName[0]!='@' ){
   352    352           char *zValue = db_text(0, 
   353         -            "SELECT value FROM config WHERE name=%Q", zName);
          353  +            "SELECT quote(value) FROM config WHERE name=%Q", zName);
   354    354           if( zValue ){
   355         -          blob_appendf(&out,"REPLACE INTO config VALUES(%Q,%Q);\n", 
          355  +          blob_appendf(&out,"REPLACE INTO config VALUES(%Q,%s);\n", 
   356    356                          zName, zValue);
   357    357           }
   358    358           free(zValue);
   359    359         }else{
   360    360           configure_render_special_name(zName, &out);
   361    361         }
   362    362       }

Changes to src/db.c.

  1059   1059     int argc,
  1060   1060     sqlite3_value **argv
  1061   1061   ){
  1062   1062     if( g.zLogin!=0 ){
  1063   1063       sqlite3_result_text(context, g.zLogin, -1, SQLITE_STATIC);
  1064   1064     }
  1065   1065   }
         1066  +
         1067  +/*
         1068  +** Make the content_get function available within a SQL query.
         1069  +*/
         1070  +static void db_sql_content_get(
         1071  +  sqlite3_context *context,
         1072  +  int argc,
         1073  +  sqlite3_value **argv
         1074  +){
         1075  +  int rid;
         1076  +  Blob content;
         1077  +  
         1078  +  if( argc != 1 ) return;
         1079  +  rid = sqlite3_value_int(argv[0]);
         1080  +  content_get(rid, &content);
         1081  +  sqlite3_result_text(context, blob_str(&content), -1, SQLITE_TRANSIENT);
         1082  +}
         1083  +
         1084  +/*
         1085  +** Retrieve the most recent revision ID of a file.
         1086  +*/
         1087  +static void db_sql_get_file_rid(
         1088  +  sqlite3_context *context,
         1089  +  int argc,
         1090  +  sqlite3_value **argv
         1091  +){
         1092  +  const unsigned char *fnid;
         1093  +  int rid;
         1094  +  Stmt q;
         1095  +  
         1096  +  if ( argc != 1 ) return;
         1097  +  fnid = sqlite3_value_text(argv[0]);
         1098  +  
         1099  +  db_prepare(&q, "SELECT fid FROM mlink WHERE fnid=%Q and mid= "
         1100  +                 "(SELECT objid FROM (SELECT objid, mtime FROM event WHERE objid IN "
         1101  +                 "(SELECT mid FROM mlink WHERE fnid=%Q) "
         1102  +                 "ORDER BY mtime DESC) LIMIT 1);", fnid, fnid);
         1103  +  
         1104  +  db_step(&q);
         1105  +  rid = db_column_int(&q, 0);
         1106  +  sqlite3_result_int(context, rid);
         1107  +  db_finalize(&q);
         1108  +}
         1109  +
         1110  +/*
         1111  +** Retrieve the most recent revision ID of a wiki entry.
         1112  +*/
         1113  +static void db_sql_get_wiki_rid(
         1114  +  sqlite3_context *context,
         1115  +  int argc,
         1116  +  sqlite3_value **argv
         1117  +){
         1118  +  const unsigned char *tagid;
         1119  +  int rid;
         1120  +  Stmt q;
         1121  +  
         1122  +  if ( argc != 1 ) return;
         1123  +  tagid = sqlite3_value_text(argv[0]);
         1124  +  
         1125  +  db_prepare(&q, "SELECT rid FROM tagxref WHERE tagid=%Q ORDER BY mtime DESC LIMIT 1", tagid);    
         1126  +  db_step(&q);
         1127  +  rid = db_column_int(&q, 0);
         1128  +  sqlite3_result_int(context, rid);
         1129  +  db_finalize(&q);
         1130  +}
  1066   1131   
  1067   1132   /*
  1068   1133   ** Implement the cgi() SQL function.  cgi() takes a an argument which is
  1069   1134   ** a name of CGI query parameter. The value of that parameter is returned, 
  1070   1135   ** if available. optional second argument will be returned if the first
  1071   1136   ** doesn't exist as a CGI parameter.
  1072   1137   */
................................................................................
  1176   1241   */
  1177   1242   LOCAL void db_connection_init(void){
  1178   1243     sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
  1179   1244     sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
  1180   1245     sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
  1181   1246     sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
  1182   1247     sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
         1248  +  sqlite3_create_function(g.db, "content_get", 1, SQLITE_ANY, 0, db_sql_content_get, 0, 0);
         1249  +  sqlite3_create_function(g.db, "get_file_rid", 1, SQLITE_ANY, 0, db_sql_get_file_rid, 0, 0);
         1250  +  sqlite3_create_function(g.db, "get_wiki_rid", 1, SQLITE_ANY, 0, db_sql_get_wiki_rid, 0, 0);  
  1183   1251     sqlite3_create_function(
  1184   1252       g.db, "file_is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
  1185   1253     );
  1186   1254     if( g.fSqlTrace ){
  1187   1255       sqlite3_trace(g.db, db_sql_trace, 0);
  1188   1256     }
  1189   1257   }

Changes to src/search.c.

   104    104   int search_score(Search *p, const char *zDoc){
   105    105     int iPrev = 999;
   106    106     int score = 10;
   107    107     int iBonus = 0;
   108    108     int i, j;
   109    109     unsigned char seen[8];
   110    110   
          111  +  if (zDoc == 0) return 0; 
   111    112     memset(seen, 0, sizeof(seen));
   112    113     for(i=0; zDoc[i]; i++){
   113    114       char c = zDoc[i];
   114    115       if( isBoundary[c&0xff] ) continue;
   115    116       for(j=0; j<p->nTerm; j++){
   116    117         int n = p->a[j].n;
   117    118         if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){
................................................................................
   160    161   ** using the given Search object.  Once this function is registered,
   161    162   ** do not delete the Search object.
   162    163   */
   163    164   void search_sql_setup(Search *p){
   164    165     sqlite3_create_function(g.db, "score", 1, SQLITE_UTF8, p,
   165    166        search_score_sqlfunc, 0, 0);
   166    167   }
          168  +
          169  +/*
          170  +** WEBPAGE: search
          171  +** URL: /search
          172  +*/
          173  +void search(void){
          174  +  const char *zType;
          175  +  const char *zSrchType;
          176  +  const char *zTitle;
          177  +  const char *zContent;
          178  +  const char *zSrch;
          179  +  const char *zUuid;
          180  +  const char *zRid;
          181  +  char zrn[4];
          182  +  char zshUuid[10];
          183  +  int zScore;
          184  +  int zSrchTypeFlag;
          185  +  
          186  +  Search *zSrchpat;
          187  +  Stmt q;
          188  +  
          189  +  zSrch = PD("search", "");
          190  +  zSrchType = PD("type", "");
          191  +  zSrchpat = search_init(zSrch);
          192  +  search_sql_setup(zSrchpat);
          193  +  
          194  +  login_check_credentials();
          195  +  
          196  +  if( !g.okHistory ){ login_needed(); return; }
          197  +  
          198  +  db_prepare(&q, "SELECT type, rid, title, content, score(content) AS score FROM "
          199  +                 "                                                                         "
          200  +                 "(SELECT 'checkin' AS type, objid AS rid, coalesce(ecomment, comment) AS title, "
          201  +                 "coalesce(ecomment, comment) AS content FROM event WHERE type='ci' UNION ALL "
          202  +                 "SELECT 'code' AS type, rid, title, content FROM "
          203  +                 "(SELECT title, rid, content_get(rid) as content FROM "
          204  +                 "(SELECT name AS title, get_file_rid(fnid) AS rid FROM "
          205  +                 "(SELECT name, fnid FROM filename))) UNION ALL "
          206  +                 "                                                                         "
          207  +                 "SELECT 'ticket' AS type, tkt_uuid AS rid, title, coalesce(title, comment) AS content FROM ticket UNION ALL "
          208  +                 "SELECT 'wiki' AS type, rid, SUBSTR(title, 6) AS title, content_get(rid) as content FROM "
          209  +                 "(SELECT tagname AS title, get_wiki_rid(tagid) AS rid FROM "
          210  +                 "(SELECT tagname, tagid FROM tag WHERE tagname LIKE 'wiki-%%')))"
          211  +                 "ORDER BY score DESC;");  
          212  +  
          213  +  zSrchTypeFlag = 0;
          214  +  if (strcmp(zSrchType, "code") == 0)
          215  +    zSrchTypeFlag = 1;
          216  +  else if (strcmp(zSrchType, "tickets") == 0)
          217  +    zSrchTypeFlag = 2;
          218  +  else if (strcmp(zSrchType, "checkins") == 0)
          219  +    zSrchTypeFlag = 3;
          220  +  else if (strcmp(zSrchType, "wiki") == 0)
          221  +    zSrchTypeFlag = 4;
          222  +  
          223  +  style_header("Search");
          224  +  style_submenu_element("Code", "Code", "search?search=%T&type=code", zSrch);
          225  +  style_submenu_element("Tickets", "Tickets", "search?search=%T&type=tickets", zSrch);
          226  +  style_submenu_element("Checkins", "Checkins", "search?search=%T&type=checkins", zSrch);
          227  +  style_submenu_element("Wiki", "Wiki", "search?search=%T&type=wiki", zSrch);
          228  +  @ <table border=1>
          229  +  @ <tr><td>link</td><td>relevance</td><td>title</td><td>type</td></tr>
          230  +  while (db_step(&q) == SQLITE_ROW){
          231  +    zType = db_column_text(&q, 0);
          232  +    zRid = db_column_text(&q, 1);
          233  +    zTitle = db_column_text(&q, 2);
          234  +    zContent = db_column_text(&q, 3); 
          235  +    zScore = db_column_int(&q, 4);
          236  +    
          237  +    sprintf(zrn, "%i", zScore);
          238  +    if (zScore > 0){
          239  +      if (strcmp(zType, "code") == 0 && (zSrchTypeFlag == 0 || zSrchTypeFlag == 1)){
          240  +        zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%h", zRid);
          241  +        strncpy(zshUuid, zUuid, 10);
          242  +        @ <tr><td><a href='/artifact?name=%h(zUuid)'>%h(zshUuid)</a></td><td>%h(zrn)</td>
          243  +        @ <td>%h(zTitle)</td><td>%h(zType)</td></tr>
          244  +      }
          245  +      else if (strcmp(zType, "ticket") == 0 && (zSrchTypeFlag == 0 || zSrchTypeFlag == 2)){
          246  +        strncpy(zshUuid, zRid, 10);
          247  +        @ <tr><td><a href='/tktview?name=%h(zRid)'>%h(zshUuid)</a></td><td>%h(zrn)</td>
          248  +        @ <td>%h(zTitle)</td><td>%h(zType)</td></tr>
          249  +      }
          250  +      else if (strcmp(zType, "checkin") == 0 && (zSrchTypeFlag == 0 || zSrchTypeFlag == 3)){
          251  +        zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%h", zRid);
          252  +        strncpy(zshUuid, zUuid, 10);
          253  +        @ <tr><td><a href='info/%h(zUuid)'>%h(zshUuid)</a></td><td>%h(zrn)</td>
          254  +        @ <td>%h(zTitle)</td><td>%h(zType)</td></tr>
          255  +      }
          256  +      else if (strcmp(zType, "wiki") == 0 && (zSrchTypeFlag == 0 || zSrchTypeFlag == 4)){
          257  +        @ <tr><td><a href='/wiki?name=%h(zTitle)'>%h(zTitle)</a></td><td>%h(zrn)</td>
          258  +        @ <td>%h(zTitle)</td><td>%h(zType)</td></tr>
          259  +      }
          260  +    }
          261  +  }
          262  +  @ </table>
          263  +  db_finalize(&q);
          264  +  style_footer();
          265  +}
   167    266   
   168    267   /*
   169    268   ** Testing the search function.
   170    269   **
   171    270   ** COMMAND: search
   172    271   ** %fossil search pattern...
   173    272   **

Changes to src/style.c.

   198    198   @      if {[info exists login]} {
   199    199   @        puts "Logged in as $login"
   200    200   @      } else {
   201    201   @        puts "Not logged in"
   202    202   @      }
   203    203   @   </th1></nobr></div>
   204    204   @ </div>
          205  +@ <th1>
          206  +@ if {[hascap h]} {
          207  +@ html "<div class='fullsrch'>"
          208  +@ html " <form action='/search' method='post'>"
          209  +@ html " <input type='text' name='search' size=20/>"
          210  +@ html " <input type='submit' value='Search'/>"
          211  +@ html " </form>"
          212  +@ html "</div>"
          213  +@ }
          214  +@ </th1>
   205    215   @ <div class="mainmenu"><th1>
   206    216   @ html "<a href='$baseurl$index_page'>Home</a> "
   207    217   @ if {[anycap jor]} {
   208    218   @   html "<a href='$baseurl/timeline'>Timeline</a> "
   209    219   @ }
   210    220   @ if {[hascap oh]} {
   211    221   @   html "<a href='$baseurl/dir?ci=tip'>Files</a> "
................................................................................
   288    298   @ }
   289    299   @
   290    300   @ /* The header across the top of the page */
   291    301   @ div.header {
   292    302   @   display: table;
   293    303   @   width: 100%;
   294    304   @ }
          305  +@
          306  +@ /* The search bar displayed at the top of the page */
          307  +@ div.fullsrch {
          308  +@   float: right;
          309  +@   margin: 2px 5px 2px 0px;
          310  +@ }
   295    311   @
   296    312   @ /* The main menu bar that appears at the top of the page beneath
   297    313   @ ** the header */
   298    314   @ div.mainmenu {
   299    315   @   padding: 5px 10px 5px 10px;
   300    316   @   font-size: 0.9em;
   301    317   @   font-weight: bold;

Changes to www/index.wiki.

     1         -<title>Fossil Home Page</title>
            1  +<title>Home Page</title>
     2      2   
     3      3   
     4      4   <p align="center">
     5      5   <font size="5">
     6      6   <b>Fossil:</b>
     7      7   <i>Simple, high-reliability, distributed software configuration management</i>
     8      8   </font>