A hint: This file contains one or more very long lines, so maybe it is better readable using the pure text view mode that shows the contents as wrapped lines within the browser window.
1 <?php 2 // ---------------------------------------------------------------------------- 3 // Zoom Search Engine 7.0 (14/July/2014) 4 // PHP search script 5 // A fast custom website search engine using pre-indexed data files. 6 // Copyright (C) Wrensoft 2000 - 2014 7 // 8 // This script is designed for PHP 4.2+ only. 9 // 10 // NOTE: YOU SHOULD NOT NEED TO MODIFY THIS SCRIPT. If you wish to customize 11 // the appearance of the search page, you should change the contents of the 12 // "search_template.html" file. See chapter 6 of the Users Guide for more 13 // details: http://www.wrensoft.com/zoom/usersguide.html 14 // 15 // IF YOU NEED TO ADD PHP TO THE SEARCH PAGE, see this FAQ: 16 // http://www.wrensoft.com/zoom/support/faq_ssi.html 17 // 18 // zoom@wrensoft.com 19 // http://www.wrensoft.com 20 // ---------------------------------------------------------------------------- 21 22 if(strcmp('4.2.0', phpversion()) > 0) 23 die("This version of the Zoom search script requires PHP 4.2.0 or higher.<br />You are currently using: PHP " . phpversion() . "<br />"); 24 25 $SETTINGSFILE = dirname(__FILE__)."/settings.php"; 26 $WORDMAPFILE = dirname(__FILE__)."/zoom_wordmap.zdat"; 27 $DICTIONARYFILE = dirname(__FILE__)."/zoom_dictionary.zdat"; 28 $PAGEDATAFILE = dirname(__FILE__)."/zoom_pagedata.zdat"; 29 $SPELLINGFILE = dirname(__FILE__)."/zoom_spelling.zdat"; 30 $PAGETEXTFILE = dirname(__FILE__)."/zoom_pagetext.zdat"; 31 $PAGEINFOFILE = dirname(__FILE__)."/zoom_pageinfo.zdat"; 32 $RECOMMENDEDFILE = dirname(__FILE__)."/zoom_recommended.zdat"; 33 $AUTOCOMPLETEFILE = dirname(__FILE__)."/zoom_autocomplete.zdat"; 34 $AUTOCOMPLETE_JSFILE = dirname(__FILE__)."/zoom_autocomplete.js"; 35 $AUTOCOMPLETE_CSSFILE = dirname(__FILE__)."/zoom_autocomplete.css"; 36 $DATEPICKER_JSFILE = dirname(__FILE__)."/zoom_datepicker.js"; 37 38 // Check for dependent files 39 if (!file_exists($SETTINGSFILE) || !file_exists($WORDMAPFILE) || !file_exists($DICTIONARYFILE)) 40 { 41 print("<b>Zoom files missing error:</b> Zoom is missing one or more of the required index data files.<br />Please make sure the generated index files are uploaded to the same path as this search script.<br />"); 42 return; 43 } 44 45 require($SETTINGSFILE); 46 47 if ($Spelling == 1 && !file_exists($SPELLINGFILE)) 48 print("<b>Zoom files missing error:</b> Zoom is missing the 'zoom_spelling.zdat' file required for the Spelling Suggestion feature which has been enabled.<br />"); 49 50 // ---------------------------------------------------------------------------- 51 // Settings 52 // ---------------------------------------------------------------------------- 53 54 // The options available in the dropdown menu for number of results 55 // per page 56 $PerPageOptions = array(10, 20, 50, 100); 57 58 /* 59 // For foreign language support, setlocale may be required on the server for 60 // wildcards and highlighting to work. Uncomment the following lines and specify 61 // the appropriate locale information 62 //if (setlocale(LC_ALL, "ru_RU.cp1251") == false) // for russian 63 // print("Failed to change locale setting or locale setting invalid"); 64 */ 65 66 // Index format information 67 $PAGEDATA_URL = 0; 68 $PAGEDATA_TITLE = 1; 69 $PAGEDATA_DESC = 2; 70 $PAGEDATA_IMG = 3; 71 72 $MaxPageDataLineLen = 5178; 73 74 $METAFIELD_TYPE = 0; 75 $METAFIELD_NAME = 1; 76 $METAFIELD_SHOW = 2; 77 $METAFIELD_FORM = 3; 78 $METAFIELD_METHOD = 4; 79 $METAFIELD_DROPDOWN = 5; 80 81 $METAFIELD_TYPE_NUMERIC = 0; 82 $METAFIELD_TYPE_TEXT = 1; 83 $METAFIELD_TYPE_DROPDOWN = 2; 84 $METAFIELD_TYPE_MULTI = 3; 85 $METAFIELD_TYPE_MONEY = 4; 86 87 $METAFIELD_METHOD_EXACT = 0; 88 $METAFIELD_METHOD_LESSTHAN = 1; 89 $METAFIELD_METHOD_LESSTHANORE = 2; 90 $METAFIELD_METHOD_GREATERTHAN = 3; 91 $METAFIELD_METHOD_GREATERTHANORE = 4; 92 $METAFIELD_METHOD_SUBSTRING = 5; 93 94 $METAFIELD_NOVALUE_MARKER = 4294967295; 95 96 97 // ---------------------------------------------------------------------------- 98 // Parameter initialisation 99 // ---------------------------------------------------------------------------- 100 101 // Send HTTP header to define meta charset 102 if (isset($Charset) && $NoCharset == 0) 103 header("Content-Type: text/html; charset=" . $Charset); 104 105 // For versions of PHP before 4.1.0 106 // we will emulate the superglobals by creating references 107 // NOTE: references created are NOT superglobals 108 if (!isset($_SERVER) && isset($HTTP_SERVER_VARS)) 109 $_SERVER = &$HTTP_SERVER_VARS; 110 if (!isset($_GET) && isset($HTTP_GET_VARS)) 111 $_GET = &$HTTP_GET_VARS; 112 if (!isset($_POST) && isset($HTTP_POST_VARS)) 113 $_POST = &$HTTP_POST_VARS; 114 115 // fix get/post variables if magic quotes are enabled 116 if (get_magic_quotes_gpc() == 1) 117 { 118 if (isset($_GET)) 119 while (list($key, $value) = each($_GET)) 120 { 121 if (!is_array($value)) 122 $_GET["$key"] = stripslashes($value); 123 } 124 if (isset($_POST)) 125 while (list($key, $value) = each($_POST)) 126 $_POST["$key"] = stripslashes($value); 127 } 128 129 // check magic_quotes for runtime stuff (reading from files, etc) 130 if (get_magic_quotes_runtime() == 1) 131 set_magic_quotes_runtime(0); 132 133 // we use the method=GET and 'query' parameter now (for sub-result pages etc) 134 $IsZoomQuery = 0; 135 if (isset($_GET['zoom_query'])) 136 { 137 $query = $_GET['zoom_query']; 138 $IsZoomQuery = 1; 139 } 140 else 141 $query = ""; 142 143 // number of results per page, defaults to 10 if not specified 144 if (isset($_GET['zoom_per_page'])) 145 { 146 $per_page = intval($_GET['zoom_per_page']); 147 if ($per_page < 1) 148 $per_page = 1; 149 } 150 else 151 $per_page = 10; 152 153 // current result page number, defaults to the first page if not specified 154 $NewSearch = 0; 155 if (isset($_GET['zoom_page'])) 156 { 157 $page = intval($_GET['zoom_page']); 158 if ($page < 1) 159 $page = 1; 160 } 161 else 162 { 163 $page = 1; 164 $NewSearch = 1; 165 } 166 167 // Check for autocomplete query 168 $IsZoomAC = 0; 169 if (isset($_GET['zoom_ac'])) 170 { 171 $IsZoomAC = intval($_GET['zoom_ac']); 172 $ZoomACOutput = ""; 173 if ($IsZoomAC == 1) 174 $SearchAsSubstring = 1; 175 } 176 177 // AND operator. 178 // 1 if we are searching for ALL terms 179 // 0 if we are searching for ANY terms (default) 180 if (isset($_GET['zoom_and'])) 181 $and = intval($_GET['zoom_and']); 182 elseif (isset($DefaultToAnd) && $DefaultToAnd == 1) 183 $and = 1; 184 else 185 $and = 0; 186 187 // for category support 188 if ($UseCats == 1) 189 { 190 if (isset($_GET['zoom_cat'])) 191 { 192 if (is_array($_GET['zoom_cat'])) 193 $cat = $_GET['zoom_cat']; 194 else 195 $cat = array($_GET['zoom_cat']); 196 $cat = array_filter($cat, "is_numeric"); 197 } 198 else 199 $cat = array(-1); // default to search all categories 200 201 $num_zoom_cats = count($cat); 202 if ($num_zoom_cats == 0) 203 $cat = array(-1); // default to search all categories 204 } 205 206 // for sorting options 207 // zero is default (relevance) 208 // 1 is sort by date (if Date/Time is available) 209 if (isset($_GET['zoom_sort'])) 210 $sort = intval($_GET['zoom_sort']); 211 else 212 $sort = $DefaultSort; 213 214 // date range 215 if ($DateRangeSearch == 1) 216 { 217 if (isset($_GET['zoom_datefrom'])) 218 $date_from = $_GET['zoom_datefrom']; 219 else 220 $date_from = ""; 221 if (isset($_GET['zoom_dateto'])) 222 $date_to = $_GET['zoom_dateto']; 223 else 224 $date_to = ""; 225 } 226 227 $LinkBackJoinChar = "?"; 228 if (isset($LinkBackURL) == false || strlen($LinkBackURL) < 1) 229 $SelfURL = htmlspecialchars($_SERVER['PHP_SELF'], ENT_COMPAT, $Charset); 230 else 231 { 232 $SelfURL = $LinkBackURL; 233 } 234 235 if (strchr($SelfURL, '?')) 236 $LinkBackJoinChar = "&"; 237 238 // init. link target string 239 $zoom_target = ""; 240 if ($UseLinkTarget == 1 && isset($LinkTarget)) 241 $zoom_target = " target=\"" . $LinkTarget . "\" "; 242 243 $UseMBFunctions = 0; 244 if ($UseUTF8 == 1) 245 { 246 if (function_exists('mb_strtolower')) 247 $UseMBFunctions = 1; 248 } 249 250 if ($UseStemming == 1) 251 { 252 $porterStemmer = new PorterStemmer(); 253 } 254 255 // ---------------------------------------------------------------------------- 256 // Template buffers 257 // ---------------------------------------------------------------------------- 258 259 // defines for output elements 260 $OUTPUT_FORM_START = 0; 261 $OUTPUT_FORM_END = 1; 262 $OUTPUT_FORM_SEARCHBOX = 2; 263 $OUTPUT_FORM_SEARCHBUTTON = 3; 264 $OUTPUT_FORM_RESULTSPERPAGE = 4; 265 $OUTPUT_FORM_MATCH = 5; 266 $OUTPUT_FORM_CATEGORIES = 6; 267 $OUTPUT_FORM_CUSTOMMETA = 7; 268 269 $OUTPUT_HEADING = 8; 270 $OUTPUT_SUMMARY = 9; 271 $OUTPUT_SUGGESTION = 10; 272 $OUTPUT_PAGESCOUNT = 11; 273 $OUTPUT_SORTING = 12; 274 $OUTPUT_SEARCHTIME = 13; 275 $OUTPUT_RECOMMENDED = 14; 276 $OUTPUT_PAGENUMBERS = 15; 277 $OUTPUT_CATSUMMARY = 16; 278 $OUTPUT_FORM_DATERANGE = 17; 279 280 $OUTPUT_TAG_COUNT = 18; 281 282 $OutputBuffers = array_fill(0, $OUTPUT_TAG_COUNT, ""); 283 $OutputResultsBuffer = ""; 284 285 $TemplateShowTags = array( 286 "<!--ZOOM_SHOW_FORMSTART-->", 287 "<!--ZOOM_SHOW_FORMEND-->", 288 "<!--ZOOM_SHOW_SEARCHBOX-->", 289 "<!--ZOOM_SHOW_SEARCHBUTTON-->", 290 "<!--ZOOM_SHOW_RESULTSPERPAGE-->", 291 "<!--ZOOM_SHOW_MATCHOPTIONS-->", 292 "<!--ZOOM_SHOW_CATEGORIES-->", 293 "<!--ZOOM_SHOW_CUSTOMMETAOPTIONS-->", 294 "<!--ZOOM_SHOW_HEADING-->", 295 "<!--ZOOM_SHOW_SUMMARY-->", 296 "<!--ZOOM_SHOW_SUGGESTION-->", 297 "<!--ZOOM_SHOW_PAGESCOUNT-->", 298 "<!--ZOOM_SHOW_SORTING-->", 299 "<!--ZOOM_SHOW_SEARCHTIME-->", 300 "<!--ZOOM_SHOW_RECOMMENDED-->", 301 "<!--ZOOM_SHOW_PAGENUMBERS-->", 302 "<!--ZOOM_SHOW_CATSUMMARY-->", 303 "<!--ZOOM_SHOW_JAVASCRIPTS-->", 304 "<!--ZOOM_SHOW_DATERANGE-->" 305 ); 306 307 $TemplateDefaultTag = "<!--ZOOMSEARCH-->"; 308 $TemplateDefaultTagLen = strlen($TemplateDefaultTag); 309 $TemplateSearchFormTag = "<!--ZOOM_SHOW_SEARCHFORM-->"; 310 $TemplateSearchFormTagLen = strlen($TemplateSearchFormTag); 311 $TemplateResultsTag = "<!--ZOOM_SHOW_RESULTS-->"; 312 $TemplateResultsTagLen = strlen($TemplateResultsTag); 313 $TemplateQueryTag = "<!--ZOOM_SHOW_QUERY-->"; 314 $TemplateQueryTagLen = strlen($TemplateQueryTag); 315 316 $OutputBuffers[$OUTPUT_FORM_START] = "<form method=\"get\" action=\"".$SelfURL."\" target=\"_self\" class=\"zoom_searchform\">"; 317 $OutputBuffers[$OUTPUT_FORM_END] = "</form>"; 318 319 // Indexes for dict structure 320 $DICT_WORD = 0; 321 $DICT_PTR = 1; 322 $DICT_VARCOUNT = 2; 323 $DICT_VARIANTS = 3; 324 325 // ---------------------------------------------------------------------------- 326 // Functions 327 // ---------------------------------------------------------------------------- 328 function ShowDefaultForm() 329 { 330 global $OutputBuffers; 331 global $OUTPUT_FORM_SEARCHBOX, $OUTPUT_FORM_SEARCHBUTTON, $OUTPUT_FORM_RESULTSPERPAGE; 332 global $OUTPUT_FORM_MATCH, $OUTPUT_FORM_CATEGORIES, $OUTPUT_FORM_CUSTOMMETA; 333 global $OUTPUT_FORM_START, $OUTPUT_FORM_END, $OUTPUT_FORM_DATERANGE; 334 335 print($OutputBuffers[$OUTPUT_FORM_START]); 336 print($OutputBuffers[$OUTPUT_FORM_SEARCHBOX]); 337 print($OutputBuffers[$OUTPUT_FORM_SEARCHBUTTON]); 338 print($OutputBuffers[$OUTPUT_FORM_RESULTSPERPAGE]); 339 print($OutputBuffers[$OUTPUT_FORM_MATCH]); 340 print($OutputBuffers[$OUTPUT_FORM_CATEGORIES]); 341 print($OutputBuffers[$OUTPUT_FORM_CUSTOMMETA]); 342 print($OutputBuffers[$OUTPUT_FORM_DATERANGE]); 343 print($OutputBuffers[$OUTPUT_FORM_END]); 344 } 345 346 function ShowDefaultSearchPage() 347 { 348 global $OutputResultsBuffer; 349 global $OutputBuffers; 350 global $OUTPUT_HEADING, $OUTPUT_SUMMARY, $OUTPUT_SUGGESTION, $OUTPUT_PAGESCOUNT; 351 global $OUTPUT_RECOMMENDED, $OUTPUT_SORTING, $OUTPUT_PAGENUMBERS, $OUTPUT_SEARCHTIME; 352 global $OUTPUT_CATSUMMARY; 353 354 ShowDefaultForm(); 355 // now show the default results layout 356 print($OutputBuffers[$OUTPUT_HEADING]); 357 print($OutputBuffers[$OUTPUT_SUMMARY]); 358 print($OutputBuffers[$OUTPUT_CATSUMMARY]); 359 print($OutputBuffers[$OUTPUT_SUGGESTION]); 360 print($OutputBuffers[$OUTPUT_PAGESCOUNT]); 361 print($OutputBuffers[$OUTPUT_RECOMMENDED]); 362 print($OutputBuffers[$OUTPUT_SORTING]); 363 print($OutputResultsBuffer); 364 print($OutputBuffers[$OUTPUT_PAGENUMBERS]); 365 print($OutputBuffers[$OUTPUT_SEARCHTIME]); 366 } 367 368 function IncludeAdditionalJS() 369 { 370 global $UseAutoComplete, $DateRangeSearch; 371 global $AUTOCOMPLETE_JSFILE, $AUTOCOMPLETE_CSSFILE, $DATEPICKER_JSFILE; 372 global $SelfURL, $LinkBackJoinChar; 373 global $onloadFunctionStr; 374 375 if ($UseAutoComplete == 1) 376 { 377 print("<script language=\"javascript\" type=\"text/javascript\">\n"); 378 //print("var ZoomAutoComplete_URL = \"".$SelfURL.$LinkBackJoinChar."zoom_ac=1\";\n"); 379 print("var ZoomAutoComplete_URL = \"search.php".$LinkBackJoinChar."zoom_ac=1\";\n"); 380 include($AUTOCOMPLETE_JSFILE); 381 $onloadFunctionStr = "function() { ZoomAutoComplete_OnLoad('zoom_searchbox');}"; 382 print("if (window.addEventListener) window.addEventListener('load', " . $onloadFunctionStr . ", false);"); 383 print(" else if (window.attachEvent) window.attachEvent('onload', " . $onloadFunctionStr . ");"); 384 print(" else window['onload'] = " . $onloadFunctionStr); 385 print("</script>\n"); 386 print("<style>\n"); 387 include($AUTOCOMPLETE_CSSFILE); 388 print("</style>\n"); 389 } 390 391 if ($DateRangeSearch == 1) 392 { 393 print("<script language=\"javascript\" type=\"text/javascript\">\n"); 394 include($DATEPICKER_JSFILE); 395 print("</script>\n"); 396 } 397 } 398 399 function ShowTemplate() 400 { 401 global $ZoomInfo; 402 global $OutputBuffers; 403 global $TemplateShowTags; 404 global $OUTPUT_TAG_COUNT; 405 global $TemplateSearchFormTag, $TemplateSearchFormTagLen; 406 global $TemplateDefaultTag, $TemplateDefaultTagLen; 407 global $TemplateResultsTag, $TemplateResultsTagLen; 408 global $OutputResultsBuffer; 409 global $TemplateQueryTag, $TemplateQueryTagLen, $queryForHTML; 410 global $UseAutoComplete, $DateRangeSearch; 411 global $AUTOCOMPLETE_JSFILE, $AUTOCOMPLETE_CSSFILE, $DATEPICKER_JSFILE; 412 global $SelfURL, $LinkBackJoinChar; 413 414 // DO NOT MODIFY THE TEMPLATE FILENAME BELOW: 415 $TemplateFilename = "search_template.html"; 416 // Note that there is no practical need to change the TemplateFilename. This file 417 // is not visible to the end user. The search link on your website should point to 418 // "search.php", and not the template file. 419 // 420 // Note also that you cannot change the filename to a PHP or ASP file. 421 // The template file will only be treated as a static HTML page and changing the 422 // extension will not alter this behaviour. Please see this FAQ support page 423 // for a solution: http://www.wrensoft.com/zoom/support/faq_ssi.html 424 425 //Open and print start of result page template 426 $TemplateFilename = dirname(__FILE__) . "/" . $TemplateFilename; 427 $template = file ($TemplateFilename); 428 $numtlines = count($template); //Number of lines in the template 429 $template_line = 0; 430 $templatePtr = $template[$template_line]; 431 $IncludedJS = false; 432 433 $NeedJS = false; 434 if ($UseAutoComplete == 1 || $DateRangeSearch == 1) 435 $NeedJS = true; 436 437 while ($template_line < $numtlines && $templatePtr != "") 438 { 439 if ($NeedJS == true && $IncludedJS == false && stristr($templatePtr, "</head>") !== FALSE) 440 { 441 IncludeAdditionalJS(); 442 $IncludedJS = true; 443 } 444 445 $tagPos = strpos($templatePtr, "<!--ZOOM"); 446 if ($tagPos === FALSE) 447 $tagPtr = ""; 448 else 449 { 450 if ($tagPos == 0) 451 $tagPtr = $templatePtr; 452 else 453 { 454 print(substr($templatePtr,0, $tagPos)); 455 $tagPtr = substr($templatePtr, $tagPos); 456 } 457 } 458 459 if ($tagPtr == "") 460 { 461 print($templatePtr); 462 $templatePtr = ""; 463 } 464 else if (strncasecmp($tagPtr, $TemplateDefaultTag, $TemplateDefaultTagLen) == 0) 465 { 466 ShowDefaultSearchPage(); 467 $templatePtr = substr($tagPtr, $TemplateDefaultTagLen); 468 } 469 else if (strncasecmp($tagPtr, $TemplateSearchFormTag, $TemplateSearchFormTagLen) == 0) 470 { 471 ShowDefaultForm(); 472 $templatePtr = substr($tagPtr, $TemplateSearchFormTagLen); 473 } 474 else if (strncasecmp($tagPtr, $TemplateResultsTag, $TemplateResultsTagLen) == 0) 475 { 476 print($OutputResultsBuffer); 477 $templatePtr = substr($tagPtr, $TemplateResultsTagLen); 478 } 479 else if (strncasecmp($tagPtr, $TemplateQueryTag, $TemplateQueryTagLen) == 0) 480 { 481 if (strlen($queryForHTML) > 0) 482 print($queryForHTML); 483 $templatePtr = substr($tagPtr, $TemplateQueryTagLen); 484 } 485 else 486 { 487 for ($tagnum = 0; $tagnum < $OUTPUT_TAG_COUNT; $tagnum++) 488 { 489 $tagLen = strlen($TemplateShowTags[$tagnum]); 490 if (strncasecmp($tagPtr, $TemplateShowTags[$tagnum], $tagLen) == 0) 491 { 492 print($OutputBuffers[$tagnum]); 493 $templatePtr = substr($tagPtr, $tagLen); 494 break; 495 } 496 } 497 if ($tagnum == $OUTPUT_TAG_COUNT) 498 { 499 print($tagPtr); 500 $templatePtr = ""; 501 } 502 } 503 504 if (strlen(trim($templatePtr)) == 0) 505 { 506 $template_line++; 507 if ($template_line < $numtlines) 508 $templatePtr = $template[$template_line]; 509 } 510 } 511 512 // Last check if we didn't add the JS (because of a lack of </head>, we will insert it before end of file 513 if ($NeedJS == true && $IncludedJS == false) 514 { 515 IncludeAdditionalJS(); 516 $IncludedJS = true; 517 } 518 } 519 520 function PrintHighlightDescription($line) 521 { 522 global $Highlighting; 523 global $HighlightColor; 524 global $RegExpSearchWords; 525 global $NumSearchWords; 526 global $SearchAsSubstring; 527 528 if ($Highlighting == 0) 529 { 530 return $line; 531 } 532 533 $res = $line; 534 535 for ($i = 0; $i < $NumSearchWords; $i++) 536 { 537 if (strlen($RegExpSearchWords[$i]) < 1) 538 continue; 539 540 // replace with marker text, assumes [;:] and [:;] is not the search text... 541 if ($SearchAsSubstring == 1) 542 $res = preg_replace("/(" .$RegExpSearchWords[$i] . ")/i", "[;:]$1[:;]", $res); 543 else 544 $res = preg_replace("/(\W|\A|\b)(" .$RegExpSearchWords[$i] . ")(\W|\Z|\b)/i", "$1[;:]$2[:;]$3", $res); 545 } 546 // replace the marker text with the html text 547 // this is to avoid finding previous <span>'ed text. 548 $res = str_replace("[;:]", "<span class=\"highlight\">", $res); 549 $res = str_replace("[:;]", "</span>", $res); 550 return $res; 551 } 552 553 554 function GetDictionaryWord($word_id, $variant_index) 555 { 556 global $dict, $DICT_VARIANTS, $DICT_WORD, $DICT_VARCOUNT; 557 558 if ($variant_index > 0 && $variant_index <= $dict[$word_id][$DICT_VARCOUNT]) 559 return $dict[$word_id][$DICT_VARIANTS][$variant_index-1]; 560 else 561 return $dict[$word_id][$DICT_WORD]; 562 } 563 564 function GetSpellingWord($word_id) 565 { 566 global $dict, $DICT_VARIANTS, $DICT_WORD, $DICT_VARCOUNT; 567 568 if ($dict[$word_id][$DICT_VARCOUNT] > 0) 569 return $dict[$word_id][$DICT_VARIANTS][0]; 570 else 571 return $dict[$word_id][$DICT_WORD]; 572 } 573 574 575 $HIGHLIGHT_NONE = 0; 576 $HIGHLIGHT_SINGLE = 1; 577 $HIGHLIGHT_START = 2; 578 $HIGHLIGHT_END = 3; 579 580 function HighlightContextArray($context_word_count) 581 { 582 global $highlightArray; 583 global $contextArray; 584 global $NumSearchWords; 585 global $SearchWords, $UseWildCards, $RegExpSearchWords; 586 global $phrase_terms_ids, $search_terms_ids; 587 global $HIGHLIGHT_NONE, $HIGHLIGHT_SINGLE, $HIGHLIGHT_START, $HIGHLIGHT_END; 588 global $SearchAsSubstring, $DictReservedLimit; 589 590 for ($i = 0; $i < $context_word_count; $i++) 591 { 592 if ($contextArray[$i] == 0) 593 continue; 594 595 $word_id = $contextArray[$i][0]; 596 $variant_index = $contextArray[$i][1]; 597 598 for ($sw = 0; $sw < $NumSearchWords; $sw++) 599 { 600 if (strpos($SearchWords[$sw], " ") !== false) 601 { 602 // this is an exact phrase and has its phrase terms stored in SearchPhrases[sw] 603 $termNum = $i; 604 $pterm = 0; 605 while ($phrase_terms_ids[$sw][$pterm] != 0 && $termNum < $context_word_count) 606 { 607 // only compare this word in the context if it is NOT a punctuation word 608 // or if it is the first word we are looking at in this phrase 609 if ($termNum == $i || $contextArray[$termNum][0] > $DictReservedLimit) 610 { 611 if ($phrase_terms_ids[$sw][$pterm] != $contextArray[$termNum][0]) 612 break; // we break out of looking at each term of the phrase if we don't match 613 $pterm++; 614 } 615 $termNum++; 616 } 617 618 if ($pterm > 0 && $phrase_terms_ids[$sw][$pterm] == 0) 619 { 620 $highlightArray[$i] = $HIGHLIGHT_START; 621 $highlightArray[$termNum-1] = $HIGHLIGHT_END; 622 } 623 } 624 else 625 { 626 $res = 0; 627 if ($UseWildCards[$sw] == 1) 628 { 629 $res = preg_match("/\A(".$RegExpSearchWords[$sw].")\Z/i", GetDictionaryWord($word_id, 0)); 630 } 631 else 632 { 633 if ($search_terms_ids[$sw] == $word_id) 634 $res = 1; 635 } 636 if ($res > 0) 637 { 638 if ($highlightArray[$i] == $HIGHLIGHT_NONE) 639 $highlightArray[$i] = $HIGHLIGHT_SINGLE; 640 } 641 } 642 } 643 } 644 } 645 646 function PrintNumResults($num) 647 { 648 global $STR_NO_RESULTS, $STR_RESULT, $STR_RESULTS; 649 global $IsMaxLimitExceeded, $STR_MORETHAN; 650 if ($num == 0) 651 return $STR_NO_RESULTS; 652 else if ($num == 1) 653 return $num . " " . $STR_RESULT; 654 else 655 { 656 if ($IsMaxLimitExceeded) 657 return $STR_MORETHAN . " " . $num . " " . $STR_RESULTS; 658 return $num . " " . $STR_RESULTS; 659 } 660 } 661 662 function RecLinkAddParamToURL($url, $paramStr) 663 { 664 // add GET parameters to URL depending on 665 // whether there are any existing parameters 666 if (strpos($url, "?") !== false) 667 return $url . "&" . $paramStr; 668 else 669 { 670 $hashPos = strpos($url, "#"); 671 if ($hashPos !== false) 672 return substr($url, 0, $hashPos) . "?" . $paramStr . substr($url, $hashPos); 673 else 674 return $url . "?" . $paramStr; 675 } 676 } 677 678 function AddParamToURL($url, $paramStr) 679 { 680 // add GET parameters to URL depending on 681 // whether there are any existing parameters 682 // Note: we don't need to worry about hash anchors here like RecLinkAddParamToURL 683 // because they are stripped for non-recommended link. 684 if (strpos($url, "?") !== false) 685 return $url . "&" . $paramStr; 686 else 687 return $url . "?" . $paramStr; 688 } 689 690 691 // ---------------------------------------------------------------------------- 692 // Compares the two values, used for sorting output results 693 // Results that match all search terms are put first, highest score 694 // ---------------------------------------------------------------------------- 695 function SortCompare ($a, $b) 696 { 697 if ($a[2] < $b[2]) 698 return 1; 699 else 700 if ($a[2] > $b[2]) 701 return -1; 702 else 703 { 704 if ($a[1] < $b[1]) 705 return 1; 706 else 707 if ($a[1] > $b[1]) 708 return -1; 709 else 710 return 0; 711 } 712 } 713 714 function SortByDate ($a, $b) 715 { 716 global $pageinfo; 717 if ($pageinfo[$a[0]]["datetime"] < $pageinfo[$b[0]]["datetime"]) 718 return 1; 719 else 720 if ($pageinfo[$a[0]]["datetime"] > $pageinfo[$b[0]]["datetime"]) 721 return -1; 722 else 723 { 724 // if equal dates/time, return based on sw matched and score 725 return SortCompare($a, $b); 726 } 727 } 728 729 function SortByDateAsc ($a, $b) 730 { 731 global $pageinfo; 732 if ($pageinfo[$a[0]]["datetime"] > $pageinfo[$b[0]]["datetime"]) 733 return 1; 734 else 735 if ($pageinfo[$a[0]]["datetime"] < $pageinfo[$b[0]]["datetime"]) 736 return -1; 737 else 738 { 739 // if equal dates/time, return based on sw matched and score 740 return SortCompare($a, $b); 741 } 742 } 743 744 function sw_compare ($a, $b) 745 { 746 if ($a[0] == '-') 747 return 1; 748 749 if ($b[0] == '-') 750 return -1; 751 752 return 0; 753 } 754 755 756 // ---------------------------------------------------------------------------- 757 // Translates a typical shell wildcard pattern ("zoo*" => "zoom" etc.) 758 // to a regular expression pattern. Supports only '*' and '?' characters. 759 // ---------------------------------------------------------------------------- 760 function pattern2regexp($pattern) 761 { 762 $i = 0; 763 $len = strlen($pattern); 764 765 if (strpos($pattern, "$") !== false) 766 str_replace($pattern, "$", "\$"); 767 if (strpos($pattern, "#") !== false) 768 str_replace($pattern, "#", "\#"); 769 770 $res = ""; 771 772 while ($i < $len) { 773 $c = $pattern[$i]; 774 if ($c == '*') 775 $res = $res . "[\d\S]*"; 776 else 777 if ($c == '?') 778 $res = $res . "."; 779 else 780 if ($c == '.') 781 $res = $res . "\."; 782 else 783 $res = $res . preg_quote($c, '/'); 784 $i++; 785 } 786 return $res; 787 } 788 789 function wordcasecmp($word1, $word2) 790 { 791 global $UseUTF8; 792 global $UseMBFunctions; 793 global $ToLowerSearchWords; 794 795 if ($ToLowerSearchWords == 0) 796 return strcmp($word1, $word2); 797 798 if ($UseUTF8 == 1 && $UseMBFunctions == 1) 799 { 800 // string length compare for speed reasons, only use mb_strtolower when absolutely necessary 801 // assumes that the lowercase variant of multibyte characters are same length as their uppercase variant 802 if (strlen($word1) == strlen($word2)) 803 { 804 if (preg_match('/^[\x80-\xff]/', $word1) || preg_match('/^[\x80-\xff]/', $word2)) 805 return strcmp(mb_strtolower($word1, "UTF-8"), mb_strtolower($word2, "UTF-8")); 806 else 807 return strcasecmp($word1, $word2); 808 } 809 else 810 return 1; 811 } 812 else 813 return strcasecmp($word1, $word2); 814 } 815 816 function mystristr($word1, $word2) 817 { 818 global $UseUTF8; 819 global $UseMBFunctions; 820 821 if ($UseUTF8 == 1 && $UseMBFunctions == 1) 822 { 823 if (preg_match('/^[\x80-\xff]/', $word1) || preg_match('/^[\x80-\xff]/', $word2)) 824 return strstr(mb_strtolower($word1, "UTF-8"), mb_strtolower($word2, "UTF-8")); 825 } 826 827 return stristr($word1, $word2); 828 } 829 830 831 // This function is unable to return any values larger than a signed int 832 // is capable of holding, due to PHP's bitwise operators only working 833 // with signed ints. 834 function GetBytes($binfile, $numbytes) 835 { 836 global $METAFIELD_NOVALUE_MARKER; 837 838 $ffcount = 0; 839 $ret = 0; 840 $bytes_buffer = fread($binfile, $numbytes); 841 for ($k = 0; $k < $numbytes; $k++) 842 { 843 if ($bytes_buffer[$k] == chr(0xFF)) 844 $ffcount++; 845 $ret = $ret | ord($bytes_buffer[$k])<<(8*$k); 846 } 847 if ($ffcount == $numbytes) 848 $ret = (float) $METAFIELD_NOVALUE_MARKER; 849 return $ret; 850 } 851 852 function GetDictID($word) 853 { 854 global $dict; 855 global $dict_count; 856 for ($i = 0; $i < $dict_count; $i++) { 857 if (wordcasecmp($dict[$i][0], $word) == 0) 858 return $i; 859 } 860 return -1; // not found 861 } 862 863 function GetNextDictWord($fp_pagetext) 864 { 865 global $DictIDLen; 866 $dict_id = 0; 867 $variant_index = 0; 868 869 $bytes_buffer = fread($fp_pagetext, $DictIDLen); 870 if ($bytes_buffer != "") 871 { 872 for ($i = 0; $i < $DictIDLen-1; $i++) 873 { 874 $dict_id = $dict_id | ord($bytes_buffer[$i])<<(8*$i); 875 } 876 $variant_index = ord($bytes_buffer[$DictIDLen-1]); 877 } 878 else 879 { 880 $dict_id = 0; 881 $variant_index = 0; 882 } 883 884 return array($dict_id,$variant_index); 885 } 886 887 function CheckBitInByteArray($bitnum, $byteArray) 888 { 889 global $NumCatBytes; 890 891 $bytenum = 0; 892 $newBitnum = 0; 893 894 $bytenum = ceil(($bitnum+1) / 8.0); 895 896 if ($bytenum > 1) 897 { 898 $newBitnum = $bitnum - (($bytenum-1)*8); 899 $bytenum = $bytenum - 1; 900 } 901 else 902 { 903 $newBitnum = $bitnum; 904 $bytenum = 0; 905 } 906 907 if ($bytenum >= $NumCatBytes) 908 { 909 exit("Error: Category number is invalid. Incorrect settings file used?"); 910 } 911 912 return ($byteArray[$bytenum] & (1 << $newBitnum)); 913 } 914 915 function SkipSearchWord($sw) 916 { 917 global $SearchWords; 918 global $SkippedWords; 919 global $SkippedOutputStr; 920 global $RegExpSearchWords; 921 global $Highlighting; 922 global $UseWildCards; 923 if ($SearchWords[$sw] != "") 924 { 925 if ($SkippedWords > 0) 926 $SkippedOutputStr .= ", "; 927 $SkippedOutputStr .= "\"<b>" . $SearchWords[$sw] . "</b>\""; 928 $SearchWords[$sw] = ""; 929 if ($Highlighting == 1 || $UseWildCards[$sw] == 1) 930 $RegExpSearchWords[$sw] = ""; 931 } 932 $SkippedWords++; 933 } 934 935 function GetSPCode($word) 936 { 937 $Vowels = "AEIOU"; 938 $FrontV = "EIY"; 939 $VarSound = "CSPTG"; 940 $Dbl = "."; 941 942 $metalen = 6; 943 944 $tmpword = strtoupper($word); 945 946 $wordlen = strlen($tmpword); 947 if ($wordlen < 1) 948 return ""; 949 950 // if ae, gn, kn, pn, wr then drop the first letter 951 $strPtr = substr($tmpword, 0, 2); 952 if ($strPtr == "AE" || $strPtr == "GN" || $strPtr == "KN" || $strPtr == "PN" || $strPtr == "WR") 953 $tmpword = substr($tmpword, 1); 954 955 // change x to s 956 if ($tmpword{0} == "X") 957 $tmpword = "S" . substr($tmpword, 1); 958 959 // get rid of the 'h' in "wh" 960 if (substr($tmpword, 0, 2) == "WH") 961 $tmpword = "W" . substr($tmpword, 2); 962 963 // update the word length 964 $wordlen = strlen($tmpword); 965 $lastChar = $wordlen-1; 966 967 // remove an 's' from the end of the string 968 if ($tmpword{$lastChar} == "S") 969 { 970 $tmpword = substr($tmpword, 0, $wordlen-1); 971 $wordlen = strlen($tmpword); 972 $lastChar = $wordlen-1; 973 } 974 975 $metaph = ""; 976 $Continue = false; 977 978 for ($i = 0; strlen($metaph) < $metalen && $i < $wordlen; $i++) 979 { 980 $char = $tmpword{$i}; 981 $vowelBefore = false; 982 $continue = false; 983 if ($i > 0) 984 { 985 $prevChar = $tmpword{$i-1}; 986 if (strpos($Vowels, $prevChar) !== FALSE) 987 $vowelBefore = true; 988 } 989 else 990 { 991 $prevChar = " "; 992 if (strpos($Vowels, $char) !== FALSE) 993 { 994 $metaph .= $tmpword{0}; 995 continue; 996 } 997 } 998 999 $vowelAfter = false; 1000 $frontvAfter = false; 1001 $nextChar = " "; 1002 if ($i < $lastChar) 1003 { 1004 $nextChar = $tmpword{$i+1}; 1005 if (strpos($Vowels, $nextChar) !== FALSE) 1006 $vowelAfter = true; 1007 if (strpos($FrontV, $nextChar) !== FALSE) 1008 $frontvAfter = true; 1009 } 1010 1011 // skip double letters except ones in list 1012 if ($char == $nextChar && $nextChar != $Dbl) 1013 continue; 1014 1015 $nextChar2 = " "; 1016 if ($i < ($lastChar-1)) 1017 $nextChar2 = $tmpword{$i+2}; 1018 1019 $nextChar3 = " "; 1020 if ($i < ($lastChar-2)) 1021 $nextChar3 = $tmpword{$i+3}; 1022 1023 switch ($char) 1024 { 1025 case "B": 1026 $silent = false; 1027 if ($i == $lastChar && $prevChar == "M") 1028 $silent = true; 1029 if ($silent == false) 1030 $metaph .= $char; 1031 break; 1032 case "C": 1033 if (!($i > 1 && $prevChar == "S" && $frontvAfter)) 1034 { 1035 if ($i > 0 && $nextChar == "I" && $nextChar2 == "A") 1036 $metaph .= "X"; 1037 elseif ($frontvAfter) 1038 $metaph .= "S"; 1039 elseif ($i > 1 && $prevChar == "S" && $nextChar == "H") 1040 $metaph .= "K"; 1041 elseif ($nextChar == "H") 1042 { 1043 if ($i == 0 && strpos($Vowels, $nextChar2) === FALSE) 1044 $metaph .= "K"; 1045 else 1046 $metaph .= "X"; 1047 } 1048 elseif ($prevChar == "C") 1049 $metaph .= "C"; 1050 else 1051 $metaph .= "K"; 1052 } 1053 break; 1054 case "D": 1055 if ($nextChar == "G" && strpos($FrontV, $nextChar2) !== FALSE) 1056 $metaph .= "J"; 1057 else 1058 $metaph .= "T"; 1059 break; 1060 case "G": 1061 $silent = false; 1062 if ( ($i < ($lastChar-1) && $nextChar == "H") && 1063 (strpos($Vowels, $nextChar2) == FALSE)) 1064 $silent = true; 1065 1066 if ( ($i == ($lastChar-3)) && $nextChar == "N" && $nextChar == "E" && $nextChar == "D") 1067 $silent = true; 1068 elseif ( ($i == ($lastChar-1)) && $nextChar == "N") 1069 $silent = true; 1070 1071 if ($prevChar == "D" && $frontvAfter) 1072 $silent = true; 1073 1074 if ($prevChar == "G") 1075 $hard = true; 1076 else 1077 $hard = false; 1078 1079 if (!$silent) 1080 { 1081 if ($frontvAfter && (!$hard)) 1082 $metaph .= "J"; 1083 else 1084 $metaph .= "K"; 1085 } 1086 break; 1087 case "H": 1088 $silent = false; 1089 if (strpos($VarSound, $prevChar) !== FALSE) 1090 $silent = true; 1091 if ($vowelBefore && !$vowelAfter) 1092 $silent = true; 1093 if (!$silent) 1094 $metaph .= $char; 1095 break; 1096 case "F": 1097 case "J": 1098 case "L": 1099 case "M": 1100 case "N": 1101 case "R": 1102 $metaph .= $char; 1103 break; 1104 case "K": 1105 if ($prevChar != "C") 1106 $metaph .= $char; 1107 break; 1108 case "P": 1109 if ($nextChar == "H") 1110 $metaph .= "F"; 1111 else 1112 $metaph .= "P"; 1113 break; 1114 case "Q": 1115 $metaph .= "K"; 1116 break; 1117 case "S": 1118 if ($i > 1 && $nextChar == "I" && ($nextChar2 == "O" || $nextChar2 == "A")) 1119 $metaph .= "X"; 1120 elseif ($nextChar == "H") 1121 $metaph .= "X"; 1122 else 1123 $metaph .= "S"; 1124 break; 1125 case "T": 1126 if ($i > 1 && $nextChar == "I" && ($nextChar2 == "O" || $nextChar2 == "A")) 1127 $metaph .= "X"; 1128 elseif ($nextChar == "H") 1129 { 1130 if ($i > 0 || (strpos($Vowels, $nextChar2) !== FALSE)) 1131 $metaph .= "0"; 1132 else 1133 $metaph .= "T"; 1134 } 1135 elseif (!($i < ($lastChar-2) && $nextChar == "C" && $nextChar2 == "H")) 1136 $metaph .= "T"; 1137 break; 1138 case "V": 1139 $metaph .= "F"; 1140 break; 1141 case "W": 1142 case "Y": 1143 if ($i < $lastChar && $vowelAfter) 1144 $metaph .= $char; 1145 break; 1146 case "X": 1147 $metaph .= "KS"; 1148 break; 1149 case "Z": 1150 $metaph .= "S"; 1151 break; 1152 } 1153 } 1154 if (strlen($metaph) == 0) 1155 return ""; 1156 return $metaph; 1157 } 1158 1159 function GetPageData($index) 1160 { 1161 global $fp_pagedata, $pageinfo, $MaxPageDataLineLen; 1162 fseek($fp_pagedata, intval($pageinfo[$index]["dataoffset"])); 1163 $pgdata = fgets($fp_pagedata, $MaxPageDataLineLen); 1164 return explode("|", $pgdata); 1165 } 1166 1167 function GetUrlFromPageData($index) 1168 { 1169 global $fp_pagedata, $pageinfo, $MaxPageDataLineLen; 1170 fseek($fp_pagedata, intval($pageinfo[$index]["dataoffset"])); 1171 $pgdata = fgets($fp_pagedata, $MaxPageDataLineLen); 1172 $pipePos = strpos($pgdata, '|'); 1173 if ($pipePos !== FALSE) 1174 { 1175 return substr($pgdata, 0, $pipePos); 1176 } 1177 return ""; 1178 } 1179 1180 1181 function QueryEntities($query) 1182 { 1183 $query = str_replace("&", "&", $query); 1184 $query = str_replace("<", "<", $query); 1185 $query = str_replace(">", ">", $query); 1186 return $query; 1187 } 1188 1189 function uniord($u) 1190 { 1191 $k = mb_convert_encoding($u, 'UCS-2LE', 'UTF-8'); 1192 $k1 = ord(substr($k, 0, 1)); 1193 $k2 = ord(substr($k, 1, 1)); 1194 return $k2 * 256 + $k1; 1195 } 1196 1197 function FixQueryForAsianWords($query) 1198 { 1199 // check if the multibyte functions we need to use are available 1200 if (!function_exists('mb_convert_encoding') || 1201 !function_exists('mb_strlen') || 1202 !function_exists('mb_substr')) 1203 return $query; 1204 1205 $currCharType = 0; 1206 $lastCharType = 0; // 0 is normal, 1 is hiragana, 2 is katakana, 3 is "han" 1207 1208 // check for hiragan/katakana splitting required 1209 $newquery = ""; 1210 $query_len = mb_strlen($query, "UTF-8"); 1211 for ($i = 0; $i < $query_len; $i++) 1212 { 1213 $ch = mb_substr($query, $i, 1, "UTF-8"); 1214 $chVal = uniord($ch); 1215 1216 if ($chVal >= 12352 && $chVal <= 12447) 1217 $currCharType = 1; 1218 else if ($chVal >= 12448 && $chVal <= 12543) 1219 $currCharType = 2; 1220 else if ($chVal >= 13312 && $chVal <= 44031) 1221 $currCharType = 3; 1222 else 1223 $currCharType = 0; 1224 1225 if ($lastCharType != $currCharType && $ch != " ") 1226 $newquery .= " "; 1227 $lastCharType = $currCharType; 1228 $newquery .= $ch; 1229 } 1230 return $newquery; 1231 } 1232 1233 $LastRecLinkIdx = 0; 1234 1235 // matches the recommended link word against the user search query 1236 function RecLinkWordMatch($rec_word, $rec_idx) 1237 { 1238 global $NumSearchWords, $queryForSearch, $queryForURL, $query, $num_rec_words; 1239 global $SearchWords, $UseWildCards, $SearchAsSubstring, $ToLowerSearchWords; 1240 global $OutputBuffers, $OUTPUT_RECOMMENDED; 1241 global $PAGEDATA_URL, $PAGEDATA_TITLE, $PAGEDATA_DESC, $PAGEDATA_IMG, $UseZoomImage; 1242 global $zoom_target, $GotoHighlight, $PdfHighlight; 1243 global $num_recs_found; 1244 global $STR_RECOMMENDED; 1245 global $LastRecLinkIdx, $IsNoKeywordQuery; 1246 1247 $bRecLinkFound = false; 1248 1249 if ($LastRecLinkIdx == $rec_idx) 1250 return false; // we've already matched one for this page 1251 1252 for ($sw = 0; $sw <= $NumSearchWords; $sw++) 1253 { 1254 // if finished with last search word, check the full search query 1255 $result = 1; 1256 if ($sw == $NumSearchWords) 1257 $result = wordcasecmp($queryForSearch, $rec_word); 1258 else if (strlen($SearchWords[$sw]) > 0) 1259 { 1260 if ($UseWildCards[$sw] == 1) 1261 { 1262 $pattern = "/"; 1263 1264 // match entire word 1265 if ($SearchAsSubstring == 0) 1266 $pattern = $pattern . "\A"; 1267 1268 $pattern = $pattern . $RegExpSearchWords[$sw]; 1269 1270 if ($SearchAsSubstring == 0) 1271 $pattern = $pattern . "\Z"; 1272 1273 if ($ToLowerSearchWords != 0) 1274 $pattern = $pattern . "/i"; 1275 else 1276 $pattern = $pattern . "/"; 1277 1278 $result = !(preg_match($pattern, $rec_word)); 1279 } 1280 else if ($SearchAsSubstring == 0) 1281 { 1282 $result = wordcasecmp($SearchWords[$sw], $rec_word); 1283 } 1284 else 1285 { 1286 if (mystristr($rec_word, $SearchWords[$sw]) == FALSE) 1287 $result = 1; // not matched 1288 else 1289 $result = 0; // matched 1290 } 1291 1292 if ($result != 0) 1293 { 1294 // if not matched, we check if the word is a wildcard 1295 if (strpos($rec_word, "*") !== false || strpos($rec_word, "?") !== false) 1296 { 1297 $RecWordRegExp = "/\A" . pattern2regexp($rec_word) . "\Z/i"; 1298 $result = !(preg_match($RecWordRegExp, $SearchWords[$sw])); 1299 } 1300 } 1301 } 1302 1303 if ($result == 0) 1304 { 1305 $bRecLinkFound = true; 1306 if ($num_recs_found == 0) 1307 { 1308 $OutputBuffers[$OUTPUT_RECOMMENDED] .= "<div class=\"recommended\">\n"; 1309 $OutputBuffers[$OUTPUT_RECOMMENDED] .= "<div class=\"recommended_heading\">$STR_RECOMMENDED</div>\n"; 1310 } 1311 $pgdata = GetPageData($rec_idx); 1312 $LastRecLinkIdx = $rec_idx; 1313 1314 $url = $pgdata[$PAGEDATA_URL]; 1315 $title = $pgdata[$PAGEDATA_TITLE]; 1316 $description = $pgdata[$PAGEDATA_DESC]; 1317 if ($UseZoomImage) 1318 $image = $pgdata[$PAGEDATA_IMG]; 1319 1320 $urlLink = $url; 1321 //$urlLink = rtrim($urls[$rec_idx]); 1322 1323 if ($GotoHighlight == 1) 1324 { 1325 if ($SearchAsSubstring == 1) 1326 $urlLink = RecLinkAddParamToURL($urlLink, "zoom_highlightsub=".$queryForURL); 1327 else 1328 $urlLink = RecLinkAddParamToURL($urlLink, "zoom_highlight=".$queryForURL); 1329 } 1330 if ($PdfHighlight == 1 && $IsNoKeywordQuery == false) 1331 { 1332 if (stristr($urlLink, ".pdf") != FALSE) 1333 $urlLink = $urlLink."#search=%22".str_replace("\"", "", $query)."%22"; 1334 } 1335 $OutputBuffers[$OUTPUT_RECOMMENDED] .= "<div class=\"recommend_block\">\n"; 1336 if ($UseZoomImage) 1337 { 1338 if (strlen($image) > 0) 1339 { 1340 $OutputBuffers[$OUTPUT_RECOMMENDED] .= "<div class=\"recommend_image\">"; 1341 $OutputBuffers[$OUTPUT_RECOMMENDED] .= "<a href=\"".$urlLink."\"" . $zoom_target . "><img src=\"$image\" alt=\"\" class=\"recommend_image\"></a>"; 1342 $OutputBuffers[$OUTPUT_RECOMMENDED] .= "</div>"; 1343 } 1344 } 1345 $OutputBuffers[$OUTPUT_RECOMMENDED] .= "<div class=\"recommend_title\">"; 1346 $OutputBuffers[$OUTPUT_RECOMMENDED] .= "<a href=\"".$urlLink."\"" . $zoom_target . ">"; 1347 if (strlen($title) > 1) 1348 $OutputBuffers[$OUTPUT_RECOMMENDED] .= PrintHighlightDescription($title); 1349 else 1350 $OutputBuffers[$OUTPUT_RECOMMENDED] .= PrintHighlightDescription($pgdata[$PAGEDATA_URL]); 1351 $OutputBuffers[$OUTPUT_RECOMMENDED] .= "</a></div>\n"; 1352 $OutputBuffers[$OUTPUT_RECOMMENDED] .= "<div class=\"recommend_description\">"; 1353 $OutputBuffers[$OUTPUT_RECOMMENDED] .= PrintHighlightDescription($description); 1354 $OutputBuffers[$OUTPUT_RECOMMENDED] .= "</div>\n"; 1355 $OutputBuffers[$OUTPUT_RECOMMENDED] .= "<div class=\"recommend_infoline\">$url</div>\n"; 1356 $OutputBuffers[$OUTPUT_RECOMMENDED] .= "</div>"; 1357 $num_recs_found++; 1358 break; 1359 } 1360 } 1361 return $bRecLinkFound; 1362 } 1363 1364 // ---------------------------------------------------------------------------- 1365 // Starts here 1366 // ---------------------------------------------------------------------------- 1367 1368 $mtime = explode(" ", microtime()); 1369 $starttime = doubleval($mtime[1]) + doubleval($mtime[0]); 1370 1371 // Read in the metafields query 1372 if ($UseMetaFields == 1) 1373 { 1374 for ($fieldnum = 0; $fieldnum < $NumMetaFields; $fieldnum++) 1375 { 1376 if (isset($_GET[$metafields[$fieldnum][$METAFIELD_NAME]])) 1377 { 1378 $meta_query[$fieldnum] = $_GET[$metafields[$fieldnum][$METAFIELD_NAME]]; 1379 1380 if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_MULTI) 1381 { 1382 if (!is_array($meta_query[$fieldnum])) 1383 $meta_query[$fieldnum] = array($meta_query[$fieldnum]); 1384 $meta_query[$fieldnum] = array_filter($meta_query[$fieldnum], "is_numeric"); 1385 } 1386 /* 1387 if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_DROPDOWN) 1388 { 1389 $ddi = 0; 1390 foreach ($metafields[$fieldnum][$METAFIELD_DROPDOWN] as $ddv) 1391 { 1392 // replace the query value string with the numeric index for faster matching 1393 if (strcasecmp($meta_query[$fieldnum], $ddv) == 0) 1394 $meta_query[$fieldnum] = $ddi; 1395 $ddi++; 1396 } 1397 } 1398 */ 1399 } 1400 else 1401 $meta_query[$fieldnum] = ""; 1402 } 1403 } 1404 1405 $OutputResultsBuffer .= "<!--Zoom Search Engine ".$Version."-->\n"; 1406 1407 // Replace the key text <!--ZOOMSEARCH--> with the following 1408 if ($FormFormat > 0) 1409 { 1410 // Insert the form 1411 $OutputBuffers[$OUTPUT_FORM_SEARCHBOX] = "<label for=\"zoom_searchbox\" id=\"zoom_searchbox_label\">$STR_FORM_SEARCHFOR</label>\n"; 1412 $OutputBuffers[$OUTPUT_FORM_SEARCHBOX] .= "<input type=\"text\" name=\"zoom_query\" size=\"15\" value=\"".htmlspecialchars($query, ENT_COMPAT, $Charset)."\" id=\"zoom_searchbox\" class=\"zoom_searchbox\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" />\n"; 1413 $OutputBuffers[$OUTPUT_FORM_SEARCHBUTTON] = "<input type=\"submit\" value=\"" . $STR_FORM_SUBMIT_BUTTON . "\" class=\"zoom_button\" />\n"; 1414 if ($FormFormat == 2) 1415 { 1416 $OutputBuffers[$OUTPUT_FORM_RESULTSPERPAGE] = "<span class=\"zoom_results_per_page\"><label for=\"zoom_per_page\">" . $STR_FORM_RESULTS_PER_PAGE . "</label>\n"; 1417 $OutputBuffers[$OUTPUT_FORM_RESULTSPERPAGE] .= "<select name=\"zoom_per_page\" id=\"zoom_per_page\">\n"; 1418 reset($PerPageOptions); 1419 foreach ($PerPageOptions as $ppo) 1420 { 1421 $OutputBuffers[$OUTPUT_FORM_RESULTSPERPAGE] .= "<option"; 1422 if ($ppo == $per_page) 1423 $OutputBuffers[$OUTPUT_FORM_RESULTSPERPAGE] .= " selected=\"selected\""; 1424 $OutputBuffers[$OUTPUT_FORM_RESULTSPERPAGE] .= ">". $ppo ."</option>\n"; 1425 } 1426 $OutputBuffers[$OUTPUT_FORM_RESULTSPERPAGE] .= "</select><br /><br /></span>\n"; 1427 if ($UseCats) 1428 { 1429 $OutputBuffers[$OUTPUT_FORM_CATEGORIES] = "<span class=\"zoom_categories\"><label for=\"zoom_cat\">" . $STR_FORM_CATEGORY . "</label>"; 1430 if ($SearchMultiCats) 1431 { 1432 $OutputBuffers[$OUTPUT_FORM_CATEGORIES] .= "<ul>\n"; 1433 $OutputBuffers[$OUTPUT_FORM_CATEGORIES] .= "<li><input type=\"checkbox\" name=\"zoom_cat[]\" value=\"-1\" id=\"zoom_cat-1\""; 1434 if ($cat[0] == -1) 1435 $OutputBuffers[$OUTPUT_FORM_CATEGORIES] .= " checked=\"checked\""; 1436 $OutputBuffers[$OUTPUT_FORM_CATEGORIES] .= " /><label for=\"zoom_cat-1\">$STR_FORM_CATEGORY_ALL</label></li>\n"; 1437 for ($i = 0; $i < $NumCats; $i++) 1438 { 1439 $OutputBuffers[$OUTPUT_FORM_CATEGORIES] .= "<li><input type=\"checkbox\" name=\"zoom_cat[]\" value=\"$i\" id=\"zoom_cat".$i."\""; 1440 if ($cat[0] != -1) 1441 { 1442 for ($catit = 0; $catit < $num_zoom_cats; $catit++) 1443 { 1444 if ($i == $cat[$catit]) 1445 { 1446 $OutputBuffers[$OUTPUT_FORM_CATEGORIES] .= " checked=\"checked\""; 1447 break; 1448 } 1449 } 1450 } 1451 $OutputBuffers[$OUTPUT_FORM_CATEGORIES] .= " /><label for=\"zoom_cat".$i."\">$catnames[$i]</label></li>\n"; 1452 } 1453 $OutputBuffers[$OUTPUT_FORM_CATEGORIES] .= "</ul><br /><br /></span>\n"; 1454 } 1455 else 1456 { 1457 $OutputBuffers[$OUTPUT_FORM_CATEGORIES] .= "<select name=\"zoom_cat[]\" id=\"zoom_cat\">"; 1458 // 'all cats option 1459 $OutputBuffers[$OUTPUT_FORM_CATEGORIES] .= "<option value=\"-1\">" . $STR_FORM_CATEGORY_ALL . "</option>"; 1460 for($i = 0; $i < $NumCats; $i++) { 1461 $OutputBuffers[$OUTPUT_FORM_CATEGORIES] .= "<option value=\"". $i . "\""; 1462 if ($i == $cat[0]) 1463 $OutputBuffers[$OUTPUT_FORM_CATEGORIES] .= " selected=\"selected\""; 1464 $OutputBuffers[$OUTPUT_FORM_CATEGORIES] .= ">". $catnames[$i] . "</option>"; 1465 } 1466 $OutputBuffers[$OUTPUT_FORM_CATEGORIES] .= "</select> \n"; 1467 } 1468 $OutputBuffers[$OUTPUT_FORM_CATEGORIES] .= "</span>\n"; 1469 } 1470 if ($UseMetaFields) 1471 { 1472 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] = "<span class=\"zoom_metaform\">\n"; 1473 for ($fieldnum = 0; $fieldnum < $NumMetaFields; $fieldnum++) 1474 { 1475 $labelID = "zoom_metaform_".$metafields[$fieldnum][$METAFIELD_NAME]; 1476 if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_NUMERIC) 1477 { 1478 // TODO: sensible label for names without clashing with common html stuff 1479 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= "<label for=\"".$labelID."\">" . $metafields[$fieldnum][$METAFIELD_FORM] . ": </label>"; 1480 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= "<input type=\"text\" id=\"".$labelID."\" name=\"".$metafields[$fieldnum][$METAFIELD_NAME]."\" size=\"20\" value=\"".$meta_query[$fieldnum]."\" class=\"zoom_metaform_numeric\" />\n"; 1481 } 1482 else if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_DROPDOWN) 1483 { 1484 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= "<label for=\"".$labelID."\">" . $metafields[$fieldnum][$METAFIELD_FORM] . ": </label>"; 1485 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= "<select id=\"".$labelID."\" name=\"".$metafields[$fieldnum][$METAFIELD_NAME]."\" class=\"zoom_metaform_dropdown\">\n"; 1486 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= "<option value=\"-1\">" . $STR_FORM_CATEGORY_ALL . "</option>"; 1487 $ddi = 0; 1488 foreach ($metafields[$fieldnum][$METAFIELD_DROPDOWN] as $ddv) 1489 { 1490 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= "<option value=\"" . $ddi . "\""; 1491 if ($ddi == floatval($meta_query[$fieldnum])) 1492 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= " selected=\"selected\""; 1493 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= ">". $ddv ."</option>\n"; 1494 $ddi++; 1495 } 1496 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= "</select>\n"; 1497 } 1498 else if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_MULTI) 1499 { 1500 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= "<label for=\"".$labelID."\">" . $metafields[$fieldnum][$METAFIELD_FORM] . ": </label>"; 1501 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= "<select multiple id=\"".$labelID."\" name=\"".$metafields[$fieldnum][$METAFIELD_NAME]."[]\" class=\"zoom_metaform_multi\">\n"; 1502 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= "<option value=\"-1\">" . $STR_FORM_CATEGORY_ALL . "</option>"; 1503 $ddi = 0; 1504 $num_multi_query = 0; 1505 if (is_array($meta_query[$fieldnum])) 1506 $num_multi_query = count($meta_query[$fieldnum]); 1507 foreach ($metafields[$fieldnum][$METAFIELD_DROPDOWN] as $ddv) 1508 { 1509 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= "<option value=\"" . $ddi . "\""; 1510 for ($mqi = 0; $mqi < $num_multi_query; $mqi++) 1511 { 1512 if ($ddi == intval($meta_query[$fieldnum][$mqi])) 1513 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= " selected=\"selected\""; 1514 } 1515 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= ">". $ddv ."</option>\n"; 1516 $ddi++; 1517 } 1518 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= "</select>\n"; 1519 } 1520 else if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_MONEY) 1521 { 1522 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= "<label for=\"".$labelID."\">" . $metafields[$fieldnum][$METAFIELD_FORM] . ": </label>"; 1523 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= $MetaMoneyCurrency . "<input type=\"text\" id=\"".$labelID."\" name=\"".$metafields[$fieldnum][$METAFIELD_NAME]."\" size=\"7\" value=\"".$meta_query[$fieldnum]."\" class=\"zoom_metaform_money\" />\n"; 1524 } 1525 else 1526 { 1527 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= "<label for=\"".$labelID."\">" . $metafields[$fieldnum][$METAFIELD_FORM] . ": </label>"; 1528 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= "<input type=\"text\" id=\"".$labelID."\" name=\"".$metafields[$fieldnum][$METAFIELD_NAME]."\" size=\"20\" value=\"".$meta_query[$fieldnum]."\" class=\"zoom_metaform_text\" />\n"; 1529 } 1530 } 1531 $OutputBuffers[$OUTPUT_FORM_CUSTOMMETA] .= "</span>\n"; 1532 } 1533 $OutputBuffers[$OUTPUT_FORM_MATCH] = "<span class=\"zoom_match\"><label for=\"zoom_match\">" . $STR_FORM_MATCH . " </label>\n"; 1534 if ($and == 0) { 1535 $OutputBuffers[$OUTPUT_FORM_MATCH] .= "<label for=\"zoom_match_any\" class=\"zoom_and_label\" id=\"zoom_and_label_any\"><input type=\"radio\" id=\"zoom_match_any\" name=\"zoom_and\" value=\"0\" checked=\"checked\" />" . $STR_FORM_ANY_SEARCH_WORDS . "</label>\n"; 1536 $OutputBuffers[$OUTPUT_FORM_MATCH] .= "<label for=\"zoom_match_all\" class=\"zoom_and_label\" id=\"zoom_and_label_all\"><input type=\"radio\" id=\"zoom_match_all\" name=\"zoom_and\" value=\"1\" />" . $STR_FORM_ALL_SEARCH_WORDS . "</label>\n"; 1537 } else { 1538 $OutputBuffers[$OUTPUT_FORM_MATCH] .= "<label for=\"zoom_match_any\" class=\"zoom_and_label\" id=\"zoom_and_label_any\"><input type=\"radio\" id=\"zoom_match_any\" name=\"zoom_and\" value=\"0\" />" . $STR_FORM_ANY_SEARCH_WORDS . "</label>\n"; 1539 $OutputBuffers[$OUTPUT_FORM_MATCH] .= "<label for=\"zoom_match_all\" class=\"zoom_and_label\" id=\"zoom_and_label_all\"><input type=\"radio\" id=\"zoom_match_all\" name=\"zoom_and\" value=\"1\" checked=\"checked\" />" . $STR_FORM_ALL_SEARCH_WORDS . "</label>\n"; 1540 } 1541 $OutputBuffers[$OUTPUT_FORM_START] .= "<input type=\"hidden\" name=\"zoom_sort\" value=\"" . $sort . "\" />\n"; 1542 $OutputBuffers[$OUTPUT_FORM_MATCH] .= "<br /><br /></span>\n"; 1543 1544 if ($DateRangeSearch == 1) 1545 { 1546 $OutputBuffers[$OUTPUT_FORM_DATERANGE] = "<span class=\"zoom_daterange\">\n"; 1547 if ($DateRangeFormat == 1) 1548 $dateformatStr = "mdy"; 1549 else 1550 $dateformatStr = "dmy"; 1551 $OutputBuffers[$OUTPUT_FORM_DATERANGE] .= "<label for=\"zoom_datefrom\">". $STR_FORM_DATE_FROM . " </label><input id=\"zoom_datefrom\" name=\"zoom_datefrom\" value=\"".$date_from."\"><input type=\"button\" value=\"".$STR_FORM_DATE_BUTTON."\" onclick=\"displayDatePicker('zoom_datefrom', false, '".$dateformatStr."');\" />"; 1552 $OutputBuffers[$OUTPUT_FORM_DATERANGE] .= "<label for=\"zoom_dateto\">".$STR_FORM_DATE_TO . " </label><input id=\"zoom_dateto\" name=\"zoom_dateto\" value=\"".$date_to."\"><input type=\"button\" value=\"".$STR_FORM_DATE_BUTTON."\" onclick=\"displayDatePicker('zoom_dateto', false, '".$dateformatStr."');\" />"; 1553 $OutputBuffers[$OUTPUT_FORM_DATERANGE] .= "</span>"; 1554 } 1555 } 1556 else 1557 { 1558 $OutputBuffers[$OUTPUT_FORM_START] .= "<input type=\"hidden\" name=\"zoom_per_page\" value=\"" . $per_page . "\" />\n"; 1559 $OutputBuffers[$OUTPUT_FORM_START] .= "<input type=\"hidden\" name=\"zoom_and\" value=\"" . $and . "\" />\n"; 1560 $OutputBuffers[$OUTPUT_FORM_START] .= "<input type=\"hidden\" name=\"zoom_sort\" value=\"" . $sort . "\" />\n"; 1561 } 1562 } 1563 1564 // Give up early if no search words provided 1565 $IsNoKeywordQuery = false; 1566 if (empty($query)) 1567 { 1568 $NoSearch = false; 1569 if ($UseMetaFields == 1) 1570 { 1571 if ($IsZoomQuery == 1) 1572 $IsNoKeywordQuery = true; 1573 else 1574 $NoSearch = true; 1575 } 1576 else 1577 { 1578 // only display 'no query' line if no form is shown 1579 if ($IsZoomQuery == 1) 1580 { 1581 $OutputBuffers[$OUTPUT_SUMMARY] .= "<div class=\"summary\">" . $STR_NO_QUERY . "</div>"; 1582 } 1583 1584 $NoSearch = true; 1585 } 1586 if ($NoSearch) 1587 { 1588 //Let others know about Zoom. 1589 if ($ZoomInfo == 1) 1590 $OutputBuffers[$OUTPUT_PAGENUMBERS] .= "<center><p><small>" . $STR_POWEREDBY . " <a href=\"http://www.wrensoft.com/zoom/\" target=\"_blank\"><b>Zoom Search Engine</b></a></small></p></center>"; 1591 1592 ShowTemplate(); 1593 return; 1594 } 1595 } 1596 1597 // Prepare query for search --------------------------------------------------- 1598 1599 if ($MapAccents == 1) { 1600 $query = str_replace($AccentChars, $NormalChars, $query); 1601 } 1602 1603 // Special query processing required when SearchAsSubstring is enabled 1604 if ($SearchAsSubstring == 1 && $UseUTF8 == 1) 1605 $query = FixQueryForAsianWords($query); 1606 1607 1608 // prepare search query, strip quotes, trim whitespace 1609 if ($AllowExactPhrase == 0) 1610 { 1611 $query = str_replace("\"", " ", $query); 1612 } 1613 if (strspn(".", $WordJoinChars) == 0) 1614 $query = str_replace(".", " ", $query); 1615 1616 if (strspn("-", $WordJoinChars) == 0) 1617 $query = preg_replace("/(\S)-/", "$1 ", $query); 1618 1619 if (strspn("#", $WordJoinChars) == 0) 1620 $query = preg_replace("/#(\S)/", " $1", $query); 1621 1622 if (strspn("+", $WordJoinChars) == 0) 1623 { 1624 $query = preg_replace("/[\+]+([^\+\s])/", " $1", $query); 1625 $query = preg_replace("/([^\+\s])\+\s/", "$1 ", $query); 1626 $query = preg_replace("/\s\+\s/", " ", $query); 1627 } 1628 1629 if (strspn("_", $WordJoinChars) == 0) 1630 $query = str_replace("_", " ", $query); 1631 1632 if (strspn("'", $WordJoinChars) == 0) 1633 $query = str_replace("'", " ", $query); 1634 1635 if (strspn("$", $WordJoinChars) == 0) 1636 $query = str_replace("$", " ", $query); 1637 1638 if (strspn(",", $WordJoinChars) == 0) 1639 $query = str_replace(",", " ", $query); 1640 1641 if (strspn(":", $WordJoinChars) == 0) 1642 { 1643 // We temporarily replace the search syntax for "site:" and "url:" 1644 // to avoid stripping it out when colon is disabled for word join 1645 $query = str_replace("site:", "[#@!]", $query); 1646 $query = str_replace("url:", "[#@]", $query); 1647 $query = str_replace(":", " ", $query); 1648 1649 // We then restore it 1650 $query = str_replace("[#@!]", "site:", $query); 1651 $query = str_replace("[#@]", "url:", $query); 1652 } 1653 1654 if (strspn("&", $WordJoinChars) == 0) 1655 $query = str_replace("&", " ", $query); 1656 1657 if (strspn("/", $WordJoinChars) == 0) 1658 $query = str_replace("/", " ", $query); 1659 1660 if (strspn("\\", $WordJoinChars) == 0) 1661 $query = str_replace("\\", " ", $query); 1662 1663 if (strspn("@", $WordJoinChars) == 0) 1664 $query = str_replace("@", " ", $query); 1665 1666 // strip consecutive spaces, parenthesis, etc. 1667 // also strip any of the wordjoinchars if followed immediately by a space 1668 $query = preg_replace("/[\s\(\)\^\[\]\|\{\}\%\!]+|[\-._',:&\/\\\](\s|$)/", " ", $query); 1669 $query = trim($query); 1670 1671 $queryForHTML = htmlspecialchars($query, ENT_COMPAT, $Charset); 1672 if ($ToLowerSearchWords == 1) 1673 { 1674 if ($UseUTF8 == 1 && $UseMBFunctions == 1) 1675 $queryForSearch = mb_strtolower($query, "UTF-8"); 1676 else 1677 $queryForSearch = strtolower($query); 1678 } 1679 else 1680 $queryForSearch = $query; 1681 1682 //Split search phrase into words 1683 preg_match_all("/\"(.*?)\"|\-\"(.*?)\"|[^\\s\"]+/", $queryForSearch, $SearchWords); 1684 $SearchWords = preg_replace("/\"[\s]+|[\s]+\"|\"/", "", $SearchWords[0]); 1685 1686 //Sort search words if there are negative signs 1687 if (strpos($queryForSearch, "-") !== false) 1688 usort($SearchWords, "sw_compare"); 1689 1690 $NumSearchWords = count ($SearchWords); 1691 1692 // Load index data files (*.zdat) --------------------------------------------- 1693 1694 if ($IsZoomAC == 1) 1695 { 1696 $fp_ac = fopen($AUTOCOMPLETEFILE, "rt"); 1697 $ac_count = 0; 1698 while (!feof($fp_ac)) 1699 { 1700 $acline = trim(fgets($fp_ac, $MaxKeyWordLineLen)); 1701 if (strlen($acline) > 0) 1702 { 1703 for ($sw = 0; $sw < $NumSearchWords; $sw++) 1704 { 1705 if (strncasecmp($acline, $SearchWords[$sw], strlen($SearchWords[$sw])) == 0) 1706 { 1707 $ZoomACOutput .= "<div class=\"zoom_ac_item\" onclick=\"ZoomAutoComplete_UseSuggestion('$acline');\"><a class=\"zoom_ac_item\" href=\"#\">" . $acline . "</a></div>\n"; 1708 $ac_count++; 1709 } 1710 } 1711 } 1712 } 1713 fclose($fp_ac); 1714 print($ZoomACOutput); 1715 exit(0); 1716 } 1717 1718 // Open pagetext file 1719 if ($DisplayContext == 1 || $AllowExactPhrase == 1) 1720 { 1721 $fp_pagetext = fopen($PAGETEXTFILE, "rb"); 1722 if ($fp_pagetext === FALSE) 1723 { 1724 $OutputResultsBuffer .= "<b>Zoom config error:</b> Failed to open zoom_pagetext.zdat file.<br />"; 1725 return; 1726 } 1727 $teststr = fgets($fp_pagetext, 8); 1728 if ($teststr[0] == "T" && $teststr[2] == "h" && $teststr[4] == "i" && $teststr[6] == "s") 1729 { 1730 $OutputResultsBuffer .= "<b>Zoom config error:</b> The zoom_pagetext.zdat file is not properly created for the search settings specified.<br />Please check that you have re-indexed your site with the search settings selected in the configuration window.<br />"; 1731 fclose($fp_pagetext); 1732 return; 1733 } 1734 } 1735 1736 // Open recommended link file 1737 if ($Recommended == 1) 1738 { 1739 $fp_rec = fopen($RECOMMENDEDFILE, "rt"); 1740 $i = 0; 1741 while (!feof($fp_rec)) 1742 { 1743 $recline = fgets($fp_rec, $MaxKeyWordLineLen); 1744 if (strlen($recline) > 0) 1745 { 1746 $sep = strrpos($recline, " "); 1747 if ($sep !== false) 1748 { 1749 $rec[$i][0] = substr($recline, 0, $sep); 1750 $rec[$i][1] = substr($recline, $sep); 1751 $i++; 1752 } 1753 } 1754 } 1755 fclose($fp_rec); 1756 $rec_count = $i; 1757 } 1758 1759 //Open pageinfo file 1760 $fp_pageinfo = fopen($PAGEINFOFILE, "rb"); 1761 $pageinfo_count = $NumPages; 1762 $rec_headersize = 2+5+4+4+1+1; 1763 for ($i = 0; !feof($fp_pageinfo) && $i < $pageinfo_count; $i++) 1764 { 1765 $bytes_buffer = fread($fp_pageinfo, $rec_headersize); 1766 $pageinfo[$i] = unpack("vrecsize/Vdataoffset/CextraByte/Vfilesize/Vdatetime/cboost/Cfiletype", $bytes_buffer); 1767 1768 if ($UseCats == 1 && $NumCatBytes > 0) 1769 { 1770 $catpages[$i] = array(); 1771 for ($byte = 0; $byte < $NumCatBytes; $byte++) 1772 $catpages[$i][$byte] = GetBytes($fp_pageinfo, 1); 1773 } 1774 1775 if ($UseMetaFields == 1) 1776 { 1777 for ($fieldnum = 0; $fieldnum < $NumMetaFields; $fieldnum++) 1778 { 1779 if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_TEXT) 1780 { 1781 $valueSize = GetBytes($fp_pageinfo, 1); 1782 if ($valueSize > 0 && $valueSize != $METAFIELD_NOVALUE_MARKER) 1783 $metavalues[$i][$fieldnum] = fread($fp_pageinfo, $valueSize); 1784 else 1785 $metavalues[$i][$fieldnum] = ""; 1786 } 1787 else if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_DROPDOWN) 1788 { 1789 // read in one byte 1790 $metavalues[$i][$fieldnum] = GetBytes($fp_pageinfo, 1); 1791 } 1792 else if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_MULTI) 1793 { 1794 // read in one byte count then variable bytes 1795 $valueSize = GetBytes($fp_pageinfo, 1); 1796 if ($valueSize > 0 && $valueSize != $METAFIELD_NOVALUE_MARKER) 1797 { 1798 $tmpMultiValues = array($valueSize); 1799 for ($mvi = 0; $mvi < $valueSize; $mvi++) 1800 array_push($tmpMultiValues, GetBytes($fp_pageinfo, 1)); 1801 $metavalues[$i][$fieldnum] = $tmpMultiValues; 1802 } 1803 else 1804 $metavalues[$i][$fieldnum] = $valueSize;// this will be METAFIELD_NOVALUE_MARKER 1805 } 1806 else 1807 { 1808 // numeric meta field type 1809 $metavalues[$i][$fieldnum] = (double)GetBytes($fp_pageinfo, 4); 1810 } 1811 } 1812 } 1813 } 1814 1815 if ($Recommended == 1) 1816 $i += $rec_count; // take into account the recommended links before verifying 1817 if ($i < $NumPages) 1818 { 1819 $OutputResultsBuffer .= ("<b>Zoom config error</b>: The zoom_pageinfo.zdat file is invalid or not up-to-date. Please make sure you have uploaded all files from the same indexing session.<br />"); 1820 $UseDateTime = 0; 1821 $UseZoomImage = 0; 1822 $DisplayFilesize = 0; 1823 } 1824 fclose($fp_pageinfo); 1825 1826 // Open pagedata file 1827 $fp_pagedata = fopen($PAGEDATAFILE, "rb"); 1828 1829 // Open wordmap file 1830 $fp_wordmap = fopen($WORDMAPFILE, "rb"); 1831 1832 // Open dictionary file 1833 $fp_dict = fopen($DICTIONARYFILE, "rb"); 1834 $i = 0; 1835 while (!feof($fp_dict)) 1836 { 1837 $dictline = fgets($fp_dict, $MaxKeyWordLineLen); 1838 if (strlen($dictline) > 0) 1839 { 1840 $dict[$i] = explode(" ", $dictline, 3); 1841 if (isset($dict[$i][$DICT_VARCOUNT])) 1842 { 1843 if ($dict[$i][$DICT_VARCOUNT] > 0) 1844 { 1845 $variantsArray = array(); 1846 // variants available 1847 for ($vi = 0; $vi < $dict[$i][$DICT_VARCOUNT]; $vi++) 1848 { 1849 $variantsArray[$vi] = rtrim(fgets($fp_dict, $MaxKeyWordLineLen)); 1850 } 1851 $dict[$i][$DICT_VARIANTS] = $variantsArray; 1852 } 1853 } 1854 $i++; 1855 } 1856 } 1857 fclose($fp_dict); 1858 $dict_count = $i; 1859 1860 $query_zoom_cats = ""; 1861 1862 //Print heading 1863 $OutputBuffers[$OUTPUT_HEADING] .= "<div class=\"searchheading\">" . $STR_RESULTS_FOR . " " . $queryForHTML; 1864 if ($UseCats) 1865 { 1866 if ($cat[0] == -1) 1867 { 1868 $OutputBuffers[$OUTPUT_HEADING] .= " " . $STR_RESULTS_IN_ALL_CATEGORIES; 1869 $query_zoom_cats = "&zoom_cat%5B%5D=-1"; 1870 } 1871 else 1872 { 1873 $OutputBuffers[$OUTPUT_HEADING] .= " " . $STR_RESULTS_IN_CATEGORY . " "; 1874 for ($catit = 0; $catit < $num_zoom_cats; $catit++) 1875 { 1876 if ($catit > 0) 1877 $OutputBuffers[$OUTPUT_HEADING] .= ", "; 1878 $OutputBuffers[$OUTPUT_HEADING] .= "\"". rtrim($catnames[$cat[$catit]]) . "\""; 1879 $query_zoom_cats .= "&zoom_cat%5B%5D=".$cat[$catit]; 1880 } 1881 } 1882 } 1883 $OutputBuffers[$OUTPUT_HEADING] .= "<br /><br /></div>\n"; 1884 1885 $OutputResultsBuffer .= "<div class=\"results\">\n"; 1886 1887 // Begin main search loop ----------------------------------------------------- 1888 1889 //$pagesCount = count($urls); 1890 $pagesCount = $NumPages; 1891 $outputline = 0; 1892 $IsMaxLimitExceeded = 0; 1893 $wordsmatched = 0; 1894 1895 // Initialise $res_table to be a 2D array of count($pages) long, filled with zeros. 1896 //$res_table = array_fill(0, $pagesCount, array_fill(0, 6, 0)); 1897 $res_table = array(); 1898 for ($i = 0; $i < $pagesCount; $i++) 1899 { 1900 $res_table[$i] = array(); 1901 $res_table[$i][0] = 0; // score 1902 $res_table[$i][1] = 0; // num of sw matched 1903 $res_table[$i][2] = 0; // pagetext ptr #1 1904 $res_table[$i][3] = 0; // pagetext ptr #2 1905 $res_table[$i][4] = 0; // pagetext ptr #3 1906 $res_table[$i][5] = 0; // 'and' user search terms matched 1907 $res_table[$i][6] = 0; // combined prox field 1908 } 1909 1910 if (isset($UseDomainDiversity) && $UseDomainDiversity == 1) 1911 { 1912 $MaxDomainDiversity = 3; 1913 $div_res_table = array($MaxDomainDiversity); 1914 $div_res_urls = array($MaxDomainDiversity); 1915 $div_res_count = 0; 1916 } 1917 else 1918 $UseDomainDiversity = 0; 1919 1920 $exclude_count = 0; 1921 1922 // check if word is in skipword file 1923 $SkippedWords = 0; 1924 $context_maxgoback = 1; 1925 $SkippedExactPhrase = 0; 1926 $maxscore = 0; 1927 1928 // queryForURL is the query prepared to be passed in a URL. 1929 $queryForURL = urlencode($query); 1930 1931 // Find recommended links if any (before stemming) 1932 $num_recs_found = 0; 1933 if ($Recommended == 1) 1934 { 1935 for ($rl = 0; $rl < $rec_count && $num_recs_found < $RecommendedMax; $rl++) 1936 { 1937 $rec_word = $rec[$rl][0]; 1938 $rec_idx = intval($rec[$rl][1]); 1939 if (strchr($rec_word, ',')) 1940 { 1941 $rec_multiwords = explode(",", $rec_word); 1942 $rec_multiwords_count = count($rec_multiwords); 1943 for ($rlm = 0; $rlm < $rec_multiwords_count; $rlm++) 1944 { 1945 if (RecLinkWordMatch($rec_multiwords[$rlm], $rec_idx) == true) 1946 break; 1947 } 1948 } 1949 else 1950 RecLinkWordMatch($rec_word, $rec_idx); 1951 } 1952 if ($num_recs_found > 0) 1953 $OutputBuffers[$OUTPUT_RECOMMENDED] .= "</div>"; 1954 } 1955 1956 $searchUrlBuffer = ""; 1957 1958 // Prepopulate some data for each searchword 1959 $sw_results = array(); 1960 $search_terms_ids = array(); 1961 $phrase_terms_ids = array(); 1962 for ($sw = 0; $sw < $NumSearchWords; $sw++) 1963 { 1964 $sw_results[$sw] = 0; 1965 $UseWildCards[$sw] = 0; 1966 1967 // for main search terms 1968 $search_terms_ids[$sw] = array(); 1969 // for exact phrases 1970 $phrase_terms_ids[$sw] = array(); 1971 1972 if (strpos($SearchWords[$sw], "*") !== false || strpos($SearchWords[$sw], "?") !== false) 1973 { 1974 $RegExpSearchWords[$sw] = pattern2regexp($SearchWords[$sw]); 1975 $UseWildCards[$sw] = 1; 1976 } 1977 1978 if ($Highlighting == 1 && $UseWildCards[$sw] == 0) 1979 { 1980 $RegExpSearchWords[$sw] = $SearchWords[$sw]; 1981 if (strpos($RegExpSearchWords[$sw], "\\") !== false) 1982 $RegExpSearchWords[$sw] = str_replace("\\", "\\\\", $RegExpSearchWords[$sw]); 1983 if (strpos($RegExpSearchWords[$sw], "/") !== false) 1984 $RegExpSearchWords[$sw] = str_replace("/", "\/", $RegExpSearchWords[$sw]); 1985 if (strpos($RegExpSearchWords[$sw], "+") !== false) 1986 $RegExpSearchWords[$sw] = str_replace("+", "\+", $RegExpSearchWords[$sw]); 1987 } 1988 } 1989 1990 for ($sw = 0; $sw < $NumSearchWords; $sw++) 1991 { 1992 if ($SearchWords[$sw] == "") 1993 continue; 1994 1995 // check min length 1996 if (strlen($SearchWords[$sw]) < $MinWordLen) 1997 { 1998 SkipSearchWord($sw); 1999 continue; 2000 } 2001 2002 $ExactPhrase = 0; 2003 $ExcludeTerm = 0; 2004 2005 // Check exclusion searches 2006 if ($SearchWords[$sw][0] == "-") 2007 { 2008 $SearchWords[$sw] = substr($SearchWords[$sw], 1); 2009 $ExcludeTerm = 1; 2010 $exclude_count++; 2011 } 2012 2013 $colonPos = 0; 2014 // check if this is a search option (e.g. "site:mysite.com") 2015 if (($colonPos = strpos($SearchWords[$sw], ':')) !== FALSE) 2016 { 2017 if (strncmp($SearchWords[$sw], "site:", 5) == 0 || strncmp($SearchWords[$sw], "url:", 4) == 0) 2018 { 2019 $searchUrlBuffer = substr($SearchWords[$sw], $colonPos+1); 2020 $exclude_count++; 2021 // if this site: term is the only search term in the query, then we enable 2022 // empty query behaviour (so we return all results) 2023 if ($NumSearchWords == 1) 2024 { 2025 $IsNoKeywordQuery = true; 2026 // we need to break out of the loop here and not continue searching through 2027 // the dictionary (and waste time) when there's no word to look up! 2028 // we'll continue to the top of the loop (where the while condition will break 2029 // since IsNoKeywordQuery is flagged) 2030 continue; 2031 } 2032 } 2033 } 2034 2035 // Stem the words if necessary (only AFTER stripping exclusion char) 2036 if ($UseStemming == 1) 2037 { 2038 if ($AllowExactPhrase == 0 || strpos($SearchWords[$sw], " ") === false) 2039 $SearchWords[$sw] = $porterStemmer->Stem($SearchWords[$sw]); 2040 } 2041 2042 if ($AllowExactPhrase == 1 && strpos($SearchWords[$sw], " ") !== false) 2043 { 2044 // Initialise exact phrase matching for this search term 2045 $ExactPhrase = 1; 2046 $phrase_terms = explode(" ", $SearchWords[$sw]); 2047 //$phrase_terms = preg_split("/\W+/", $SearchWords[$sw], -1, 0 /*PREG_SPLIT_DELIM_CAPTURE*/); 2048 $num_phrase_terms = count($phrase_terms); 2049 if ($num_phrase_terms > $context_maxgoback) 2050 $context_maxgoback = $num_phrase_terms; 2051 2052 $phrase_terms_data = array(); 2053 2054 if ($UseStemming == 1) 2055 { 2056 for ($j = 0; $j < $num_phrase_terms; $j++) 2057 $phrase_terms[$j] = $porterStemmer->Stem($phrase_terms[$j]); 2058 } 2059 2060 $tmpid = 0; 2061 $WordNotFound = 0; 2062 $j = 0; 2063 for ($j = 0; $j < $num_phrase_terms; $j++) 2064 { 2065 $tmpid = GetDictID($phrase_terms[$j]); 2066 if ($tmpid == -1) // word is not in dictionary 2067 { 2068 $WordNotFound = 1; 2069 break; 2070 } 2071 $phrase_terms_ids[$sw][$j] = $tmpid; 2072 2073 $wordmap_row = $dict[$tmpid][$DICT_PTR]; 2074 if ($wordmap_row != -1) 2075 { 2076 fseek($fp_wordmap, $wordmap_row); 2077 $countbytes = fread($fp_wordmap, 2); 2078 $phrase_data_count[$j] = ord($countbytes[0]) | ord($countbytes[1])<<8; 2079 for ($xbi = 0; $xbi < $phrase_data_count[$j]; $xbi++) { 2080 $xbindata = fread($fp_wordmap, 8); 2081 if (strlen($xbindata) == 0) 2082 $OutputResultsBuffer .= "error in wordmap file: expected data not found"; 2083 $phrase_terms_data[$j][$xbi] = unpack("Cscore/Cprox/vpagenum/Vptr", $xbindata); 2084 } 2085 } 2086 else 2087 { 2088 $phrase_data_count[$j] = 0; 2089 $phrase_terms_data[$j] = 0; 2090 } 2091 } 2092 $phrase_terms_ids[$sw][$j] = 0; // null terminate the list 2093 2094 if ($WordNotFound == 1) 2095 continue; 2096 } 2097 else if ($UseWildCards[$sw]) 2098 { 2099 $pattern = "/"; 2100 2101 // match entire word 2102 if ($SearchAsSubstring == 0) 2103 $pattern = $pattern . "\A"; 2104 2105 $pattern = $pattern . $RegExpSearchWords[$sw]; 2106 2107 if ($SearchAsSubstring == 0) 2108 $pattern = $pattern . "\Z"; 2109 2110 if ($ToLowerSearchWords != 0) 2111 $pattern = $pattern . "/i"; 2112 else 2113 $pattern = $pattern . "/"; 2114 } 2115 2116 for ($i = 0; $i < $dict_count; $i++) 2117 { 2118 $dictline = $dict[$i]; 2119 $word = $dict[$i][$DICT_WORD]; 2120 2121 // if we're not using wildcards, direct match 2122 if ($ExactPhrase == 1) 2123 { 2124 // todo: move to next phrase term if first phrase term is skipped? 2125 // compare first term in exact phrase 2126 //$result = wordcasecmp($phrase_terms[0], $word); 2127 if ($i == $phrase_terms_ids[$sw][0]) 2128 $result = 0; 2129 else 2130 $result = 1; 2131 } 2132 else if ($UseWildCards[$sw] == 1) 2133 { 2134 // if we have wildcards... 2135 $result = 1; // set to not matched before loop 2136 if (isset($dict[$i][$DICT_VARCOUNT])) 2137 { 2138 for ($variant_index = 1; $result != 0 && $variant_index <= $dict[$i][$DICT_VARCOUNT]; $variant_index++) 2139 { 2140 $variant_word = GetDictionaryWord($i, $variant_index); 2141 $result = !(preg_match($pattern, $variant_word)); 2142 } 2143 } 2144 } 2145 else 2146 { 2147 if ($SearchAsSubstring == 0) 2148 $result = wordcasecmp($SearchWords[$sw], $word); 2149 else 2150 { 2151 if (mystristr($word, $SearchWords[$sw]) == FALSE) 2152 $result = 1; // not matched 2153 else 2154 $result = 0; // matched 2155 } 2156 } 2157 2158 // result = 0 if matched, result != 0 if not matched. 2159 2160 // word found but indicated to be not indexed or skipped 2161 if ($result == 0 && (is_numeric($dictline[$DICT_PTR]) == false || $dictline[$DICT_PTR] == -1)) 2162 { 2163 if ($UseWildCards[$sw] == 0 && $SearchAsSubstring == 0) 2164 { 2165 if ($ExactPhrase == 1) 2166 $SkippedExactPhrase = 1; 2167 2168 SkipSearchWord($sw); 2169 break; 2170 } 2171 else 2172 continue; 2173 } 2174 2175 if ($result == 0) 2176 { 2177 // keyword found in the dictionary 2178 $wordsmatched++; 2179 if ($ExcludeTerm == false && $wordsmatched > $MaxMatches) 2180 { 2181 $IsMaxLimitExceeded = true; 2182 break; 2183 } 2184 2185 /// remember the dictionary ID for this matched search term 2186 $search_terms_ids[$sw] = $i; 2187 2188 if ($ExactPhrase == 1) 2189 { 2190 // we'll use the wordmap data for the first term that we have worked out earlier 2191 $data = $phrase_terms_data[0]; 2192 $data_count = $phrase_data_count[0]; 2193 $ContextSeeks = 0; 2194 } 2195 else 2196 { 2197 // seek to position in wordmap file 2198 fseek($fp_wordmap, $dictline[$DICT_PTR]); 2199 //print "seeking in wordmap: " . $dictline[1] . "<br />"; 2200 2201 // first 2 bytes is data count 2202 $countbytes = fread($fp_wordmap, 2); 2203 $data_count = ord($countbytes[0]) | ord($countbytes[1])<<8; 2204 //print "data count: " . $data_count . "<br />"; 2205 2206 for ($bi = 0; $bi < $data_count; $bi++) 2207 { 2208 $bindata = fread($fp_wordmap, 8); 2209 if (strlen($bindata) == 0) 2210 $OutputResultsBuffer .= "Error in wordmap file: expected data not found"; 2211 $data[$bi] = unpack("Cscore/Cprox/vpagenum/Vptr", $bindata); 2212 } 2213 } 2214 $sw_results[$sw] += $data_count; 2215 2216 // Go through wordmap for each page this word appears on 2217 for ($j = 0; $j < $data_count; $j++) 2218 { 2219 $score = $data[$j]["score"]; 2220 $prox = $data[$j]["prox"]; 2221 $txtptr = $data[$j]["ptr"]; 2222 $ipage = $data[$j]["pagenum"]; 2223 2224 if ($score == 0) 2225 continue; 2226 2227 if ($pageinfo[$ipage]["boost"] != 0) 2228 { 2229 $score *= ($pageinfo[$ipage]["boost"] / 10); 2230 $score = ceil($score); 2231 } 2232 2233 if ($ExactPhrase == 1) 2234 { 2235 $maxptr = $data[$j]["ptr"]; 2236 $maxptr_term = 0; 2237 $GotoNextPage = 0; 2238 2239 // Check if all of the other words in the phrase appears on this page. 2240 for ($xi = 0; $xi < $num_phrase_terms && $GotoNextPage == 0; $xi++) 2241 { 2242 // see if this word appears at all on this page, if not, we stop scanning page. 2243 // do not check for skipped words (data count value of zero) 2244 if ($phrase_data_count[$xi] != 0) 2245 { 2246 // check wordmap for this search phrase to see if it appears on the current page. 2247 for ($xbi = 0; $xbi < $phrase_data_count[$xi]; $xbi++) 2248 { 2249 if ($phrase_terms_data[$xi][$xbi]["pagenum"] == $data[$j]["pagenum"]) 2250 { 2251 // make sure that words appear in same proximity 2252 2253 $overlapProx = $phrase_terms_data[$xi][$xbi]["prox"] << 1; 2254 2255 if (($data[$j]["prox"] & $phrase_terms_data[$xi][$xbi]["prox"]) == 0 && 2256 ($data[$j]["prox"] & $overlapProx) == 0) 2257 { 2258 $GotoNextPage = 1; 2259 } 2260 else 2261 { 2262 // intersection, this term appears on both pages, goto next term 2263 // remember biggest pointer. 2264 if ($phrase_terms_data[$xi][$xbi]["ptr"] > $maxptr) 2265 { 2266 $maxptr = $phrase_terms_data[$xi][$xbi]["ptr"]; 2267 $maxptr_term = $xi; 2268 } 2269 $score += $phrase_terms_data[$xi][$xbi]["score"]; 2270 } 2271 break; 2272 } 2273 } 2274 if ($xbi == $phrase_data_count[$xi]) // if not found 2275 { 2276 $GotoNextPage = 1; 2277 break; // goto next page 2278 } 2279 } 2280 } // end phrase term for loop 2281 if ($GotoNextPage == 1) 2282 { 2283 continue; 2284 } 2285 2286 // Check how many context seeks we have made. 2287 $ContextSeeks++; 2288 if ($ContextSeeks > $MaxContextSeeks) 2289 { 2290 $IsMaxLimitExceeded = true; 2291 break; 2292 } 2293 2294 // ok, so this page contains all of the words in the phrase 2295 $FoundPhrase = 0; 2296 $FoundFirstWord = 0; 2297 2298 // we goto the first occurance of the first word in pagetext 2299 $pos = $maxptr - (($maxptr_term+3) * $DictIDLen); // assume 3 possible punctuations. 2300 // do not seek further back than the occurance of the first word (avoid wrong page) 2301 if ($pos < $data[$j]["ptr"]) 2302 $pos = $data[$j]["ptr"]; 2303 2304 fseek($fp_pagetext, $pos); 2305 2306 // now we look for the phrase within the context of this page 2307 do 2308 { 2309 for ($xi = 0; $xi < $num_phrase_terms; $xi++) 2310 { 2311 // do...while loop to ignore punctuation marks in context phrase 2312 do 2313 { 2314 // Inlined (and unlooped) the following function for speed reasons 2315 //$xword_id = GetNextDictWord($fp_pagetext); 2316 $bytes_buffer = fread($fp_pagetext, $DictIDLen); 2317 if ($DictIDLen == 4) 2318 { 2319 $xword_id = ord($bytes_buffer[0]); 2320 $xword_id = $xword_id | ord($bytes_buffer[1]) << 8; 2321 $xword_id = $xword_id | ord($bytes_buffer[2]) << (8*2); 2322 $variant_index = $bytes_buffer[3]; 2323 } 2324 else 2325 { 2326 $xword_id = ord($bytes_buffer[0]); 2327 $xword_id = $xword_id | ord($bytes_buffer[1]) << 8; 2328 $variant_index = $bytes_buffer[2]; 2329 } 2330 $pos += $DictIDLen; 2331 // check if we are at the end of page (wordid = 0) or invalid $xword_id 2332 if ($xword_id == 0 || $xword_id == 1 || $xword_id >= $dict_count) 2333 break; 2334 } while ($xword_id <= $DictReservedLimit && !feof($fp_pagetext)); 2335 2336 if ($xword_id == 0 || $xword_id == 1 || $xword_id >= $dict_count) 2337 break; 2338 2339 // if the words are NOT the same, we break out 2340 if ($xword_id != $phrase_terms_ids[$sw][$xi]) 2341 { 2342 // also check against first word 2343 if ($xi != 0 && $xword_id == $phrase_terms_ids[$sw][0]) 2344 $xi = 0; // matched first word 2345 else 2346 break; 2347 } 2348 2349 // remember how many times we find the first word on this page 2350 if ($xi == 0) 2351 { 2352 $FoundFirstWord++; 2353 // remember the position of the 'start' of this phrase 2354 $txtptr = $pos - $DictIDLen; 2355 } 2356 } 2357 if ($xi == $num_phrase_terms) 2358 { 2359 // exact phrase found! 2360 $FoundPhrase = 1; 2361 } 2362 } while ($xword_id != 0 && $FoundPhrase == 0 && 2363 $FoundFirstWord <= $data[$j]["score"]); 2364 2365 if ($FoundPhrase != 1) 2366 continue; // goto next page. 2367 2368 2369 $checktime = time(); 2370 $checkTimeDiff = abs($starttime - $checktime); 2371 if ($checkTimeDiff > $MaxSearchTime) 2372 { 2373 $IsMaxLimitExceeded = true; 2374 break; 2375 } 2376 } 2377 2378 //Check if page is already in output list 2379 $pageexists = 0; 2380 2381 if ($ExcludeTerm == 1) 2382 { 2383 // we clear out the score entry so that it'll be excluded in the filtering stage 2384 $res_table[$ipage][0] = 0; 2385 } 2386 elseif ($res_table[$ipage][0] == 0) 2387 { 2388 // not in list, count this page as a unique match 2389 $res_table[$ipage][0] = $score; 2390 $res_table[$ipage][2] = $txtptr; 2391 $res_table[$ipage][6] = $prox; 2392 } 2393 else 2394 { 2395 // already in list 2396 if ($res_table[$ipage][0] > 10000) 2397 { 2398 // take it easy if its too big (to prevent huge scores) 2399 $res_table[$ipage][0] += 1; 2400 } 2401 else 2402 { 2403 $res_table[$ipage][0] += $score; //Add in score 2404 //$res_table[$ipage][0] *= 2; //Double Score as we have two words matching 2405 } 2406 2407 // store the next two searchword matches 2408 if ($res_table[$ipage][1] > 0 && $res_table[$ipage][1] < $MaxContextKeywords) 2409 { 2410 if ($res_table[$ipage][3] == 0) 2411 $res_table[$ipage][3] = $txtptr; 2412 elseif ($res_table[$ipage][4] == 0) 2413 $res_table[$ipage][4] = $txtptr; 2414 } 2415 2416 $res_table[$ipage][6] = $res_table[$ipage][6] & $prox; 2417 } 2418 $res_table[$ipage][1] += 1; 2419 2420 if ($res_table[$ipage][0] > $maxscore) 2421 $maxscore = $res_table[$ipage][0]; 2422 2423 // store the 'and' user search terms matched' value 2424 if ($res_table[$ipage][5] == $sw || $res_table[$ipage][5] == $sw-$SkippedWords-$exclude_count) 2425 $res_table[$ipage][5] += 1; 2426 } 2427 2428 if ($UseWildCards[$sw] == 0 && $SearchAsSubstring == 0) 2429 break; //This search word was found, so skip to next 2430 } 2431 } 2432 } 2433 //Close the files 2434 fclose($fp_wordmap); 2435 2436 if ($SkippedWords > 0) 2437 { 2438 $OutputBuffers[$OUTPUT_SUMMARY] .= "<div class=\"summary\">" . $STR_SKIPPED_FOLLOWING_WORDS . " " . $SkippedOutputStr . "<br />\n"; 2439 if ($SkippedExactPhrase == 1) 2440 $OutputBuffers[$OUTPUT_SUMMARY] .= $STR_SKIPPED_PHRASE . ".<br />\n"; 2441 $OutputBuffers[$OUTPUT_SUMMARY] .= "<br /></div>\n"; 2442 } 2443 2444 $metaParams = ""; 2445 // append to queryForURL with other query parameters for custom meta fields? 2446 if ($UseMetaFields == 1) 2447 { 2448 for ($fieldnum = 0; $fieldnum < $NumMetaFields; $fieldnum++) 2449 { 2450 if (is_array($meta_query[$fieldnum])) 2451 { 2452 $num_multi_query = count($meta_query[$fieldnum]); 2453 for ($mqi = 0; $mqi < $num_multi_query; $mqi++) 2454 $metaParams .= "&".$metafields[$fieldnum][$METAFIELD_NAME]."[]=".$meta_query[$fieldnum][$mqi]; 2455 } 2456 else 2457 { 2458 if ($meta_query[$fieldnum] !== "") 2459 $metaParams .= "&".$metafields[$fieldnum][$METAFIELD_NAME]."=".$meta_query[$fieldnum]; 2460 } 2461 } 2462 } 2463 2464 // Do this after search form so we can keep the search form value the same as the way the user entered it 2465 if ($UseMetaFields == 1 && $MetaMoneyShowDec == 1) 2466 { 2467 for ($fieldnum = 0; $fieldnum < $NumMetaFields; $fieldnum++) 2468 { 2469 if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_MONEY && $meta_query[$fieldnum] !== "") 2470 $meta_query[$fieldnum] = $meta_query[$fieldnum] * 100; 2471 } 2472 } 2473 2474 //Count number of output lines that match ALL search terms 2475 $oline = 0; 2476 $fullmatches = 0; 2477 $matches = 0; 2478 2479 $baseScale = 1.3; 2480 $proxScale = 1.7; 2481 if (isset($WeightProximity)) 2482 $proxScale += ($WeightProximity/10); 2483 2484 $CatCounterFilled = 0; 2485 if ($UseCats && $DisplayCatSummary == 1) 2486 { 2487 if (($cat[0] == -1 || $num_zoom_cats > 1) && $NumCats > 0) 2488 $CatCounter = array_fill(0, $NumCats, 0); 2489 else 2490 $DisplayCatSummary = 0; 2491 } 2492 2493 $dateRangeParams = ""; // append to queryForURL with other query parameters for custom meta fields? 2494 if ($DateRangeSearch == 1) 2495 { 2496 $UseDateRange = false; 2497 $tmpFromMonth = 0; 2498 $tmpFromDay = 0; 2499 $tmpFromYear = 0; 2500 $tmpToMonth = 0; 2501 $tmpToDay = 0; 2502 $tmpToYear = 0; 2503 if ($DateRangeFormat == 1) 2504 { 2505 sscanf($date_from, "%d/%d/%d", $tmpFromMonth, $tmpFromDay, $tmpFromYear); 2506 sscanf($date_to, "%d/%d/%d", $tmpToMonth, $tmpToDay, $tmpToYear); 2507 } 2508 else 2509 { 2510 sscanf($date_from, "%d/%d/%d", $tmpFromDay, $tmpFromMonth, $tmpFromYear); 2511 sscanf($date_to, "%d/%d/%d", $tmpToDay, $tmpToMonth, $tmpToYear); 2512 } 2513 if ($tmpFromDay > 0 && $tmpFromMonth > 0 && $tmpFromYear > 0 && $tmpToDay > 0 && $tmpToMonth > 0 && $tmpToYear > 0) 2514 { 2515 $from_datetime = mktime(0, 0, 0, $tmpFromMonth, $tmpFromDay, $tmpFromYear); 2516 $to_datetime = mktime(23, 59, 59, $tmpToMonth, $tmpToDay, $tmpToYear); 2517 if ($from_datetime !== FALSE && $to_datetime !== FALSE) 2518 { 2519 $UseDateRange = true; 2520 $dateRangeParams = "&zoom_datefrom=".urlencode($date_from)."&zoom_dateto=".urlencode($date_to); 2521 } 2522 } 2523 } 2524 2525 // Second pass, results filtering. 2526 $full_numwords = $NumSearchWords - $SkippedWords - $exclude_count; 2527 for ($i = 0; $i < $pagesCount; $i++) 2528 { 2529 $IsFiltered = false; 2530 $pageUrlBuffer = ""; 2531 2532 if ($res_table[$i][0] > 0 || $IsNoKeywordQuery) 2533 { 2534 if ($pageinfo[$i]["dataoffset"] == 0) // filter out if deleted 2535 $IsFiltered = true; 2536 2537 if ($IsFiltered == false && $searchUrlBuffer !== "") 2538 { 2539 $pageUrlBuffer = GetUrlFromPageData($i); 2540 if (mystristr($pageUrlBuffer, $searchUrlBuffer) === FALSE) 2541 $IsFiltered = true; 2542 else 2543 { 2544 // the site/URL matched with the site: parameter 2545 if ($IsNoKeywordQuery) 2546 { 2547 // increment score/terms if we're allowing this through on site: match alone 2548 $res_table[$i][0]++; 2549 $res_table[$i][1]++; 2550 } 2551 } 2552 } 2553 2554 if ($UseMetaFields && $IsFiltered == false) 2555 { 2556 for ($fieldnum = 0; $fieldnum < $NumMetaFields && !$IsFiltered; $fieldnum++) 2557 { 2558 $IsAnyDropdown = false; 2559 if (is_array($meta_query[$fieldnum])) 2560 $tmpQueryVal = $meta_query[$fieldnum][0]; 2561 else 2562 $tmpQueryVal = $meta_query[$fieldnum]; 2563 2564 2565 if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_DROPDOWN || 2566 $metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_MULTI) 2567 { 2568 if ($tmpQueryVal == -1) 2569 $IsAnyDropdown = true; 2570 } 2571 2572 if ($tmpQueryVal !== "" && $IsAnyDropdown == false) 2573 { 2574 if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_TEXT) 2575 { 2576 if (strlen($metavalues[$i][$fieldnum]) == 0) 2577 $IsFiltered = true; 2578 else if ($metafields[$fieldnum][$METAFIELD_METHOD] == $METAFIELD_METHOD_SUBSTRING) 2579 { 2580 if (mystristr($metavalues[$i][$fieldnum], $meta_query[$fieldnum]) === FALSE) 2581 $IsFiltered = true; 2582 } 2583 else 2584 { 2585 if (strcasecmp($metavalues[$i][$fieldnum], $meta_query[$fieldnum]) !== 0) 2586 $IsFiltered = true; 2587 } 2588 } 2589 else if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_DROPDOWN) 2590 { 2591 if ($metavalues[$i][$fieldnum] == $METAFIELD_NOVALUE_MARKER) 2592 $IsFiltered = true; 2593 else if ($metavalues[$i][$fieldnum] != floatval($meta_query[$fieldnum])) 2594 $IsFiltered = true; 2595 } 2596 else if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_MULTI) 2597 { 2598 $IsFiltered = true; 2599 if ($metavalues[$i][$fieldnum] !== 0) 2600 { 2601 $num_multi_query = 0; 2602 if (is_array($meta_query[$fieldnum])) 2603 $num_multi_query = count($meta_query[$fieldnum]); 2604 for ($mqi = 0; $mqi < $num_multi_query && $IsFiltered; $mqi++) 2605 { 2606 for ($mvi = 0; $mvi < $metavalues[$i][$fieldnum][0]; $mvi++) 2607 { 2608 if ($metavalues[$i][$fieldnum][$mvi+1] == intval($meta_query[$fieldnum][$mqi])) 2609 { 2610 $IsFiltered = false; 2611 break; 2612 } 2613 } 2614 } 2615 } 2616 } 2617 else 2618 { 2619 // numeric comparison here 2620 if ($metavalues[$i][$fieldnum] == $METAFIELD_NOVALUE_MARKER) 2621 { 2622 $bRet = false; 2623 } 2624 else if ($metafields[$fieldnum][$METAFIELD_METHOD] == $METAFIELD_METHOD_LESSTHAN) 2625 { 2626 $bRet = $metavalues[$i][$fieldnum] < $meta_query[$fieldnum]; 2627 } 2628 else if ($metafields[$fieldnum][$METAFIELD_METHOD] == $METAFIELD_METHOD_LESSTHANORE) 2629 { 2630 $bRet = $metavalues[$i][$fieldnum] <= $meta_query[$fieldnum]; 2631 } 2632 else if ($metafields[$fieldnum][$METAFIELD_METHOD] == $METAFIELD_METHOD_GREATERTHAN) 2633 { 2634 $bRet = $metavalues[$i][$fieldnum] > $meta_query[$fieldnum]; 2635 } 2636 else if ($metafields[$fieldnum][$METAFIELD_METHOD] == $METAFIELD_METHOD_GREATERTHANORE) 2637 { 2638 $bRet = $metavalues[$i][$fieldnum] >= $meta_query[$fieldnum]; 2639 } 2640 else 2641 { 2642 // exact match 2643 $bRet = $metavalues[$i][$fieldnum] == $meta_query[$fieldnum]; 2644 } 2645 2646 if ($bRet == false) 2647 $IsFiltered = true; 2648 } 2649 } 2650 // only add to res_table if empty query! 2651 if ($IsNoKeywordQuery == true && $IsFiltered == false) 2652 { 2653 $res_table[$i][0]++; 2654 $res_table[$i][1]++; 2655 } 2656 } 2657 } 2658 2659 if ($IsFiltered == false) 2660 { 2661 if ($res_table[$i][5] < $full_numwords && $and == 1) 2662 { 2663 // if AND search, only copy AND results 2664 $IsFiltered = true; 2665 } 2666 } 2667 2668 if ($UseCats && $cat[0] != -1 && $IsFiltered == false) 2669 { 2670 // Using cats and not doing an "all cats" search 2671 $bFoundCat = false; 2672 for ($cati = 0; $cati < $num_zoom_cats; $cati++) 2673 { 2674 if (CheckBitInByteArray($cat[$cati], $catpages[$i]) !== 0) 2675 { 2676 if ($DisplayCatSummary == 1) 2677 { 2678 $CatCounter[$cat[$cati]]++; 2679 $CatCounterFilled = 1; 2680 } 2681 $bFoundCat = true; 2682 } 2683 } 2684 //if ($cati == $num_zoom_cats) 2685 if ($bFoundCat == false) 2686 $IsFiltered = true; 2687 } 2688 2689 if ($IsFiltered == false && $DateRangeSearch == 1 && $UseDateRange == true) 2690 { 2691 if ($pageinfo[$i]["datetime"] < $from_datetime) 2692 $IsFiltered = true; 2693 else if ($pageinfo[$i]["datetime"] > $to_datetime) 2694 $IsFiltered = true; 2695 } 2696 2697 if ($IsFiltered == false) 2698 { 2699 // we can only count our AND total here AFTER we've filtered out the cats 2700 if ($res_table[$i][5] >= $full_numwords) 2701 $fullmatches++; 2702 2703 // copy if not filtered out 2704 $output[$oline][0] = $i; // page index 2705 2706 $finalScale = (($res_table[$i][6] / 255.0) * $proxScale) + $baseScale; 2707 2708 if ($res_table[$i][1] > 1) // multiword search 2709 { 2710 if ($res_table[$i][1] <= 10) 2711 { 2712 $finalScale = pow($finalScale, $res_table[$i][1]-1); 2713 } 2714 else 2715 { 2716 $finalScale = pow($finalScale, 10); 2717 $finalScale += $res_table[$i][1] - 10; 2718 } 2719 } 2720 2721 if ($UseCats && $DisplayCatSummary == 1 && $cat[0] == -1) 2722 { 2723 // if we are doing an All category search AND we're showing cat summary 2724 for ($cati = 0; $cati < $NumCats; $cati++) 2725 { 2726 //if (($pageinfo[$i]["catnumber"] & (1 << $cati)) !== 0) 2727 if (CheckBitInByteArray($cati, $catpages[$i]) !== 0) 2728 { 2729 $CatCounter[$cati]++; 2730 $CatCounterFilled = 1; 2731 } 2732 } 2733 } 2734 2735 // final score and rounding 2736 $output[$oline][1] = (int) ($res_table[$i][0] * $finalScale + 0.5); 2737 $output[$oline][2] = $res_table[$i][1]; // num of sw matched 2738 $output[$oline][3] = $res_table[$i][2]; // pagetext ptr #1 2739 $output[$oline][4] = $res_table[$i][3]; // pagetext ptr #2 2740 $output[$oline][5] = $res_table[$i][4]; // pagetext ptr #3 2741 $oline++; 2742 } 2743 } 2744 } 2745 $matches = $oline; 2746 2747 //Sort results in order of score, use the "SortCompare" function 2748 if ($matches > 1) 2749 { 2750 if ($UseDateTime == 1 && $sort == 1) 2751 usort($output, "SortByDate"); 2752 else if ($UseDateTime == 1 && $sort == 2) 2753 usort($output, "SortByDateAsc"); 2754 else 2755 usort($output, "SortCompare");// Default sort by relevance 2756 } 2757 2758 2759 if ($UseDomainDiversity == 1) 2760 { 2761 if ($page == 1 && $matches > 5) 2762 { 2763 $arrayline = 0; 2764 $div_res_count = 0; 2765 if(!defined('PHP_URL_HOST')) define('PHP_URL_HOST', 2); // This define is missing in PHP4. 2766 2767 while ($arrayline < $matches && $div_res_count < $MaxDomainDiversity) 2768 { 2769 $pageUrlBuffer = GetUrlFromPageData($output[$arrayline][0]); 2770 $domainBuffer = parse_url($pageUrlBuffer, PHP_URL_HOST); 2771 $IsDifferentDomain = true; 2772 for ($div_url_i = 0; $div_url_i < $div_res_count; $div_url_i++) 2773 { 2774 if (strcasecmp($div_res_urls[$div_url_i], $domainBuffer) == 0) 2775 { 2776 $IsDifferentDomain = false; 2777 break; 2778 } 2779 } 2780 if ($IsDifferentDomain == true) 2781 { 2782 $div_res_table[$div_res_count] = $arrayline; 2783 $div_res_urls[$div_res_count] = $domainBuffer; 2784 $div_res_count++; 2785 } 2786 $arrayline++; 2787 } 2788 } 2789 else 2790 $UseDomainDiversity = 0; 2791 } 2792 2793 //Display search result information 2794 $OutputBuffers[$OUTPUT_SUMMARY] .= "<div class=\"summary\">\n"; 2795 2796 if ($IsMaxLimitExceeded) 2797 $OutputBuffers[$OUTPUT_SUMMARY] .= $STR_PHRASE_CONTAINS_COMMON_WORDS . "<br /><br />"; 2798 2799 if ($matches == 0) 2800 $OutputBuffers[$OUTPUT_SUMMARY] .= $STR_SUMMARY_NO_RESULTS_FOUND; 2801 elseif ($NumSearchWords > 1 && $and == 0) 2802 { 2803 //OR 2804 $SomeTermMatches = $matches - $fullmatches; 2805 $OutputBuffers[$OUTPUT_SUMMARY] .= PrintNumResults($fullmatches) . " " . $STR_SUMMARY_FOUND_CONTAINING_ALL_TERMS . " "; 2806 if ($SomeTermMatches > 0) 2807 $OutputBuffers[$OUTPUT_SUMMARY] .= PrintNumResults($SomeTermMatches) . " " . $STR_SUMMARY_FOUND_CONTAINING_SOME_TERMS; 2808 } 2809 elseif ($NumSearchWords > 1 && $and == 1) //AND 2810 $OutputBuffers[$OUTPUT_SUMMARY] .= PrintNumResults($fullmatches) . " " . $STR_SUMMARY_FOUND_CONTAINING_ALL_TERMS; 2811 else 2812 $OutputBuffers[$OUTPUT_SUMMARY] .= PrintNumResults($matches) . " " . $STR_SUMMARY_FOUND; 2813 2814 $OutputBuffers[$OUTPUT_SUMMARY] .= "<br />\n</div>\n"; 2815 2816 if ($matches < 3) 2817 { 2818 if ($and == 1 && $NumSearchWords > 1) 2819 $OutputBuffers[$OUTPUT_SUGGESTION] .= "<div class=\"suggestion\"><br />" . $STR_POSSIBLY_GET_MORE_RESULTS . " <a href=\"".$SelfURL.$LinkBackJoinChar."zoom_query=".$queryForURL.$metaParams."&zoom_per_page=".$per_page.$query_zoom_cats.$dateRangeParams."&zoom_and=0&zoom_sort=".$sort."\">". $STR_ANY_OF_TERMS . "</a>.</div>"; 2820 else if ($UseCats && $cat[0] != -1) 2821 $OutputBuffers[$OUTPUT_SUGGESTION] .= "<div class=\"suggestion\"><br />" . $STR_POSSIBLY_GET_MORE_RESULTS . " <a href=\"".$SelfURL.$LinkBackJoinChar."zoom_query=".$queryForURL.$metaParams."&zoom_per_page=".$per_page."&zoom_cat=-1".$dateRangeParams."&zoom_and=".$and."&zoom_sort=".$sort."\">" . $STR_ALL_CATS . "</a>.</div>"; 2822 } 2823 2824 // Show category summary 2825 if ($UseCats == 1 && $DisplayCatSummary == 1 && $CatCounterFilled == 1) 2826 { 2827 $OutputBuffers[$OUTPUT_CATSUMMARY] .= "<div class=\"cat_summary\"><br />".$STR_CAT_SUMMARY."\n<ul>\n"; 2828 $catSummaryItemCount = 0; 2829 for ($catit = 0; $catit < $NumCats; $catit++) 2830 { 2831 if ($CatCounter[$catit] > 0) 2832 { 2833 // if all the results found belonged in this current category, then we don't show it in the summary 2834 if ($CatCounter[$catit] != $matches) 2835 { 2836 $catSummaryItemCount++; 2837 $OutputBuffers[$OUTPUT_CATSUMMARY] .= "<li><a href=\"".$SelfURL.$LinkBackJoinChar."zoom_query=".$queryForURL.$metaParams."&zoom_cat=".$catit.$dateRangeParams."&zoom_per_page=".$per_page."&zoom_and=".$and."&zoom_sort=".$sort."\">".$catnames[$catit]; 2838 $OutputBuffers[$OUTPUT_CATSUMMARY] .= "</a> (".$CatCounter[$catit].")</li>"; 2839 } 2840 } 2841 } 2842 if ($catSummaryItemCount == 0) 2843 { 2844 // Clear the cat summary if we decided we didn't need to show it afterall 2845 $OutputBuffers[$OUTPUT_CATSUMMARY] = ""; 2846 } 2847 else 2848 $OutputBuffers[$OUTPUT_CATSUMMARY] .= "</ul>\n</div>\n"; 2849 } 2850 2851 if ($Spelling == 1) 2852 { 2853 // load in spellings file 2854 $fp_spell = fopen($SPELLINGFILE, "rt"); 2855 $i = 0; 2856 while (!feof($fp_spell)) 2857 { 2858 $spline = fgets($fp_spell, $MaxKeyWordLineLen); 2859 if (strlen($spline) > 0) 2860 { 2861 $spell[$i] = explode(" ", $spline, 4); 2862 $i++; 2863 } 2864 } 2865 fclose($fp_spell); 2866 $spell_count = $i; 2867 2868 $SuggestStr = ""; 2869 $SuggestionFound = 0; 2870 $SuggestionCount = 0; 2871 2872 $word = ""; 2873 $word2 = ""; 2874 $word3 = ""; 2875 $tmpWordStr = ""; // for local stemming and comparison 2876 2877 for ($sw = 0; $sw < $NumSearchWords; $sw++) 2878 { 2879 if ($sw_results[$sw] >= $SpellingWhenLessThan) 2880 { 2881 // this word has enough results 2882 if ($sw > 0) 2883 $SuggestStr = $SuggestStr . " "; 2884 $SuggestStr = $SuggestStr . $SearchWords[$sw]; 2885 } 2886 else 2887 { 2888 // this word returned less results than threshold, and requires spelling suggestions 2889 $sw_spcode = GetSPCode($SearchWords[$sw]); 2890 2891 if (strlen($sw_spcode) > 0) 2892 { 2893 $SuggestionFound = 0; 2894 for ($i = 0; $i < $spell_count && $SuggestionFound == 0; $i++) 2895 { 2896 $spcode = $spell[$i][0]; 2897 2898 if ($spcode == $sw_spcode) 2899 { 2900 $j = 0; 2901 while ($SuggestionFound == 0 && $j < 3 && isset($spell[$i][1+$j])) 2902 { 2903 $dictid = intval($spell[$i][1+$j]); 2904 $word = GetSpellingWord($dictid); 2905 $tmpWordStr = $word; 2906 if ($UseStemming == 1) 2907 { 2908 $tmpWordStr = strtolower($tmpWordStr); 2909 $tmpWordStr = $porterStemmer->Stem($tmpWordStr); 2910 } 2911 2912 if (wordcasecmp($tmpWordStr, $SearchWords[$sw]) == 0) 2913 { 2914 // Check that it is not a skipped word or the same word 2915 $SuggestionFound = 0; 2916 } 2917 else 2918 { 2919 $SuggestionFound = 1; 2920 $SuggestionCount++; 2921 if ($NumSearchWords == 1) // if single word search 2922 { 2923 if ($j < 1 && isset($spell[$i][1+$j+1])) 2924 { 2925 $dictid = intval($spell[$i][1+$j+1]); 2926 $word2 = GetSpellingWord($dictid); 2927 $tmpWordStr = $word2; 2928 if ($UseStemming == 1) 2929 { 2930 $tmpWordStr = strtolower($tmpWordStr); 2931 $tmpWordStr = $porterStemmer->Stem($tmpWordStr); 2932 } 2933 if (wordcasecmp($tmpWordStr, $SearchWords[$sw]) == 0) 2934 $word2 = ""; 2935 } 2936 if ($j < 2 && isset($spell[$i][1+$j+2])) 2937 { 2938 $dictid = intval($spell[$i][1+$j+2]); 2939 $word3 = GetSpellingWord($dictid); 2940 $tmpWordStr = $word3; 2941 if ($UseStemming == 1) 2942 { 2943 $tmpWordStr = strtolower($tmpWordStr); 2944 $tmpWordStr = $porterStemmer->Stem($tmpWordStr); 2945 } 2946 if (wordcasecmp($tmpWordStr, $SearchWords[$sw]) == 0) 2947 $word3 = ""; 2948 } 2949 } 2950 } 2951 $j++; 2952 } 2953 } 2954 elseif (strcmp($spcode, $sw_spcode) > 0) 2955 { 2956 break; 2957 } 2958 } 2959 2960 if ($SuggestionFound == 1) 2961 { 2962 if ($sw > 0) 2963 $SuggestStr = $SuggestStr . " "; 2964 $SuggestStr = $SuggestStr . $word; // add string AFTER so we can preserve order of words 2965 } 2966 } 2967 } 2968 } 2969 if ($SuggestionCount > 0) 2970 { 2971 $OutputBuffers[$OUTPUT_SUGGESTION] .= "<div class=\"suggestion\"><br />" . $STR_DIDYOUMEAN . " <a href=\"".$SelfURL.$LinkBackJoinChar."zoom_query=".urlencode($SuggestStr).$metaParams."&zoom_per_page=".$per_page.$query_zoom_cats.$dateRangeParams."&zoom_and=0&zoom_sort=".$sort."\">". $SuggestStr . "</a>"; 2972 if (strlen($word2) > 0) 2973 $OutputBuffers[$OUTPUT_SUGGESTION] .= " $STR_OR <a href=\"".$SelfURL.$LinkBackJoinChar."zoom_query=".urlencode($word2).$metaParams."&zoom_per_page=".$per_page.$query_zoom_cats.$dateRangeParams."&zoom_and=".$and."&zoom_sort=".$sort."\">". $word2 . "</a>"; 2974 if (strlen($word3) > 0) 2975 $OutputBuffers[$OUTPUT_SUGGESTION] .= " $STR_OR <a href=\"".$SelfURL.$LinkBackJoinChar."zoom_query=".urlencode($word3).$metaParams."&zoom_per_page=".$per_page.$query_zoom_cats.$dateRangeParams."&zoom_and=".$and."&zoom_sort=".$sort."\">". $word3 . "</a>"; 2976 $OutputBuffers[$OUTPUT_SUGGESTION] .= "?</div>"; 2977 } 2978 } 2979 2980 // Number of pages of results 2981 $num_pages = ceil($matches / $per_page); 2982 if ($num_pages > 1) 2983 $OutputBuffers[$OUTPUT_PAGESCOUNT] .= "<div class=\"result_pagescount\"><br />" . $num_pages . " " . $STR_PAGES_OF_RESULTS . "</div>\n"; 2984 2985 // Show sorting options 2986 if ($matches > 1) 2987 { 2988 if ($UseDateTime == 1) 2989 { 2990 $OutputBuffers[$OUTPUT_SORTING] .= "<div class=\"sorting\">"; 2991 if ($sort == 1) 2992 $OutputBuffers[$OUTPUT_SORTING] .= "<a href=\"".$SelfURL.$LinkBackJoinChar."zoom_query=".$queryForURL.$metaParams."&zoom_page=".$page."&zoom_per_page=".$per_page.$query_zoom_cats.$dateRangeParams."&zoom_and=".$and."&zoom_sort=0\">". $STR_SORTBY_RELEVANCE . "</a> / <a href=\"".$SelfURL.$LinkBackJoinChar."zoom_query=".$queryForURL.$metaParams."&zoom_page=".$page."&zoom_per_page=".$per_page.$query_zoom_cats.$dateRangeParams."&zoom_and=".$and."&zoom_sort=2\">". $STR_SORTEDBY_DATE . "</a>"; 2993 elseif ($sort == 2) 2994 $OutputBuffers[$OUTPUT_SORTING] .= "<a href=\"".$SelfURL.$LinkBackJoinChar."zoom_query=".$queryForURL.$metaParams."&zoom_page=".$page."&zoom_per_page=".$per_page.$query_zoom_cats.$dateRangeParams."&zoom_and=".$and."&zoom_sort=0\">". $STR_SORTBY_RELEVANCE . "</a> / <a href=\"".$SelfURL.$LinkBackJoinChar."zoom_query=".$queryForURL.$metaParams."&zoom_page=".$page."&zoom_per_page=".$per_page.$query_zoom_cats.$dateRangeParams."&zoom_and=".$and."&zoom_sort=1\">". $STR_SORTEDBY_DATE_ASC . "</a>"; 2995 else 2996 $OutputBuffers[$OUTPUT_SORTING] .= "<b>". $STR_SORTEDBY_RELEVANCE . "</b> / <a href=\"".$SelfURL.$LinkBackJoinChar."zoom_query=".$queryForURL.$metaParams."&zoom_page=".$page."&zoom_per_page=".$per_page.$query_zoom_cats.$dateRangeParams."&zoom_and=".$and."&zoom_sort=1\">". $STR_SORTBY_DATE . "</a>"; 2997 $OutputBuffers[$OUTPUT_SORTING] .= "</div>"; 2998 } 2999 } 3000 3001 // Determine current line of result from the $output array 3002 if ($page == 1) { 3003 $arrayline = 0; 3004 } else { 3005 $arrayline = (($page - 1) * $per_page); 3006 } 3007 3008 // The last result to show on this page 3009 $result_limit = $arrayline + $per_page; 3010 3011 $display_num = $arrayline + 1; 3012 3013 // Display the results 3014 while ($arrayline < $matches && $arrayline < $result_limit) 3015 { 3016 if ($UseDomainDiversity == 1 && $arrayline < $div_res_count) 3017 { 3018 $ipage = $output[$div_res_table[$arrayline]][0]; 3019 $score = $output[$div_res_table[$arrayline]][1]; 3020 $termsmatched = $output[$div_res_table[$arrayline]][2]; 3021 3022 // we'll mark this as done 3023 $output[$div_res_table[$arrayline]][1] = -1; 3024 } 3025 else 3026 { 3027 $ipage = $output[$arrayline][0]; 3028 $score = $output[$arrayline][1]; 3029 $termsmatched = $output[$arrayline][2]; 3030 3031 if ($output[$arrayline][1] == -1) 3032 { 3033 $arrayline++; 3034 continue; 3035 } 3036 } 3037 3038 $pgdata = GetPageData($ipage); 3039 $url = $pgdata[$PAGEDATA_URL]; 3040 $title = $pgdata[$PAGEDATA_TITLE]; 3041 $description = $pgdata[$PAGEDATA_DESC]; 3042 3043 $urlLink = $url; 3044 3045 //$urlLink = rtrim($urls[$ipage]); 3046 if ($GotoHighlight == 1) 3047 { 3048 if ($SearchAsSubstring == 1) 3049 $urlLink = AddParamToURL($urlLink, "zoom_highlightsub=".$queryForURL); 3050 else 3051 $urlLink = AddParamToURL($urlLink, "zoom_highlight=".$queryForURL); 3052 } 3053 if ($PdfHighlight == 1 && $IsNoKeywordQuery == false) 3054 { 3055 if (stristr($urlLink, ".pdf") != FALSE) 3056 $urlLink = $urlLink."#search=%22".str_replace("\"", "", $query)."%22"; 3057 } 3058 3059 if ($arrayline % 2 == 0) 3060 $OutputResultsBuffer .= "<div class=\"result_block\">"; 3061 else 3062 $OutputResultsBuffer .= "<div class=\"result_altblock\">"; 3063 3064 if ($PluginOpenNewWindow == 1 && $pageinfo[$ipage]["filetype"] >= $FileTypePluginStart) 3065 $target = " target=\"_blank\""; 3066 else 3067 $target = $zoom_target; 3068 3069 if ($UseZoomImage) 3070 { 3071 if (isset($pgdata[$PAGEDATA_IMG])) 3072 $image = $pgdata[$PAGEDATA_IMG]; 3073 else 3074 $image = ""; 3075 if (strlen($image) > 0) 3076 { 3077 $OutputResultsBuffer .= "<div class=\"result_image\">"; 3078 $OutputResultsBuffer .= "<a href=\"".$urlLink."\"" . $target . "><img src=\"$image\" alt=\"\" class=\"result_image\" /></a>"; 3079 $OutputResultsBuffer .= "</div>"; 3080 } 3081 } 3082 3083 $OutputResultsBuffer .= "<div class=\"result_title\">"; 3084 if ($DisplayNumber == 1) 3085 $OutputResultsBuffer .= "<b>".($display_num).".</b> "; 3086 $display_num++; 3087 3088 if ($DisplayTitle == 1) 3089 { 3090 $OutputResultsBuffer .= "<a href=\"".$urlLink."\"" . $target . ">"; 3091 $OutputResultsBuffer .= PrintHighlightDescription(rtrim($title)); 3092 $OutputResultsBuffer .= "</a>"; 3093 } 3094 else 3095 $OutputResultsBuffer .= "<a href=\"".$urlLink."\"" . $target . ">".rtrim($url)."</a>"; 3096 3097 if ($UseCats) 3098 { 3099 $OutputResultsBuffer .= " <span class=\"category\">"; 3100 for ($catit = 0; $catit < $NumCats; $catit++) 3101 { 3102 //if (($pageinfo[$ipage]["catnumber"] & (1 << $catit)) !== 0) 3103 if (CheckBitInByteArray($catit, $catpages[$ipage]) !== 0) 3104 $OutputResultsBuffer .= " [".trim($catnames[$catit])."]"; 3105 } 3106 $OutputResultsBuffer .= "</span>"; 3107 } 3108 $OutputResultsBuffer .= "</div>\n"; 3109 3110 if ($UseMetaFields == 1 && $DisplayMetaFields == 1) 3111 { 3112 for ($fieldnum = 0; $fieldnum < $NumMetaFields; $fieldnum++) 3113 { 3114 $cssFieldName = "result_metaname_" . $metafields[$fieldnum][$METAFIELD_NAME]; 3115 $cssValueName = "result_metavalue_" . $metafields[$fieldnum][$METAFIELD_NAME]; 3116 if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_MULTI) 3117 { 3118 if ($metavalues[$ipage][$fieldnum][0] > 0) 3119 { 3120 $OutputResultsBuffer .= "<div class=\"result_custommeta\">"; 3121 $OutputResultsBuffer .= "<span class=\"$cssFieldName\">".$metafields[$fieldnum][$METAFIELD_SHOW].": </span>"; 3122 $OutputResultsBuffer .= "<span class=\"$cssValueName\">"; 3123 $ddarray = $metafields[$fieldnum][$METAFIELD_DROPDOWN]; 3124 for ($mvi = 0; $mvi < $metavalues[$ipage][$fieldnum][0]; $mvi++) 3125 { 3126 if ($mvi > 0) 3127 $OutputResultsBuffer .= ", "; 3128 $OutputResultsBuffer .= $ddarray[$metavalues[$ipage][$fieldnum][$mvi+1]]; 3129 } 3130 $OutputResultsBuffer .= "</span>"; 3131 $OutputResultsBuffer .= "</div>"; 3132 } 3133 } 3134 else 3135 { 3136 if ($metavalues[$ipage][$fieldnum] != $METAFIELD_NOVALUE_MARKER && strlen($metavalues[$ipage][$fieldnum]) > 0) 3137 { 3138 if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_DROPDOWN) 3139 { 3140 $OutputResultsBuffer .= "<div class=\"result_custommeta\">"; 3141 $OutputResultsBuffer .= "<span class=\"$cssFieldName\">".$metafields[$fieldnum][$METAFIELD_SHOW].": </span>"; 3142 $OutputResultsBuffer .= "<span class=\"$cssValueName\">"; 3143 $ddarray = $metafields[$fieldnum][$METAFIELD_DROPDOWN]; 3144 $OutputResultsBuffer .= $ddarray[$metavalues[$ipage][$fieldnum]]."</span>"; 3145 $OutputResultsBuffer .= "</div>"; 3146 } 3147 else if ($metafields[$fieldnum][$METAFIELD_TYPE] == $METAFIELD_TYPE_MONEY) 3148 { 3149 $OutputResultsBuffer .= "<div class=\"result_custommeta\">"; 3150 $OutputResultsBuffer .= "<span class=\"$cssFieldName\">".$metafields[$fieldnum][$METAFIELD_SHOW].": </span>"; 3151 $OutputResultsBuffer .= "<span class=\"$cssValueName\">".$MetaMoneyCurrency; 3152 $tmpMoneyStr = ""; 3153 if ($MetaMoneyShowDec == 1) 3154 $tmpMoneyStr = sprintf("%01.2f", $metavalues[$ipage][$fieldnum]/100); 3155 else 3156 $tmpMoneyStr = sprintf("%d", $metavalues[$ipage][$fieldnum]); 3157 $OutputResultsBuffer .= $tmpMoneyStr."</span>"; 3158 $OutputResultsBuffer .= "</div>"; 3159 } 3160 else 3161 { 3162 // just print it out 3163 $OutputResultsBuffer .= "<div class=\"result_custommeta\">"; 3164 $OutputResultsBuffer .= "<span class=\"$cssFieldName\">".$metafields[$fieldnum][$METAFIELD_SHOW].": </span>"; 3165 $OutputResultsBuffer .= "<span class=\"$cssValueName\">"; 3166 $OutputResultsBuffer .= $metavalues[$ipage][$fieldnum]."</span>"; 3167 $OutputResultsBuffer .= "</div>"; 3168 } 3169 } 3170 } 3171 } 3172 } 3173 3174 if ($DisplayMetaDesc == 1) 3175 { 3176 // Print meta description 3177 if (strlen($description) > 2) { 3178 $OutputResultsBuffer .= "<div class=\"description\">"; 3179 $OutputResultsBuffer .= PrintHighlightDescription(rtrim($description)); 3180 $OutputResultsBuffer .= "</div>\n"; 3181 } 3182 } 3183 3184 if ($DisplayContext == 1 && $output[$arrayline][2] > 0 && $IsNoKeywordQuery == false) 3185 { 3186 // Extract contextual page content 3187 $context_keywords = $output[$arrayline][2]; // # of terms matched 3188 3189 if ($context_keywords > $MaxContextKeywords) 3190 $context_keywords = $MaxContextKeywords; 3191 3192 $context_word_count = ceil($ContextSize / $context_keywords); 3193 3194 $goback = floor($context_word_count / 2); 3195 $gobackbytes = $goback * $DictIDLen; 3196 3197 $last_startpos = 0; 3198 $first_startpos = 0; 3199 $last_endpos = 0; 3200 3201 $FoundContext = 0; 3202 $IsEndOfContent = 0; 3203 3204 $OutputResultsBuffer .= "<div class=\"context\">\n"; 3205 for ($j = 0; $IsEndOfContent == 0 && $j < $context_keywords && ($j == 0 || !feof($fp_pagetext)); $j++) 3206 { 3207 $origpos = $output[$arrayline][3 + $j]; 3208 $startpos = $origpos; 3209 3210 if ($gobackbytes < $startpos) 3211 { 3212 $startpos = $startpos - $gobackbytes; 3213 $noGoBack = false; 3214 } 3215 else 3216 $noGoBack = true; 3217 3218 // Check that this will not overlap with previous extract 3219 if (($startpos > $last_startpos || $startpos > $first_startpos) && $startpos < $last_endpos) 3220 $startpos = $last_endpos; // we will just continue last extract if so. 3221 3222 // find the pagetext pointed to 3223 fseek($fp_pagetext, $startpos); 3224 3225 // remember the last start position 3226 $last_startpos = $startpos; 3227 if ($j == 0) 3228 $first_startpos = $startpos; 3229 3230 $last_bytesread = 0; 3231 $bytesread = 0; 3232 3233 $retDict = GetNextDictWord($fp_pagetext); 3234 $word_id = $retDict[0]; 3235 $variant_index = $retDict[1]; 3236 $bytesread += $DictIDLen; 3237 3238 $contextArray = array_fill(0, $context_word_count, 0); 3239 $highlightArray = array_fill(0, $context_word_count, 0); 3240 3241 for ($cti = 0; $cti < $context_word_count && !feof($fp_pagetext); $cti++) 3242 { 3243 if ($word_id == 0 || $word_id == 1 || $word_id >= $dict_count) // check if end of page or section 3244 { 3245 // if end of page occurs AFTER word pointer (ie: reached next page) 3246 if ($noGoBack || ($startpos+$bytesread) > $origpos) 3247 { 3248 $IsEndOfContent = 1; 3249 break; // then we stop. 3250 } 3251 else // if end of page occurs BEFORE word pointer (ie: reached previous page) 3252 { 3253 //$context_str = "";// then we clear the existing context buffer we've created. 3254 $contextArray = array_fill(0, $context_word_count, 0); // then we clear the existing context buffer we've created. 3255 $cti = 0; 3256 } 3257 } 3258 else 3259 { 3260 if ($word_id >= $NumKeywords) 3261 { 3262 $OutputResultsBuffer .= "Critical error with pagetext file. Check that your files are from the same indexing session."; 3263 } 3264 else 3265 { 3266 if ($Highlighting == 1 && $IsNoKeywordQuery == false && ($startpos+$last_bytesread) == $origpos) 3267 $highlightArray[$cti] = 1; 3268 3269 $contextArray[$cti] = array(); 3270 $contextArray[$cti][0] = $word_id; 3271 $contextArray[$cti][1] = $variant_index; 3272 } 3273 } 3274 $last_bytesread = $bytesread; 3275 3276 $retDict = GetNextDictWord($fp_pagetext); 3277 $word_id = $retDict[0]; 3278 $variant_index = $retDict[1]; 3279 $bytesread += $DictIDLen; 3280 } 3281 3282 // remember the last end position (if not already at end of page) 3283 if ($word_id != 0) 3284 $last_endpos = ftell($fp_pagetext); 3285 3286 if ($Highlighting == 1) 3287 { 3288 HighlightContextArray($context_word_count); 3289 } 3290 3291 $prev_word_id = 0; 3292 $context_str = ""; 3293 $noSpaceForNextChar = false; 3294 3295 for ($cti = 0; $cti < $context_word_count && !feof($fp_pagetext); $cti++) 3296 { 3297 if ($contextArray[$cti] == 0) 3298 continue; 3299 3300 $word_id = $contextArray[$cti][0]; 3301 $variant_index = $contextArray[$cti][1]; 3302 3303 if ($noSpaceForNextChar == false) 3304 { 3305 // No space for reserved words (punctuation, etc) 3306 if ($word_id > $DictReservedNoSpaces) 3307 { 3308 if ($prev_word_id <= $DictReservedPrefixes || $prev_word_id > $DictReservedNoSpaces) 3309 $context_str .= " "; 3310 } 3311 elseif ($word_id > $DictReservedSuffixes && $word_id <= $DictReservedPrefixes) 3312 { 3313 // This is a Prefix character 3314 $context_str .= " "; 3315 $noSpaceForNextChar = true; 3316 } 3317 elseif ($word_id > $DictReservedPrefixes) // this is a nospace character 3318 $noSpaceForNextChar = true; 3319 } 3320 else 3321 $noSpaceForNextChar = false; 3322 3323 if ($word_id > 0) 3324 { 3325 if ($Highlighting == 1 && 3326 ($highlightArray[$cti] == $HIGHLIGHT_SINGLE || $highlightArray[$cti] == $HIGHLIGHT_START)) 3327 $context_str .= "<span class=\"highlight\">"; 3328 3329 $context_str .= GetDictionaryWord($word_id, $variant_index); 3330 3331 if ($Highlighting == 1 && 3332 ($highlightArray[$cti] == $HIGHLIGHT_SINGLE || $highlightArray[$cti] == $HIGHLIGHT_END)) 3333 $context_str .= "</span>"; 3334 3335 $prev_word_id = $word_id; 3336 } 3337 } 3338 3339 if (strcmp(trim($context_str), trim($title)) == 0) 3340 { 3341 $context_str = ""; // clear the string if its identical to the title 3342 } 3343 3344 if ($context_str != "") 3345 { 3346 $OutputResultsBuffer .= " <b>...</b> "; 3347 $FoundContext = 1; 3348 $OutputResultsBuffer .= $context_str; 3349 //$OutputResultsBuffer .= PrintHighlightDescription($context_str); 3350 } 3351 } 3352 if ($FoundContext == 1) 3353 $OutputResultsBuffer .= " <b>...</b>"; 3354 $OutputResultsBuffer .= "</div>\n"; 3355 } 3356 3357 $info_str = ""; 3358 3359 if ($DisplayTerms == 1) 3360 { 3361 $info_str .= $STR_RESULT_TERMS_MATCHED . " ". $termsmatched; 3362 } 3363 3364 if ($DisplayScore == 1) 3365 { 3366 if (strlen($info_str) > 0) 3367 $info_str .= " - "; 3368 $info_str .= $STR_RESULT_SCORE . " " . $score; 3369 } 3370 3371 if ($DisplayDate == 1 && $pageinfo[$ipage]["datetime"] > 0) 3372 { 3373 if (strlen($info_str) > 0) 3374 $info_str .= " - "; 3375 $info_str .= date("j M Y", $pageinfo[$ipage]["datetime"]); 3376 } 3377 3378 if ($DisplayFilesize == 1) 3379 { 3380 if (strlen($info_str) > 0) 3381 $info_str .= " - "; 3382 $filesize = $pageinfo[$ipage]["filesize"]/1024; 3383 if ($filesize == 0) 3384 $filesize = 1; 3385 $info_str .= number_format($filesize) . "k"; 3386 } 3387 3388 if ($DisplayURL == 1) 3389 { 3390 if (strlen($info_str) > 0) 3391 $info_str .= " - "; 3392 3393 $url = rtrim($url); 3394 if ($TruncateShowURL > 0) 3395 { 3396 if (strlen($url) > $TruncateShowURL) 3397 $url = substr($url, 0, $TruncateShowURL) . "..."; 3398 } 3399 $info_str .= $STR_RESULT_URL . " ".$url; 3400 } 3401 3402 $OutputResultsBuffer .= "<div class=\"infoline\">"; 3403 $OutputResultsBuffer .= $info_str; 3404 $OutputResultsBuffer .= "</div>\n"; 3405 3406 $OutputResultsBuffer .= "</div>"; 3407 3408 $arrayline++; 3409 } 3410 3411 if ($DisplayContext == 1 || $AllowExactPhrase == 1) 3412 fclose($fp_pagetext); 3413 3414 fclose($fp_pagedata); 3415 3416 $OutputResultsBuffer .= "</div>"; // end of results style tag 3417 3418 // Show links to other result pages 3419 if ($num_pages > 1) 3420 { 3421 // 10 results to the left of the current page 3422 $start_range = $page - 10; 3423 if ($start_range < 1) 3424 $start_range = 1; 3425 3426 // 10 to the right 3427 $end_range = $page + 10; 3428 if ($end_range > $num_pages) 3429 $end_range = $num_pages; 3430 3431 $OutputBuffers[$OUTPUT_PAGENUMBERS] .= "<div class=\"result_pages\">\n" . $STR_RESULT_PAGES . " "; 3432 if ($page > 1) 3433 $OutputBuffers[$OUTPUT_PAGENUMBERS] .= "<a href=\"".$SelfURL.$LinkBackJoinChar."zoom_query=".$queryForURL.$metaParams."&zoom_page=".($page-1)."&zoom_per_page=".$per_page.$query_zoom_cats.$dateRangeParams."&zoom_and=".$and."&zoom_sort=".$sort."\"><< " . $STR_RESULT_PAGES_PREVIOUS . "</a> "; 3434 for ($i = $start_range; $i <= $end_range; $i++) 3435 { 3436 if ($i == $page) 3437 $OutputBuffers[$OUTPUT_PAGENUMBERS] .= $page." "; 3438 else 3439 $OutputBuffers[$OUTPUT_PAGENUMBERS] .= "<a href=\"".$SelfURL.$LinkBackJoinChar."zoom_query=".$queryForURL.$metaParams."&zoom_page=".($i)."&zoom_per_page=".$per_page.$query_zoom_cats.$dateRangeParams."&zoom_and=".$and."&zoom_sort=".$sort."\">".$i."</a> "; 3440 } 3441 if ($page != $num_pages) 3442 $OutputBuffers[$OUTPUT_PAGENUMBERS] .= "<a href=\"".$SelfURL.$LinkBackJoinChar."zoom_query=".$queryForURL.$metaParams."&zoom_page=".($page+1)."&zoom_per_page=".$per_page.$query_zoom_cats.$dateRangeParams."&zoom_and=".$and."&zoom_sort=".$sort."\">" . $STR_RESULT_PAGES_NEXT . " >></a> "; 3443 $OutputBuffers[$OUTPUT_PAGENUMBERS] .= "</div>"; 3444 } 3445 3446 //Let others know about Zoom. 3447 if ($ZoomInfo == 1) 3448 $OutputBuffers[$OUTPUT_PAGENUMBERS] .= "<center><p><small>" . $STR_POWEREDBY . " <a href=\"http://www.wrensoft.com/zoom/\" target=\"_blank\"><b>Zoom Search Engine</b></a></small></p></center>"; 3449 3450 3451 if ($Timing == 1 || $Logging == 1) 3452 { 3453 $mtime = explode(" ", microtime()); 3454 $endtime = doubleval($mtime[1]) + doubleval($mtime[0]); 3455 $difference = abs($starttime - $endtime); 3456 $timetaken = number_format($difference, 3, '.', ''); 3457 if ($Timing == 1) 3458 $OutputBuffers[$OUTPUT_SEARCHTIME] .= "<div class=\"searchtime\"><br /><br />" . $STR_SEARCH_TOOK . " " . $timetaken . " " . $STR_SECONDS . "</div>\n"; 3459 } 3460 3461 //Log the search words, if required 3462 if ($Logging == 1) 3463 { 3464 $LogQuery = str_replace("\"", "\"\"", $query); 3465 if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) 3466 { 3467 $ip_addr = $_SERVER['HTTP_X_FORWARDED_FOR']; 3468 $ip_array = explode(",", $ip_addr); 3469 if (count($ip_array) > 0) 3470 $ip_addr = trim($ip_array[0]); // get first IP if there are multiple addresses 3471 } 3472 else 3473 $ip_addr = $_SERVER['REMOTE_ADDR']; 3474 $LogString = Date("Y-m-d, H:i:s") . ", " . $ip_addr . ", \"" .$LogQuery . "\", Matches = " . $matches; 3475 if ($and == 1) 3476 $LogString = $LogString . ", AND"; 3477 else 3478 $LogString = $LogString . ", OR"; 3479 3480 if ($NewSearch == 1) 3481 $page = 0; 3482 3483 $LogString = $LogString . ", PerPage = " . $per_page . ", PageNum = " . $page; 3484 3485 if ($UseCats == 0) 3486 $LogString = $LogString . ", No cats"; 3487 else 3488 { 3489 if ($cat[0] == -1) 3490 $LogString = $LogString . ", \"Cat = All\""; 3491 else 3492 { 3493 $LogString = $LogString . ", \"Cat = "; 3494 for ($cati = 0; $cati < $num_zoom_cats; $cati++) 3495 { 3496 if ($cati > 0) 3497 $LogString = $LogString . "; "; 3498 $logCatStr = trim($catnames[$cat[$cati]]); 3499 $logCatStr = str_replace("\"", "\"\"", $logCatStr); 3500 $LogString = $LogString . $logCatStr; 3501 } 3502 $LogString = $LogString . "\""; 3503 } 3504 } 3505 $LogString = $LogString . ", Time = " . $timetaken; 3506 3507 $LogString = $LogString . ", Rec = " . $num_recs_found; 3508 3509 // end of entry 3510 $LogString = $LogString . "\r\n"; 3511 3512 $fp = fopen ($LogFileName, "ab"); 3513 if ($fp != false) 3514 { 3515 fputs ($fp, $LogString); 3516 fclose ($fp); 3517 } 3518 else 3519 { 3520 $OutputResultsBuffer .= "Unable to write to log file (" . $LogFileName . "). Check that you have specified the correct log filename in your Indexer settings and that you have the required file permissions set.<br />"; 3521 } 3522 } 3523 3524 //Print out the end of the template 3525 ShowTemplate(); 3526 3527 3528 // ---------------------------------------------------------------------------------- 3529 // Porter Stemming algorithm by Dr Martin Porter. 3530 // PHP5 implementation by Richard Heyes, copyright 2005. 3531 // PHP4 support and additional features by Wrensoft, copyright 2009. 3532 // The PorterStemmer class is available for use "free of charge for any purpose" as 3533 // published on Martin Porter's website (http://tartarus.org/~martin/PorterStemmer/) 3534 // ---------------------------------------------------------------------------------- 3535 class PorterStemmer 3536 { 3537 var $regex_consonant = '(?:[bcdfghjklmnpqrstvwxz]|(?<=[aeiou])y|^y)'; 3538 var $regex_vowel = '(?:[aeiou]|(?<![aeiou])y)'; 3539 var $StemStopChars = '`1234567890-=[]\\;\',./~!@#$%^&*_+|:"<>?'; 3540 3541 function Stem($word) 3542 { 3543 if (strlen($word) <= 2) { 3544 return $word; 3545 } 3546 3547 if (strcspn($word, $this->StemStopChars) < strlen($word)) 3548 return $word; 3549 3550 $word = $this->step1ab($word); 3551 $word = $this->step1c($word); 3552 $word = $this->step2($word); 3553 $word = $this->step3($word); 3554 $word = $this->step4($word); 3555 $word = $this->step5($word); 3556 3557 return $word; 3558 } 3559 3560 function step1ab($word) 3561 { 3562 // Part a 3563 if (substr($word, -1) == 's') { 3564 3565 $this->replace($word, 'sses', 'ss') 3566 OR $this->replace($word, 'ies', 'i') 3567 OR $this->replace($word, 'ss', 'ss') 3568 OR $this->replace($word, 's', ''); 3569 } 3570 3571 // Part b 3572 if (substr($word, -2, 1) != 'e' OR !$this->replace($word, 'eed', 'ee', 0)) { // First rule 3573 $v = $this->regex_vowel; 3574 3575 // ing and ed 3576 if ( preg_match("#$v+#", substr($word, 0, -3)) && $this->replace($word, 'ing', '') 3577 OR preg_match("#$v+#", substr($word, 0, -2)) && $this->replace($word, 'ed', '')) { // Note use of && and OR, for precedence reasons 3578 3579 // If one of above two test successful 3580 if ( !$this->replace($word, 'at', 'ate') 3581 AND !$this->replace($word, 'bl', 'ble') 3582 AND !$this->replace($word, 'iz', 'ize')) { 3583 3584 // Double consonant ending 3585 if ( $this->doubleConsonant($word) 3586 AND substr($word, -2) != 'll' 3587 AND substr($word, -2) != 'ss' 3588 AND substr($word, -2) != 'zz') { 3589 3590 $word = substr($word, 0, -1); 3591 3592 } else if ($this->m($word) == 1 AND $this->cvc($word)) { 3593 $word .= 'e'; 3594 } 3595 } 3596 } 3597 } 3598 return $word; 3599 } 3600 3601 function step1c($word) 3602 { 3603 $v = $this->regex_vowel; 3604 3605 if (substr($word, -1) == 'y' && preg_match("#$v+#", substr($word, 0, -1))) { 3606 $this->replace($word, 'y', 'i'); 3607 } 3608 3609 return $word; 3610 } 3611 3612 function step2($word) 3613 { 3614 switch (substr($word, -2, 1)) { 3615 case 'a': 3616 $this->replace($word, 'ational', 'ate', 0) 3617 OR $this->replace($word, 'tional', 'tion', 0); 3618 break; 3619 3620 case 'c': 3621 $this->replace($word, 'enci', 'ence', 0) 3622 OR $this->replace($word, 'anci', 'ance', 0); 3623 break; 3624 3625 case 'e': 3626 $this->replace($word, 'izer', 'ize', 0); 3627 break; 3628 3629 case 'g': 3630 $this->replace($word, 'logi', 'log', 0); 3631 break; 3632 3633 case 'l': 3634 $this->replace($word, 'entli', 'ent', 0) 3635 OR $this->replace($word, 'ousli', 'ous', 0) 3636 OR $this->replace($word, 'alli', 'al', 0) 3637 OR $this->replace($word, 'bli', 'ble', 0) 3638 OR $this->replace($word, 'eli', 'e', 0); 3639 break; 3640 3641 case 'o': 3642 $this->replace($word, 'ization', 'ize', 0) 3643 OR $this->replace($word, 'ation', 'ate', 0) 3644 OR $this->replace($word, 'ator', 'ate', 0); 3645 break; 3646 3647 case 's': 3648 $this->replace($word, 'iveness', 'ive', 0) 3649 OR $this->replace($word, 'fulness', 'ful', 0) 3650 OR $this->replace($word, 'ousness', 'ous', 0) 3651 OR $this->replace($word, 'alism', 'al', 0); 3652 break; 3653 3654 case 't': 3655 $this->replace($word, 'biliti', 'ble', 0) 3656 OR $this->replace($word, 'aliti', 'al', 0) 3657 OR $this->replace($word, 'iviti', 'ive', 0); 3658 break; 3659 } 3660 return $word; 3661 } 3662 3663 function step3($word) 3664 { 3665 switch (substr($word, -2, 1)) { 3666 case 'a': 3667 $this->replace($word, 'ical', 'ic', 0); 3668 break; 3669 3670 case 's': 3671 $this->replace($word, 'ness', '', 0); 3672 break; 3673 3674 case 't': 3675 $this->replace($word, 'icate', 'ic', 0) 3676 OR $this->replace($word, 'iciti', 'ic', 0); 3677 break; 3678 3679 case 'u': 3680 $this->replace($word, 'ful', '', 0); 3681 break; 3682 3683 case 'v': 3684 $this->replace($word, 'ative', '', 0); 3685 break; 3686 3687 case 'z': 3688 $this->replace($word, 'alize', 'al', 0); 3689 break; 3690 } 3691 3692 return $word; 3693 } 3694 3695 function step4($word) 3696 { 3697 switch (substr($word, -2, 1)) { 3698 case 'a': 3699 $this->replace($word, 'al', '', 1); 3700 break; 3701 3702 case 'c': 3703 $this->replace($word, 'ance', '', 1) 3704 OR $this->replace($word, 'ence', '', 1); 3705 break; 3706 3707 case 'e': 3708 $this->replace($word, 'er', '', 1); 3709 break; 3710 3711 case 'i': 3712 $this->replace($word, 'ic', '', 1); 3713 break; 3714 3715 case 'l': 3716 $this->replace($word, 'able', '', 1) 3717 OR $this->replace($word, 'ible', '', 1); 3718 break; 3719 3720 case 'n': 3721 $this->replace($word, 'ant', '', 1) 3722 OR $this->replace($word, 'ement', '', 1) 3723 OR $this->replace($word, 'ment', '', 1) 3724 OR $this->replace($word, 'ent', '', 1); 3725 break; 3726 3727 case 'o': 3728 if (substr($word, -4) == 'tion' OR substr($word, -4) == 'sion') { 3729 $this->replace($word, 'ion', '', 1); 3730 } else { 3731 $this->replace($word, 'ou', '', 1); 3732 } 3733 break; 3734 3735 case 's': 3736 $this->replace($word, 'ism', '', 1); 3737 break; 3738 3739 case 't': 3740 $this->replace($word, 'ate', '', 1) 3741 OR $this->replace($word, 'iti', '', 1); 3742 break; 3743 3744 case 'u': 3745 $this->replace($word, 'ous', '', 1); 3746 break; 3747 3748 case 'v': 3749 $this->replace($word, 'ive', '', 1); 3750 break; 3751 3752 case 'z': 3753 $this->replace($word, 'ize', '', 1); 3754 break; 3755 } 3756 3757 return $word; 3758 } 3759 3760 function step5($word) 3761 { 3762 // Part a 3763 if (substr($word, -1) == 'e') { 3764 if ($this->m(substr($word, 0, -1)) > 1) { 3765 $this->replace($word, 'e', ''); 3766 3767 } else if ($this->m(substr($word, 0, -1)) == 1) { 3768 3769 if (!$this->cvc(substr($word, 0, -1))) { 3770 $this->replace($word, 'e', ''); 3771 } 3772 } 3773 } 3774 3775 // Part b 3776 if ($this->m($word) > 1 AND $this->doubleConsonant($word) AND substr($word, -1) == 'l') { 3777 $word = substr($word, 0, -1); 3778 } 3779 3780 return $word; 3781 } 3782 3783 function replace(&$str, $check, $repl, $m = null) 3784 { 3785 $len = 0 - strlen($check); 3786 3787 if (substr($str, $len) == $check) { 3788 $substr = substr($str, 0, $len); 3789 if (is_null($m) OR $this->m($substr) > $m) { 3790 $str = $substr . $repl; 3791 } 3792 3793 return true; 3794 } 3795 3796 return false; 3797 } 3798 3799 function m($str) 3800 { 3801 $c = $this->regex_consonant; 3802 $v = $this->regex_vowel; 3803 3804 $str = preg_replace("#^$c+#", '', $str); 3805 $str = preg_replace("#$v+$#", '', $str); 3806 3807 preg_match_all("#($v+$c+)#", $str, $matches); 3808 3809 return count($matches[1]); 3810 } 3811 3812 function doubleConsonant($str) 3813 { 3814 $c = $this->regex_consonant; 3815 3816 return preg_match("#$c{2}$#", $str, $matches) AND $matches[0]{0} == $matches[0]{1}; 3817 } 3818 3819 function cvc($str) 3820 { 3821 $c = $this->regex_consonant; 3822 $v = $this->regex_vowel; 3823 3824 return preg_match("#($c$v$c)$#", $str, $matches) 3825 AND strlen($matches[1]) == 3 3826 AND $matches[1]{2} != 'w' 3827 AND $matches[1]{2} != 'x' 3828 AND $matches[1]{2} != 'y'; 3829 } 3830 } 3831 3832 ?>