/// <summary> /// Executes the search using the currently entered text /// </summary> private void LaunchSearch(bool interactive) { if (indexes.Count == 0) { return; } searchStatusLabel.Text = String.Format(Properties.Resources.SearchingForTerm, searchBox.Text); searchLaunched = true; searchIdentifier++; if (!interactive) { SearchItem si = new SearchItem(); si.SearchIdentifier = searchIdentifier; si.SearchText = searchBox.Text; ThreadPool.QueueUserWorkItem(BackgroundSearch, si); return; } HitCollection hits = Indexer.Search(searchBox.Text, indexes.Values, Indexer.MAX_SEARCH_HITS); searchStatusLabel.Text = String.Empty; if (String.IsNullOrEmpty(hits.ErrorMessages)) { loadingResults = true; hitsBox.DataSource = hits; hitsBox.SelectedItem = null; loadingResults = false; if (hits.HadMoreHits) { searchStatusLabel.Text = String.Format(Properties.Resources.ShowingXTopResults, Indexer.MAX_SEARCH_HITS.ToString()); } if (hits.Count > 0) { hitsBox.SetSelected(0, true); PageInfo page = hitsBox.SelectedItem as PageInfo; webBrowser.Navigate(WebServer.Instance.GenerateUrl(page)); } } else { MessageBox.Show(this, hits.ErrorMessages, Properties.Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error); } }
/// <summary> /// Gets called whenever the browser control requests a URL from the web server /// </summary> /// <param name="sender">Web server instance</param> /// <param name="e">Request parameters</param> private void Web_UrlRequested(object sender, UrlRequestedEventArgs e) { string response = "Not found"; string redirect = String.Empty; if (!String.IsNullOrEmpty(e.TeXEquation)) { return; } string topic = e.TopicName.Replace('_', ' ').Trim(); if (topic.Contains("#")) { topic = topic.Substring(0, topic.IndexOf('#')).Trim(); } PageInfo page = hitsBox.SelectedItem as PageInfo; if (page != null && topic.Equals(page.Name, StringComparison.InvariantCultureIgnoreCase) && e.IndexName.Equals(page.Indexer.File, StringComparison.InvariantCultureIgnoreCase) && !IsCircularRedirect(page)) { response = page.GetFormattedContent(); redirect = page.RedirectToTopic; } else { List <Indexer> searchArea = new List <Indexer>(); // This is an internal link if (String.IsNullOrEmpty(e.IndexName)) { if (page != null) { searchArea.Add(page.Indexer); } else { foreach (Indexer ixr in indexes.Values) { searchArea.Add(ixr); } } } else { foreach (Indexer ixr in indexes.Values) { if (ixr.File.Equals(e.IndexName, StringComparison.InvariantCultureIgnoreCase)) { searchArea.Add(ixr); break; } } } if (searchArea.Count > 0) { HitCollection hits = Indexer.Search(topic, searchArea, 100); bool exactTopicLocated = false; foreach (PageInfo pi in hits) { if (pi.Name.Trim().Equals(topic, StringComparison.InvariantCultureIgnoreCase) && !IsCircularRedirect(pi)) { response = pi.GetFormattedContent(); redirect = pi.RedirectToTopic; exactTopicLocated = true; break; } } if (hits.Count > 0 && !exactTopicLocated) { foreach (PageInfo pi in hits) { if (String.IsNullOrEmpty(pi.RedirectToTopic)) { response = pi.GetFormattedContent(); redirect = pi.RedirectToTopic; exactTopicLocated = true; break; } } if (!exactTopicLocated) { foreach (PageInfo pi in hits) { if (!IsCircularRedirect(pi)) { response = pi.GetFormattedContent(); redirect = pi.RedirectToTopic; break; } } } } } } e.Redirect = !String.IsNullOrEmpty(redirect); e.RedirectTarget = redirect; e.Response = Encoding.UTF8.GetBytes(response); e.MimeType = "text/html"; if (String.IsNullOrEmpty(redirect)) { autoRedirects.Clear(); } else { autoRedirects.Push(redirect); } }
/// <summary> /// Searches for the specified term in the index. /// </summary> /// <param name="term">The term.</param> public static HitCollection Search(string term, IEnumerable <Indexer> indexers, int maxResults) { foreach (Indexer ixr in indexers) { if (!ixr.IndexExists || ixr.Searcher == null) { throw new Exception(String.Format(Properties.Resources.IndexDoesNotExist, ixr.FilePath)); } } string searchRequest = String.Format("title:\"{0}\" AND -\"Image:\"", term); HitCollection ret = new HitCollection(); SearchItem si = new SearchItem(); si.Hits = ret; si.SearchRequest = searchRequest; si.MaxResults = maxResults; si.Errors = new Queue <Exception>(); int indexersNumber = 0; // I can't really be sure about the thread safety of Lucene try { lock (typeof(Indexer)) { foreach (Indexer ixr in indexers) { indexersNumber++; int i = 0; while (ixr.searchRunning && i < 30) { Thread.Sleep(100); i++; } if (i >= 30) { throw new Exception(Properties.Resources.FailedStartingSearch); } ixr.searchRunning = true; } foreach (Indexer ixr in indexers) { ThreadPool.QueueUserWorkItem(ixr.Search, si); } foreach (Indexer ixr in indexers) { int i = 0; while (ixr.searchRunning && i < 30) { Thread.Sleep(100); i++; } if (i >= 30) { throw new Exception(Properties.Resources.FailedFinishingSearch); } } } } catch (Exception ex) { lock (si.Errors) { si.Errors.Enqueue(ex); } } StringCollection sc = new StringCollection(); lock (si.Errors) { while (si.Errors.Count > 0) { Exception ex = si.Errors.Dequeue(); if (!sc.Contains(ex.Message)) { sc.Add(ex.Message); } } } StringBuilder sb = new StringBuilder(); foreach (string message in sc) { sb.AppendLine(message); } ret.ErrorMessages = sb.Length > 0 ? sb.ToString() : String.Empty; if (indexersNumber > 1) { PageInfo[] arr = new PageInfo[ret.Count]; for (int i = 0; i < ret.Count; i++) { arr[i] = ret[i]; } Array.Sort <PageInfo>(arr, delegate(PageInfo a, PageInfo b) { return(a.Score < b.Score ? 1 : (a.Score > b.Score ? -1 : 0)); }); ret.Clear(); foreach (PageInfo pi in arr) { ret.Add(pi); } } return(ret); }