<?php 
/*#################################################################*\
|# Licence Number 0DT7-0122-0NW1-0210
|# -------------------------------------------------------------   #|
|# Copyright (c)2010 PHP Link Directory.                           #|
|# http://www.phplinkdirectory.com                                 #|
\*#################################################################*/
	
/**
# ################################################################################
# Project:   PHP Link Directory
#
# **********************************************************************
# Copyright (C) 2004-2009 NetCreated, Inc. (http://www.netcreated.com/)
#
# This software is for use only to those who have purchased a license.
# A license must be purchased for EACH installation of the software.
#
# By using the software you agree to the terms:
#
#    - You may not redistribute, sell or otherwise share this software
#      in whole or in part without the consent of the the ownership
#      of PHP Link Directory. Please contact david@david-duval.com
#      if you need more information.
#
#    - You agree to retain a link back to http://www.phplinkdirectory.com/
#      on all pages of your directory in you purchased the $25 version
#      of the software.
#
# License holders are entitled to upgrades to the 3.4 branch of the software
# as they are made available at http://www.phplinkdirectory.com/
#
# In some cases, license holders may be required to agree to changes
# in the software license before receiving updates to the software.
# **********************************************************************
#
# For questions, help, comments, discussion, etc., please join the
# PHP Link Directory Forum http://www.phplinkdirectory.com/forum/
#
# @link           http://www.phplinkdirectory.com/
# @copyright      2004-2009 NetCreated, Inc. (http://www.netcreated.com/)
# @projectManager David DuVal <david@david-duval.com>
# @package        PHPLinkDirectory
# @version        4.0.0
# ################################################################################
*/

//Define search page to print (search form, results page, etc)
//Default none
/*
$printSearchPage = false;
$tpl->assign('printSearchPage', $printSearchPage);
*/

//Define search types

require_once 'init.php';

$searchTemplates = array ( 'advanced'
                           //add more
                        );
$searchTemplate = (in_array (strtolower ($_REQUEST['type']), $searchTemplates) ? strtolower ($_REQUEST['type']) : '');

//Get search ID if available
$searchid = (isset ($_REQUEST['searchid']) && preg_match ('`^[\d]+$`', $_REQUEST['searchid']) ? intval ($_REQUEST['searchid']) : 0);
if (empty ($searchid))
{
   //No or no numeric search ID
   unset ($searchid);
}


if ($searchid)
{
   
   //Print search results page
   $printSearchPage = 'results';
   $tpl->assign('printSearchPage', $printSearchPage);

   
   //Disable any caching by the browser
   disable_browser_cache();

   //If current user is banned, show a custom error message
   //and stop the rest of the script
   check_if_banned();

   //Define dummy variable to store if results available or not
   $have_search_results = 0;

   //Get search preferences
   $getSearchPrefs = $db->GetRow("SELECT * FROM `{$tables['search']['name']}` WHERE `SEARCHID` = ".$db->qstr($searchid));
   if (!is_array ($getSearchPrefs) || empty ($getSearchPrefs))
   {
      //No valid search ID,
      //No results found
      $have_search_results = 0;
      $tpl->assign('have_search_results', $have_search_results);

      //Send nofollow,noindex headers
      $tpl->assign('MetaRobots', 'nofollow, noindex');

      $tpl->assign('error'   , $error);
      $tpl->assign('errorMsg', $errorMsg);

      //Clean whitespace
      $tpl->load_filter('output', 'trimwhitespace');

      //Make output
      echo $tpl->fetch('search.tpl');
      exit();
   }
   else
   {
      //Search preferences available
      $db->Execute("UPDATE `{$tables['search']['name']}` SET `COMPLETED` = '1' WHERE `SEARCHID` = ".$db->qstr($searchid));

      //Build path
      $path   = array ();
      $path[] = array ('ID' => '0', 'TITLE' => _L(SITE_NAME)        , 'TITLE_URL' => DOC_ROOT, 'DESCRIPTION' => SITE_DESC);
      $path[] = array ('ID' => '0', 'TITLE' => _L('Search Results') , 'TITLE_URL' => ''      , 'DESCRIPTION' => _L('Search Results'));
      $tpl->assign('path', $path);

      //Determine if boolean searches possible (need for sort by relevancy)
      $booleanPossible = (defined ('BOOLEAN_SEARCH_ACTIVE') && BOOLEAN_SEARCH_ACTIVE && version_compare (mysql_get_server_info(), '4.0.1', '>=') == 1);
      if (!$booleanPossible && strtolower ($searchPrefs['sortby']) == 'relevancy')
      {
         //Remove sorting by relevancy,
         //Boolean searches not possible
         unset ($searchPrefs['sortby']);
      }

      //Remove paging from URL
      $pattern = array ("/page-(\d+)\.htm[l]?/", '`([?]|[&])(p=)+[\d]*`', '`([?]|[&])(cat_page=)+[\d]*`', '`([?]|[&])(article_page=)+[\d]*`');
      $searchRequestURL = preg_replace ($pattern, '', request_uri());

      //Define a counter to track *all* found results
      //Used only to display error message
      $countSearchResults = 0;

      //Extract search preferences
      $searchPrefs = array();
      foreach ($getSearchPrefs as $field => $value)
      {
         if ($field == 'SEARCHTERMS' || $field == 'DISPLAYTERMS')
         {
            //Need to unserialize
            $termsArray = unserialize ($value);
            if (is_array ($termsArray))
            {
               foreach ($termsArray as $termKey => $termValue)
               {
                  $searchPrefs[strtolower($termKey)] = $termValue;
                  unset ($termsArray[$termKey], $termValue);
               }
            }
         }
         else
         {
            $searchPrefs[strtolower($field)] = $value;
         }
         unset ($getSearchPrefs[$field], $value);
      }

      //Don't add a WHERE option for category ID's if root/top is selected
      $incateg = array();
      if (!in_array (0, $searchPrefs['categchoice']) && !empty ($searchPrefs['categchoice']))
      {
         //Add all selected categories
         $incateg = $searchPrefs['categchoice'];

         //Add all subcategories if this is the case
         if ($searchPrefs['childcategs'])
         {
            foreach ($incateg as $cKey => $cID)
            {
               $subcategs = get_sub_categories($cID);
               if (is_array ($subcategs) && !empty ($subcategs))
               {
                  $incateg = array_merge ($incateg, $subcategs);
               }
               unset ($subcategs, $cKey, $cID);
            }
         }

         //Use unique category IDs
         $incateg = array_unique ($incateg);
         //Sort categories in ascending order
         sort ($incateg);
      }

      $tpl->assign('searchquery', $searchPrefs['query']);


      ##################################################
      ################# CATEGORY SEARCH ################
      ##################################################
      if (in_array ('categories', $searchPrefs['location']))
      {
         //Build category search preferences
         $search_preferences = array();
         //Add search query
         $search_preferences['search'] = $searchPrefs['query'];
         $search_preferences['Select_Options']  = array ( '*' );
         //Define WHERE options
         $search_preferences['Where_Options']   = array ("`STATUS` = '2'",
                                                         "`CACHE_TITLE` IS NOT NULL" ,
                                                         "`CACHE_URL` IS NOT NULL"
                                                         );
         $search_preferences['Where_Options'][] = '`HITS` '.($searchPrefs['hitless'] == 0 ? '>=' : '<').' '.$db->qstr($searchPrefs['hitlimit']);
         if (!empty ($incateg))
         {
            //Get categories from selected parent categories
            $search_preferences['Where_Options'][] = "`PARENT_ID` IN ('".implode ("', '", $incateg)."')";
         }


         $search_preferences['Search_Location'] = array ('TITLE');
         if (!$searchPrefs['titleonly'])
         {
            $search_preferences['Search_Location'][] = 'DESCRIPTION';
            $search_preferences['Search_Location'][] = 'META_DESCRIPTION';
            $search_preferences['Search_Location'][] = 'META_KEYWORDS';
         }

         $search_preferences['From_Table']      = $tables['category']['name'];

         switch (strtolower ($searchPrefs['sortby']))
         {
            case 'title' :
               $search_preferences['Order_Options'][] = '`TITLE` ' . $searchPrefs['sortorder'];
               break;
            case 'hits' :
               $search_preferences['Order_Options'][] = '`HITS` ' . $searchPrefs['sortorder'];
               break;
            case 'category' :
               $search_preferences['Order_Options'][] = '`PARENT_ID` ' . $searchPrefs['sortorder'];
               break;
         }

         //Use boolean search if possible
         $search_preferences['BooleanSearchActive'] = $booleanPossible;

         //Build search
         $CategorySearchResults = search($search_preferences);

         if (empty ($CategorySearchResults['errors']['empty_search']))
         {
            //Define category search results preferences
            $num_categs_per_page = 5;
            $categs_page_limit   = 3;

            //Count category search results
            $CountCategResults = $db->GetOne($CategorySearchResults['SQL_Count_All']);
            $CountCategResults = (empty ($CountCategResults) || $CountCategResults < 0 ? 0 : intval ($CountCategResults));

            if (!empty ($CountCategResults))
            {
               //Increment results counter
               $countSearchResults += $CountCategResults;

               $start_query = (!empty($_REQUEST['cat_page']) && preg_match('#^[\d]+$#', $_REQUEST['cat_page']) ? intval ($_REQUEST['cat_page']) : 1);

               //Get categories search results
               $ListCategs = $db->GetAll($CategorySearchResults['SQL_Query']." LIMIT ".($start_query <= 1 ? '0' : $start_query).", {$num_categs_per_page}");

               //Start category paging
               SmartyPaginate :: connect('CategoryPaging'); //Connect Paging
               if ($CountCategResults < 2)
               {
                  SmartyPaginate :: disconnect('CategoryPaging');
                  SmartyPaginate :: reset     ('CategoryPaging');
               }

               SmartyPaginate :: setPrevText    ('['._L('...less') .']' , 'CategoryPaging');
               SmartyPaginate :: setNextText    ('['._L('more...').']'  , 'CategoryPaging');
               SmartyPaginate :: setFirstText   ('['._L('First').']'    , 'CategoryPaging');
               SmartyPaginate :: setLastText    ('['._L('Last').']'     , 'CategoryPaging');
               SmartyPaginate :: setTotal       ($CountCategResults     , 'CategoryPaging');
               SmartyPaginate :: setUrlVar      ('cat_page'             , 'CategoryPaging');
               SmartyPaginate :: setUrl         ($searchRequestURL      , 'CategoryPaging');
               SmartyPaginate :: setCurrentItem ($start_query           , 'CategoryPaging');
               SmartyPaginate :: setLimit       ($num_categs_per_page   , 'CategoryPaging');
               SmartyPaginate :: setPageLimit   ($categs_page_limit     , 'CategoryPaging');
               SmartyPaginate :: assign         ($tpl                   , 'CategoryPaging', 'CategoryPaging');

               $tpl->assign('list_cat', $ListCategs);
               if (!empty ($ListCategs))
               {
                  $search_cat = $tpl->fetch('category_search.tpl');
                  $tpl->assign('search_category', $search_cat);
               }
            }
         }

         //Free memory
         unset ($CategorySearchResults, $search_preferences, $ListCategs, $categs_page_limit, $num_categs_per_page, $start_query, $search_cat);
      }//End category search


      ##################################################
      ################# ARTICLE SEARCH #################
      ##################################################
      if (in_array ('articles', $searchPrefs['location']))
      {
         //Build articles search preferences
         $search_preferences = array ();
         //Add search query
         $search_preferences['search'] = $searchPrefs['query'];
         $search_preferences['Select_Options']  = array (   '`ID`'                      ,
                                                            '`TITLE`'                   ,
                                                            '`DESCRIPTION`'             ,
                                                            '`ARTICLE`'                 ,
                                                            '`CATEGORY_ID`'
                                                         );
         $search_preferences['Where_Options']   = array ( "`STATUS` = '2'" );
         if (!empty ($incateg))
         {
            //Get articles from selected categories
            $search_preferences['Where_Options'][] = "`CATEGORY_ID` IN ('".implode ("', '", $incateg)."')";
         }

         $search_preferences['Search_Location'] = array ('TITLE');
         if (!$searchPrefs['titleonly'])
         {
            $search_preferences['Search_Location'][] = 'DESCRIPTION';
            $search_preferences['Search_Location'][] = 'ARTICLE';
         }

         $search_preferences['From_Table']      = $tables['article']['name'];

         switch (strtolower ($searchPrefs['sortby']))
         {
            case 'title' :
               $search_preferences['Order_Options'][] = '`TITLE` ' . $searchPrefs['sortorder'];
               break;
            case 'hits' :
               $search_preferences['Order_Options'][] = '`HITS` ' . $searchPrefs['sortorder'];
               break;
            case 'category' :
               $search_preferences['Order_Options'][] = '`CATEGORY_ID` ' . $searchPrefs['sortorder'];
               break;
         }

         //Use boolean search if possible
         $search_preferences['BooleanSearchActive'] = $booleanPossible;

         //Build search
         $ArticleSearchResults = search($search_preferences);

         if (empty ($ArticleSearchResults['errors']['empty_search']))
         {
            $num_articles_per_page = 5;
            $articles_page_limit   = 3;

            //Count articles search results
            $CountArticleResults = $db->GetOne($ArticleSearchResults['SQL_Count_All']);
            $CountArticleResults = (empty ($CountArticleResults) || $CountArticleResults < 0 ? 0 : intval ($CountArticleResults));

            if (!empty ($CountArticleResults))
            {
               //Increment results counter
               $countSearchResults += $CountArticleResults;

               $start_query = (!empty($_REQUEST['article_page']) && preg_match('`^[\d]+$`', $_REQUEST['article_page']) ? intval ($_REQUEST['article_page']) : 1);

               //Get articles search results
               $ListArticles = $db->GetAll($ArticleSearchResults['SQL_Query']." LIMIT ".($start_query <= 1 ? '0' : $start_query).", {$num_articles_per_page}");

               //Start article paging
               SmartyPaginate :: connect('ArticlePaging'); //Connect Paging
               if ($CountArticleResults < 2)
               {
                  SmartyPaginate :: disconnect('ArticlePaging');
                  SmartyPaginate :: reset     ('ArticlePaging');
               }

               SmartyPaginate :: setPrevText    ('['._L('...less') .']' , 'ArticlePaging');
               SmartyPaginate :: setNextText    ('['._L('more...').']'  , 'ArticlePaging');
               SmartyPaginate :: setFirstText   ('['._L('First').']'    , 'ArticlePaging');
               SmartyPaginate :: setLastText    ('['._L('Last').']'     , 'ArticlePaging');
               SmartyPaginate :: setTotal       ($CountArticleResults   , 'ArticlePaging');
               SmartyPaginate :: setUrlVar      ('article_page'         , 'ArticlePaging');
               SmartyPaginate :: setUrl         ($searchRequestURL      , 'ArticlePaging');
               SmartyPaginate :: setCurrentItem ($start_query           , 'ArticlePaging');
               SmartyPaginate :: setLimit       ($num_articles_per_page , 'ArticlePaging');
               SmartyPaginate :: setPageLimit   ($articles_page_limit   , 'ArticlePaging');
               SmartyPaginate :: assign         ($tpl                   , 'ArticlePaging', 'ArticlePaging');
// Articles Rewrite
foreach($ListArticles as $k => $v)
   $ListArticles[$k]['SEO_URL'] = seo_url($v['ID'], $v['TITLE'], REWRITE_TYPE, REWRITE_EXT, 2);              
 $tpl->assign('list_articles', $ListArticles);
               if (!empty ($ListArticles))
               {
                  $search_article = $tpl->fetch('article_search.tpl');
                  $tpl->assign('search_article', $search_article);
               }
            }
         }

         //Free memory
         unset ($ArticleSearchResults, $search_preferences, $ListArticles, $article_page_limit, $num_articles_per_page, $start_query, $search_article);
      }//End article search



      ##################################################
      ################### LINK SEARCH ##################
      ##################################################
      if (in_array ('links', $searchPrefs['location']))
      {
         //Build links search preferences
         $search_preferences = array();
         //Add search query
         $search_preferences['search'] = $searchPrefs['query'];
         $search_preferences['Select_Options']  = array ( '*' );
         //Define WHERE options
         $search_preferences['Where_Options']   = array ("`STATUS` = '2'",
                                                         "(`EXPIRY_DATE` >= ".$db->DBDate(time())." OR `EXPIRY_DATE` IS NULL)"
                                                         );
         $search_preferences['Where_Options'][] = '`HITS` '.($searchPrefs['hitless'] == 0 ? '>=' : '<').' '.$db->qstr($searchPrefs['hitlimit']);
         if (!empty ($incateg))
         {
            //Get links from selected categories
            $search_preferences['Where_Options'][] = "`CATEGORY_ID` IN ('".implode ("', '", $incateg)."')";
         }


         $search_preferences['Search_Location'] = array ('TITLE');
         if (!$searchPrefs['titleonly'])
         {
            $search_preferences['Search_Location'][] = 'URL';
            $search_preferences['Search_Location'][] = 'DESCRIPTION';
            $search_preferences['Search_Location'][] = 'META_DESCRIPTION';
            $search_preferences['Search_Location'][] = 'META_KEYWORDS';
		    $search_preferences['Search_Location'][] = 'ADDRESS';
			$search_preferences['Search_Location'][] = 'CITY';
			$search_preferences['Search_Location'][] = 'STATE';
			$search_preferences['Search_Location'][] = 'ZIP';
         }

         $search_preferences['From_Table']      = $tables['link']['name'];

         $search_preferences['Order_Options']   = array ('`FEATURED` DESC');

         switch (strtolower ($searchPrefs['sortby']))
         {
            case 'title' :
               $search_preferences['Order_Options'][] = '`TITLE` ' . $searchPrefs['sortorder'];
               break;
            case 'hits' :
               $search_preferences['Order_Options'][] = '`HITS` ' . $searchPrefs['sortorder'];
               break;
            case 'category' :
               $search_preferences['Order_Options'][] = '`CATEGORY_ID` ' . $searchPrefs['sortorder'];
               break;
         }

         //Use boolean search if possible
         $search_preferences['BooleanSearchActive'] = $booleanPossible;

         //Build search
         $LinksResults = search($search_preferences);

         if (empty ($LinksResults['errors']['empty_search']))
         {
            $PagerGroupings = (PAGER_GROUPINGS && PAGER_GROUPINGS > 0 ? intval (PAGER_GROUPINGS) : 20);
            $LinksPerPage   = (PAGER_LPP       && PAGER_LPP       > 0 ? intval (PAGER_LPP)       : 10);

            //Determine paging
            $current_item = (!empty ($_REQUEST['p']) && preg_match ('`^[\d]+$`', $_REQUEST['p']) ? intval ($_REQUEST['p']) : 1);
            $current_item--;
            //Determine page
            $page         = ceil ($current_item / PAGER_LPP);

            $page = ($page < 1 ? 1 : $page); // Check again for negative page

            //Build limit query
            $limit = ' LIMIT '.($current_item <= 1 ? '0' : $current_item).', '.PAGER_LPP;

            //Count link search results
            $CountLinkResults = $db->GetOne($LinksResults['SQL_Count_All']);
            $CountLinkResults = (empty ($CountLinkResults) || $CountLinkResults < 0 ? 0 : intval ($CountLinkResults));

            if (!empty ($CountLinkResults))
            {
               //Increment results counter
               $countSearchResults += $CountLinkResults;

               //Get link search results
               $links = $db->GetAll($LinksResults['SQL_Query'].$limit);

               //Add cached category URL and title for regular links
               $links = addCategPathToLinks($links);

               //Start link paging
               SmartyPaginate :: connect('MainPaging'); //Connect Paging
               if ($CountLinkResults < 2)
               {
                  SmartyPaginate :: disconnect('MainPaging');
                  SmartyPaginate :: reset     ('MainPaging');
               }

               SmartyPaginate :: setPrevText    ('Previous'              , 'MainPaging');
               SmartyPaginate :: setNextText    ('Next'                  , 'MainPaging');
               SmartyPaginate :: setFirstText   ('First'                 , 'MainPaging');
               SmartyPaginate :: setLastText    ('Last'                  , 'MainPaging');
               SmartyPaginate :: setTotal       ($CountLinkResults       , 'MainPaging');
               SmartyPaginate :: setUrlVar      ('p'                     , 'MainPaging');
               SmartyPaginate :: setUrl         ($searchRequestURL       , 'MainPaging');
               SmartyPaginate :: setCurrentItem ($current_item + 1       , 'MainPaging');
               SmartyPaginate :: setLimit       ($LinksPerPage           , 'MainPaging');
               SmartyPaginate :: setPageLimit   ($PagerGroupings         , 'MainPaging');
               SmartyPaginate :: assign         ($tpl                    , 'MainPaging', 'MainPaging');

              // Links Rewrite
             foreach($links as $k => $v)
$links[$k]['SEO_URL'] = seo_url($v['ID'], $v['TITLE'], REWRITE_TYPE, REWRITE_EXT, 2);
$tpl->assign('links', $links);
            }
         }

         //Free memory
         unset ($LinksResults, $search_preferences, $LinksPerPage, $PagerGroupings, $current_item);
      }//End article search


      //Prepare for output
      $have_search_results = ($countSearchResults > 0 ? 1 : 0);
      $tpl->assign('have_search_results', $have_search_results);

      //Send nofollow,noindex headers
      $tpl->assign('MetaRobots', 'nofollow, noindex');

      $tpl->assign('error'   , $error);
      $tpl->assign('errorMsg', $errorMsg);

      //Clean whitespace
      $tpl->load_filter('output', 'trimwhitespace');

  
      
      //Make output
      echo $tpl->fetch('search.tpl');
      exit();
   }
}//IF searchid

if ($searchTemplate == 'advanced')
{ //Draw the advanced search page and save preferences
   require_once('init.php');

   //Print search form page
   $printSearchPage = 'form';
   $tpl->assign('printSearchPage', $printSearchPage);

   //Disable any caching by the browser
   disable_browser_cache();

   //If current user is banned, show a custom error message
   //and stop the rest of the script
   check_if_banned();

   //Build path
   $path   = array ();
   $path[] = array ('ID' => '0', 'TITLE' => _L(SITE_NAME), 'TITLE_URL' => DOC_ROOT, 'DESCRIPTION' => SITE_DESC);
   $path[] = array ('ID' => '0', 'TITLE' => _L('Search') , 'TITLE_URL' => ''      , 'DESCRIPTION' => _L('Search Directory'));
   $tpl->assign('path', $path);

   //Search in title only select options
   $titleonlyOptions = array ( 0 => _L('Search all fields'), //Search title, URL, description, etc.
                               1 => _L('Search Titles Only') //Search only in title
                              );
   $tpl->assign('titleonlyOptions', $titleonlyOptions);

   $locationOptions = array ( 'links'        => _L('Links').(FTR_ENABLE ? ' ('._L('Featured links first').')' : ''),
                              'articles'     => _L('Articles'),
                              'categories'   => _L('Categories')
                            );
   $tpl->assign('locationOptions', $locationOptions);

   //Hitlimits
   $hitlessOptions = array (  0 => _L('At Least'),
                              1 => _L('At Most')
                           );
   $tpl->assign('hitlessOptions', $hitlessOptions);

   //Results sorting
   $sortbyOptions = array ();
   if (version_compare (mysql_get_server_info(), '4.0.1', '>=') == 1)
   {
      $sortbyOptions['relevancy'] = _L('Relevancy');//Relevancy for Boolean search only
   }
   $sortbyOptions['title']    = _L('Title');
   $sortbyOptions['hits']     = _L('Hits');
   $sortbyOptions['category'] = _L('Category'); //Category ID, or parent category ID


   $tpl->assign('sortbyOptions', $sortbyOptions);
   $sortorderOptions = array (   'desc' => _L('in descending order'),
                                 'asc'  => _L('in ascending order')
                              );
   $tpl->assign('sortorderOptions', $sortorderOptions);

   if (CAT_SELECTION_METHOD != 2) {
      //Search in categories
      $categchoiceOptions = get_regular_categs_tree(0);
      $categchoiceOptions[0] = _L('Search all open categories');
      $tpl->assign('categchoiceOptions', $categchoiceOptions);
   } else {
      $load_Javascript = 1;
      $tpl->assign('load_Javascript', $load_Javascript);
   }

   if (empty ($_POST['submit']))
   {
      //Set default search options
      $data = array();
      $data['titleonly']      = 0; //Search all fields by default
      $data['location']       = array ('links', 'articles', 'categories'); //Search in all (links,articles,categs) by default
      $data['hitless']        = 0; //Search results of at least X hits
      $data['hitlimit']       = 0; //Search results of 0 (zero) hitlimit
      $data['sortby']         = 'relevancy'; //Sort results by relevancy
      $data['sortorder']      = 'desc'; //Sort results in descending order
      $data['categchoice']    = 0; //Search in all categories by default
      $data['childcategs']    = 1; //Search in all subcategories by default

      //Clear some varialbles
      if (isset($_SESSION['SmartyPaginate']))
         unset ($_SESSION['SmartyPaginate']);
      if (isset($_SESSION['SmartyValidate']))
         unset ($_SESSION['SmartyValidate']);

      SmartyValidate :: disconnect();
      SmartyValidate :: connect($tpl, true);
      
        //for login

        if (!SmartyValidate :: is_registered_form('login')) {
        
        SmartyValidate :: register_form('login', true);
        SmartyValidate :: register_validator('v_user', 'user', 'notEmpty', false, false, 'trim', 'login');
        SmartyValidate :: register_validator('v_pass', 'pass', 'notEmpty', false, false, 'trim', 'login');
        }
        //end for login
      
      SmartyValidate :: register_form('search', true);

      SmartyValidate :: register_validator('v_search'      , 'search'      , 'notEmpty' , false, false, 'trim', 'search');
      SmartyValidate :: register_validator('v_titleonly'   , 'titleonly'   , 'notEmpty' , true , false, 'trim', 'search');

      SmartyValidate :: register_validator('v_location'    , 'location'    , 'notEmpty' , false, false, 'trim', 'search');

      SmartyValidate :: register_validator('v_hitless'     , 'hitless'     , 'notEmpty' , true , false, 'trim', 'search');
      SmartyValidate :: register_validator('v_hitlimit'    , 'hitlimit'    , 'isInt'    , true , false, 'trim', 'search');

      SmartyValidate :: register_validator('v_sortby'      , 'sortby'      , 'notEmpty' , false, false, 'trim', 'search');
      SmartyValidate :: register_validator('v_sortorder'   , 'sortorder'   , 'notEmpty' , false, false, 'trim', 'search');

      SmartyValidate :: register_validator('v_categchoice' , 'categchoice' , 'notEmpty' , false, false, 'trim', 'search');
      SmartyValidate :: register_validator('v_childcategs' , 'childcategs' , 'notEmpty' , true , false, 'trim', 'search');
   }
   else
   {
      SmartyValidate :: connect($tpl);

      $data = array ();
      $data['search']    = (!empty ($_POST['search']) ? clean_search_query($_POST['search']) : '');
      $data['titleonly'] = (!empty ($_POST['titleonly']) && array_key_exists ($_POST['titleonly'], $titleonlyOptions) ? intval ($_POST['titleonly']): 0);
      
      $data['location'] = (is_array ($_POST['location']) && !empty ($_POST['location']) ? $_POST['location'] : '');
      //Keep only correct values of search location
      if (is_array ($data['location']))
      {
         foreach ($data['location'] as $key => $loc)
         {
            if (!array_key_exists ($loc, $locationOptions))
               unset ($data['location'][$key]);
         }

         if (empty ($data['location']))
            $data['location'] = '';
      }

      $data['hitless']  = (!empty ($_POST['hitless']) && array_key_exists ($_POST['hitless'], $hitlessOptions) ? intval ($_POST['hitless']): 0);
      $data['hitlimit'] = (preg_match ('`^[\d]+$`', $_POST['hitlimit']) ? intval ($_POST['hitlimit']) : 0);

      $data['sortby']  = (!empty ($_POST['sortby']) && array_key_exists ($_POST['sortby'], $sortbyOptions) ? $_POST['sortby'] : 'relevancy');
      $data['sortorder']  = (!empty ($_POST['sortorder']) && array_key_exists ($_POST['sortorder'], $sortorderOptions) ? $_POST['sortorder'] : 'desc');

      $data['categchoice'] = (is_array ($_POST['categchoice']) ? $_POST['categchoice'] : array());
      if (empty ($data['categchoice']))
      {
         //No categories selected,
         //search in all of them
         $data['categchoice'][0] = 0;
      }
      $data['categchoice'] = array_unique ($data['categchoice']);//Remove duplicate entries
      $data['childcategs'] = (!empty ($_POST['childcategs']) ? 1 : 0);

      if (SmartyValidate :: is_valid($data, 'search'))
      {
         //Build database entries
         $dbdata = array();
         $dbdata['USERID'] = (isset ($_SESSION['phpld']['user']['id']) ? intval ($_SESSION['phpld']['user']['id']) : 0);
         $dbdata['IPADDRESS'] = $client_info['IP'];
         $dbdata['QUERY'] = $data['search'];
         $dbdata['SORTBY'] = $data['sortby'];
         $dbdata['SORTORDER'] = strtoupper ($data['sortorder']);
         $dbdata['SEARCHTIME']  = gmdate ('Y-m-d H:i:s');

         $searchterms = array();
         $searchterms['titleonly']   = $data['titleonly'];
         $searchterms['location']    = $data['location'];
         $searchterms['hitless']     = $data['hitless'];
         $searchterms['hitlimit']    = $data['hitlimit'];
         $searchterms['categchoice'] = $data['categchoice'];
         $searchterms['childcategs'] = $data['childcategs'];
         $dbdata['SEARCHTERMS'] = serialize ($searchterms);

         $displayterms = array();
         $displayterms['sortby']    = $data['sortby'];
         $displayterms['sortorder'] = $data['sortorder'];
         $dbdata['DISPLAYTERMS'] = serialize ($displayterms);

         $dbdata['COMPLETED'] = 0;

         unset ($searchterms, $displayterms);

         //Save search preferences into database
         $saveSearch = $db->Replace($tables['search']['name'], $dbdata, 'ID', true);

         //Get insert ID
         $searchid = mysql_insert_id();
         $searchid = (!empty ($searchid) ? intval ($searchid) : 0);

         if ($newCatId < 1)
         {
            //"mysql_insert_id()" failed, try to get ID via MySQL query
            $mysql_id = $db->GetOne("SELECT MAX(ID) AS `maxid` FROM `{$tables['search']['name']}`");
            $searchid = intval ($searchid);
         }

         if (!empty ($saveSearch))
         {
            //Redirect to search results
            http_custom_redirect(DOC_ROOT."/search.php?searchid={$searchid}");
         }
         else
         {
            //Print error that occured while saving
            $error = 1;
            $errorMsg = $db->ErrorMsg();
         }
      }
   }

   $tpl->assign($data);
   $tpl->assign('error'   , $error);
   $tpl->assign('errorMsg', $errorMsg);

   //Clean whitespace
   $tpl->load_filter('output', 'trimwhitespace');

   //Make output
   echo $tpl->fetch('search.tpl');
   exit();
}//IF type=advanced




function search($search_preferences)
{
   global $tables, $db;

// Initialize search options array
if (!is_array ($search_preferences) || empty ($search_preferences))
   $search_preferences = array();

// Determine fields to search in
if (!is_array ($search_preferences['Select_Options']) || empty ($search_preferences['Select_Options']))
   $search_preferences['Select_Options'] = array ( '*' );

// Determine query options */
if (!is_array ($search_preferences['Where_Options']) || empty ($search_preferences['Where_Options']))
   $search_preferences['Where_Options'] = array ("`STATUS` = 2", '`ID` > 1');

// Determine search results order
if (!is_array ($search_preferences['Order_Options']) || empty ($search_preferences['Order_Options']))
   $search_preferences['Order_Options'] = array ( '`ID` ASC' );

// Determine search location
if (!is_array ($search_preferences['Order_Options']) || empty ($search_preferences['Order_Options']))
   $search_preferences['Search_Location'] = array ( 'TITLE', 'URL', 'DESCRIPTION' );

// Determine table to search in */
$search_preferences['From_Table'] = (!empty ($search_preferences['From_Table']) ? trim ($search_preferences['From_Table']) : $tables['link']['name']);
if (strpos (strtoupper ($search_preferences['From_Table']), 'FROM') !== 0)
   $search_preferences['From_Table'] = ' FROM `'.$search_preferences['From_Table'].'`';

// Determine the minimum number of letters for a fulltext search

//this i commented since i want to search short ids as well
//$Request_MinWordLength = $db->GetAssoc("SHOW VARIABLES LIKE 'ft_min_word_len'");

//since i'm now searching for id as well, min_word_length more than 4 is not ok anymore. i'm setting it to 1 now
//$search_preferences['Min_Word_Length'] = ($Request_MinWordLength != false ? $Request_MinWordLength['ft_min_word_len'] : 4);

$search_preferences['Min_Word_Length'] = ($Request_MinWordLength != false ? $Request_MinWordLength['ft_min_word_len'] : 1);
unset($Request_MinWordLength);

// Check if the boolean search mode is suported by MySQL version
$search_preferences['BooleanSearchPossible'] = version_compare (mysql_get_server_info(), '4.0.1', '>=') == 1;

$search_preferences['BooleanSearchActive']   = (isset ($search_preferences['BooleanSearchActive']) ? $search_preferences['BooleanSearchActive'] : BOOLEAN_SEARCH_ACTIVE);

// Populate array with words that are removed by default
$search_preferences['Black_List']      = array ('img', 'url', 'quote', 'www', 'http', 'https', 'ftp', 'the', 'is', 'it', 'are', 'if');

if (empty ($search_preferences['search'])) // Check search words
{
   if (!empty ($_GET['search']))
      $search_preferences['search'] = clean_search_query ($_GET['search']);
   elseif (!empty ($_POST['search']))
      $search_preferences['search'] = clean_search_query ($_POST['search']);
   elseif (!empty ($_REQUEST['search']))
      $search_preferences['search'] = clean_search_query ($_REQUEST['search']);
   else
      $search_preferences['search'] = '';
}

// Check again for search words
if (empty ($search_preferences['search']))
   $search_preferences['errors']['empty_search'] = 1;
else
   $search_preferences['errors']['empty_search'] = 0;

// Extract phrase(s) that needs exact matching
preg_match_all ('/(?:^|\s)([+-]?)"([^"]+)"(?:$|\s)/', $search_preferences['search'], $matches, PREG_PATTERN_ORDER);

// Dummy arrays to store search values
$Search_Array  = $matches[2];
$Exclude_Words = array ();

// Remove the exact matching phrase(s) and extract the words
$Keyword_Array = explode (' ', preg_replace ('/(?:^|\s)([+-]?)"([^"]+)"(?:$|\s)/', ' ', $search_preferences['search']));

// Initialize two arrays to store keywords to search for and keywords that need to be excluded
$search_preferences['Exclude_Words'] = array ();
$search_preferences['Search_Words']  = array ();

// Check for -"common phrase"
foreach ($matches[1] as $key => $phrase)
   if ($phrase == '-')
   {
      $phrase = strtolower (trim ($Search_Array[$key]));
      if (!empty ($phrase) && !in_array ($phrase, $search_preferences['Black_List']))
         $Exclude_Words[] = $phrase;
      unset ($Search_Array[$key]);
   }

// Check for -keyword
foreach ($Keyword_Array as $key => $word) {
   $word = trim ($word);
   if (strpos ($word, '-') === 0)
   {
      $word = preg_replace ('`([-+"])`', '', $word);
      $word = trim ($word);
      if (!empty ($word) && !in_array ($word, $search_preferences['Black_List']))
         $Exclude_Words[] = $word;
      unset ($Keyword_Array[$key]);
   }
}

$Search_Array = array_merge ($Search_Array, $Keyword_Array);

unset ($Keyword_Array); // Free some memory

// Clean excluded keywords, remove duplicates and of shorter length than allowed
foreach ($Exclude_Words as $key => $value)
{
   $Exclude_Words[$key] = strtolower (trim ($value)); // Remove unneded chars
   $Keyword_Array = explode (' ', $Exclude_Words[$key]);

   foreach($Keyword_Array as $KeywKey => $keyword) {
      $keyword = trim($keyword);
      // Check current keyword
      if (strlen ($keyword) >= $search_preferences['Min_Word_Length'] && !in_array ($keyword, $search_preferences['Black_List']))
         $search_preferences['Exclude_Words'][] = $keyword; // Add keyword
      unset ($Keyword_Array[$KeywKey]); // Free some memory
   }
   unset ($Exclude_Words[$key]); // Free some memory
}
$search_preferences['Exclude_Words'] = array_slice (array_unique ($search_preferences['Exclude_Words']), 0, 20);
unset ($Exclude_Words, $Keyword_Array); // Free some memory

// Clean keywords, remove duplicates and of shorter length than allowed
foreach ($Search_Array as $key => $value)
{
   $Search_Array[$key] = strtolower (trim ($value)); // Remove unneded chars
   $Keyword_Array = explode (' ', $Search_Array[$key]);

   foreach($Keyword_Array as $KeywKey => $keyword) {
      $keyword = trim ($keyword);
      // Check current keyword
      if (strlen ($keyword) >= $search_preferences['Min_Word_Length'] && !in_array($keyword, $search_preferences['Black_List']))
         $search_preferences['Search_Words'][] = $keyword; // Add keyword
      unset ($Keyword_Array[$KeywKey]);
   }
   unset ($Search_Array[$key]); // Free some memory
}
$search_preferences['Search_Words'] = array_slice (array_unique ($search_preferences['Search_Words']), 0, 20);
unset ($Search_Array, $Keyword_Array); // Free some memory

$search_preferences['Relevancy_Order']  = '';
$search_preferences['Relevancy_Tuning'] = '';
$search_preferences['Select_Relevancy'] = '';
$Count_All_Keywords = count($search_preferences['Search_Words']) + count($search_preferences['Exclude_Words']);
if ($Count_All_Keywords > 0)
if ($search_preferences['BooleanSearchPossible'] == 1 && $search_preferences['BooleanSearchActive'] == 1) // Build boolean search query
{
   // Build search location
   $location = "";
   foreach ($search_preferences['Search_Location'] as $ThisLocation)
   {
      $ThisLocation = trim ($ThisLocation);
      if (strpos ($ThisLocation, '.') === false)
         $ThisLocation = (!empty ($ThisLocation) ? '`'.$ThisLocation.'`' : '');
      $location    .= (!empty ($ThisLocation) ? $ThisLocation.', ' : '');
   }
   $location = preg_replace('`,[\s]*$`', '', $location); // Remove trailing comma and space

   //$BooleanSelect   = ' AS `relevancy`'; // Add field for relevant results order

   // Build query
   $search_preferences['Search_Query'] = "MATCH (".$location.") AGAINST ('";
/*
   foreach ($search_preferences['Search_Words'] as $word)
      $search_preferences['Search_Query'] .= ''.$word.' '; // Add keywords to search for
   foreach ($search_preferences['Exclude_Words'] as $word)
      $search_preferences['Search_Query'] .= '-'.$word.' '; // Add keywords to be excluded from search
*/

   $search_preferences['Search_Query']    .= $search_preferences['search'];

   $search_preferences['Search_Query']     = trim ($search_preferences['Search_Query']);
   $search_preferences['Search_Query']    .= "' IN BOOLEAN MODE)";
   $search_preferences['Select_Relevancy']   = $search_preferences['Search_Query'].' AS `relevancy`';
   $search_preferences['Select_Options'][] = $search_preferences['Select_Relevancy'];
   $search_preferences['Relevancy_Order']  = '`relevancy` DESC';
   $search_preferences['Relevancy_Tuning'] = ' HAVING `relevancy` > 0.2 ';
}
else // Build regular search query
{
   $search_preferences['Search_Query'] = '';

   // Build query for needed keywords
   if (count ($search_preferences['Search_Words']) > 0)
   {
      $search_preferences['Search_Query'] .= "(";
      foreach ($search_preferences['Search_Words'] as $word)
         foreach ($search_preferences['Search_Location'] as $ThisLocation) {
            $ThisLocation = trim ($ThisLocation);
            if (strpos ($ThisLocation, '.') === false)
               $ThisLocation = (!empty ($ThisLocation) ? '`'.$ThisLocation.'`' : '');
            $search_preferences['Search_Query'] .= $ThisLocation." LIKE ".$db->qstr('%'.$word.'%')." OR ";
         }

      /* Remove trailing AND/OR and space */
      $search_preferences['Search_Query']  = preg_replace ('`[\s]+(AND|OR){1,1}[\s]*$`', '', $search_preferences['Search_Query']);
      $search_preferences['Search_Query'] .= ') '; // Close search for needed words
   }

   // Build query for excluded keywords
   if(count($search_preferences['Exclude_Words']) > 0)
   {
      $search_preferences['Search_Query'] .= " AND (";
      foreach ($search_preferences['Exclude_Words'] as $word)
         foreach($search_preferences['Search_Location'] as $ThisLocation)
            $search_preferences['Search_Query'] .= '`'.trim ($ThisLocation).'`'." NOT LIKE ".$db->qstr('%'.$word.'%')." AND ";

      // Remove trailing AND/OR and space
      $search_preferences['Search_Query']  = preg_replace ('`[\s]+(AND|OR){1,1}[\s]*$`', '', $search_preferences['Search_Query']);
      $search_preferences['Search_Query'] .= ') '; // Close search for excluded words
   }
}
$search_preferences['Where_Options'][] = $search_preferences['Search_Query'];

// Start building the complete query
$search_preferences['SQL_Query']     = '';



// Start building the count query
$search_preferences['SQL_Count_All'] = 'SELECT COUNT(*) ';

// Build SELECT
$search_preferences['Search_Select'] = 'SELECT ';
if (is_array ($search_preferences['Select_Options']) && !empty ($search_preferences['Select_Options']))
{
   foreach ($search_preferences['Select_Options'] as $SelectOption) {
      $SelectOption = trim ($SelectOption);
         $search_preferences['Search_Select'] .= $SelectOption.', ';
   }
   unset ($search_preferences['Select_Options']);
}
// Remove trailing comma and space
$search_preferences['SQL_Query']     .= preg_replace ('`,[\s]*$`', '', $search_preferences['Search_Select']);
//$search_preferences['SQL_Count_All'] .= (!empty($search_preferences['Select_Relevancy']) ? ', '.$search_preferences['Select_Relevancy'] : '');
unset ($search_preferences['Search_Select']);

// Add table within to search */
$search_preferences['SQL_Query']     .= $search_preferences['From_Table'];
$search_preferences['SQL_Count_All'] .= $search_preferences['From_Table'];

// Build WHERE
$search_preferences['Search_Where'] = ' WHERE 1 ';
if (is_array ($search_preferences['Where_Options']) && !empty ($search_preferences['Where_Options']))
{
   foreach ($search_preferences['Where_Options'] as $WhereOption)
   {
      $WhereOption = trim ($WhereOption);
      if (!empty ($WhereOption))
         $search_preferences['Search_Where'] .= ' AND '.$WhereOption.' ';
   }
   unset ($search_preferences['Where_Options']);
}

// Remove trailing 'AND' / 'OR'
$where .= preg_replace ('`[\s]+(AND|OR){1,1}[\s]*$`', '', $search_preferences['Search_Where']);
$search_preferences['SQL_Query']     .= $where.' '.trim ($search_preferences['Relevancy_Tuning']);
$search_preferences['SQL_Count_All'] .= $where;
unset ($search_preferences['Search_Where'], $where);

// Build ORDER BY
$search_preferences['Search_Order'] = ' ORDER BY ';
if (is_array ($search_preferences['Order_Options']) && !empty ($search_preferences['Order_Options']))
{
   $search_preferences['Search_Order'] .= (!empty ($search_preferences['Relevancy_Order']) ? $search_preferences['Relevancy_Order'].', ' : '');
   foreach ($search_preferences['Order_Options'] as $SearchOrder) {
      $SearchOrder = preg_replace ('`,[\s]*$`', '', $SearchOrder);
      $SearchOrder = trim ($SearchOrder);
      $search_preferences['Search_Order'] .= trim ($SearchOrder).', ';
   }
   unset ($search_preferences['Order_Options']);
}
/* Remove trailing comma and space */
$search_preferences['SQL_Query'] .= preg_replace ('`,[\s]*$`', '', $search_preferences['Search_Order']);
unset ($search_preferences['Search_Order']);

// Make nice query, remove multiple: spaces, '`' (safe slashes), 'AND', 'OR', ...
//$pattern = array ( '/(AND[\s])+/', '/(OR[\s])+/', '/\s+/', '/`+/', '`^[^\w\d]`', '`[^`\w\d]$`' );
$pattern = array ( '#(AND[\s])+#i', '#(OR[\s])+#i', '#[\s]+#', '#[`]+#', '#^[^\w\d]#i', '#[^`\w\d]$#i' );
$replace = array ( 'AND '        , 'OR '        , ' '    , '`'   , ''        , ''         );
$search_preferences['SQL_Query']     = preg_replace ($pattern, $replace, $search_preferences['SQL_Query']    );
$search_preferences['SQL_Count_All'] = preg_replace ($pattern, $replace, $search_preferences['SQL_Count_All']);

return $search_preferences;
}
?>