<?php
/* This page produces search results.
*
* "Advanced Search" adds the ability to search other users' calendars.
* We do a number of security checks to make sure this is allowed.
*
* @author Craig Knudsen <cknudsen@cknudsen.com>
* @copyright Craig Knudsen, <cknudsen@cknudsen.com>, http://www.k5n.us/cknudsen
* @license http://www.gnu.org/licenses/gpl.html GNU GPL
* @package WebCalendar
* @version $Id: search_handler.php,v 1.46.2.6 2008/04/23 20:22:55 umcesrjones Exp $
*/
include_once 'includes/init.php';
$error = '';
// Disable if public access and OVERRIDE_PUBLIC in use
if ( $login == '__public__' && ! empty ( $OVERRIDE_PUBLIC ) &&
$OVERRIDE_PUBLIC == 'Y' ) {
print_header ();
echo print_not_auth ();
print_trailer ();
exit;
}
$keywords = getValue ( 'keywords' );
$advanced = getValue ( 'advanced' );
if ( strlen ( $keywords ) == 0 )
$error = translate ( 'You must enter one or more search keywords' ) . '.';
$matches = 0;
// Determine if this user is allowed to search the calendar of other users
$search_others = false; // show "Advanced Search"
if ( $single_user == 'Y' )
$search_others = false;
if ( $is_admin )
$search_others = true;
else
if ( access_is_enabled () )
$search_others = access_can_access_function ( ACCESS_ADVANCED_SEARCH );
else
if ( $login != '__public__' && ! empty ( $ALLOW_VIEW_OTHER ) &&
$ALLOW_VIEW_OTHER == 'Y' )
$search_others = true;
else
if ( $login == '__public__' && ! empty ( $PUBLIC_ACCESS_OTHERS ) &&
$PUBLIC_ACCESS_OTHERS == 'Y' )
$search_others = true;
$users = getValue ( 'users' );
if ( empty ( $users ) || empty ( $users[0] ) )
$search_others = false;
// Security precaution -- make sure users listed in participants list
// was not hacked up to include users that they don't really have access to.
if ( $search_others ) {
// If user can only see users in his group, then remove users not in his group.
if ( ! empty ( $USER_SEES_ONLY_HIS_GROUPS ) &&
$USER_SEES_ONLY_HIS_GROUPS == 'Y' && ! empty ( $GROUPS_ENABLED ) &&
$GROUPS_ENABLED == 'Y' ) {
$myusers = get_my_users ( '', 'view' );
$userlookup = array ();
for ( $i = 0, $cnt = count ( $myusers ); $i < $cnt; $i++ ) {
$userlookup[$myusers[$i]['cal_login']] = 1;
}
$newlist = array ();
$cnt = count ( $users );
for ( $i = 0; $i < $cnt; $i++ ) {
if ( ! empty ( $userlookup[$users[$i]] ) )
$newlist[] = $users[$i];
}
$users = $newlist;
}
// Now, use access control to remove more users :-)
if ( access_is_enabled () && ! $is_admin ) {
$newlist = array ();
for ( $i = 0; $i < count ( $users ); $i++ ) {
if ( access_user_calendar ( 'view', $users[$i] ) ) {
$newlist[] = $users[$i];
//echo "can access $users[$i] <br>";
} else {
//echo "cannot access $users[$i] <br>";
}
}
$users = $newlist;
}
}
if ( empty ( $users ) || empty ( $users[0] ) )
$search_others = false;
//Get advanced filters
$cat_filter = getPostValue ( 'cat_filter' );
$extra_filter = getPostValue ( 'extra_filter' );
$date_filter = getPostValue ( 'date_filter' );
$start_day = getPostValue ( 'from_day' );
$start_month = getPostValue ( 'from_month' );
$start_year = getPostValue ( 'from_year' );
if ( $start_year < 1970 )
$start_year = 1970;
$end_day = getPostValue ( 'until_day' );
$end_month = getPostValue ( 'until_month' );
$end_year = getPostValue ( 'until_year' );
if ( $end_year < 1970 )
$end_year = 1970;
$startDate = gmdate ( 'Ymd', gmmktime ( 0, 0, 0,
$start_month, $start_day, $start_year ) );
$endDate = gmdate ( 'Ymd', gmmktime ( 23, 59, 59,
$end_month, $end_day, $end_year ) );
print_header ();
echo '
<h2>' . translate ( 'Search Results' ) . '</h2>';
if ( ! empty ( $error ) )
echo print_error ( $error );
else {
// *** "Phrase" feature by Steve Weyer saweyer@comcast.net 4-May-2005
// check if keywords is surrounded by quotes
// an alternative might be to add a checkbox/list on search.php
// to indicate Phrase or other mode via an arg
// if a phrase, use (after removing quotes) rather than split into words
// also add query (keywords) to "match results" heading near end
// e.g., search_handler.php?keywords=%22Location:%20Arts%20and%20Crafts%22
// begin Phrase modification
$klen = strlen ( $keywords );
$phrasedelim = "\\\"";
$plen = strlen ( $phrasedelim );
if ( substr ( $keywords, 0, $plen ) == $phrasedelim &&
substr ( $keywords, $klen - $plen ) == $phrasedelim ) {
$phrase = substr ( $keywords, $plen, $klen - ( $plen * 2 ) );
$words = array ( $phrase );
} else
// original (default) behavior
$words = explode ( ' ', $keywords );
// end Phrase modification
$order = 'DESC';
$word_cnt = count ( $words );
for ( $i = 0; $i < $word_cnt; $i++ ) {
$sql_params = array ();
// Note: we only search approved/waiting events (not deleted).
$sql = 'SELECT we.cal_id, we.cal_name, we.cal_date, weu.cal_login '
. ( ! empty ( $extra_filter ) ? ', wse.cal_data ' : '' )
. 'FROM webcal_entry_user weu LEFT JOIN webcal_entry we '
. ( ! empty ( $cat_filter ) ? ', webcal_entry_categories wec ' : '')
. ( ! empty ( $extra_filter ) ? ', webcal_site_extras wse ' : '')
. 'ON weu.cal_id = we.cal_id
WHERE weu.cal_status in ( \'A\',\'W\' )
AND weu.cal_login IN ( ?';
if ( $search_others ) {
if ( empty ( $users[0] ) )
$sql_params[0] = $users[0] = $login;
$user_cnt = count ( $users );
for ( $j = 0; $j < $user_cnt; $j++ ) {
if ( $j > 0 ) $sql .= ', ?';
$sql_params[] = $users[$j];
}
} else
$sql_params[] = $login;
$sql .= ' ) ';
if ( $search_others ) {
// Don't search confidential entries of other users.
$sql .= 'AND ( weu.cal_login = ?
OR ( weu.cal_login != ? AND we.cal_access = \'P\' ) ) ';
$sql_params[] = $login;
$sql_params[] = $login;
}
// We get an error using mssql trying to read text column as varchar.
// This workaround seems to fix it up ROJ
// but, will only search the first 1kb of the description.
$sql .= 'AND ( UPPER( we.cal_name ) LIKE UPPER( ? ) OR UPPER( '
. ( strcmp ( $GLOBALS['db_type'], 'mssql' ) == 0
? 'CAST ( we.cal_description AS varchar (1024) )'
: 'we.cal_description' )
. ' ) LIKE UPPER( ? ) ';
$sql_params[] = '%' . $words[$i] . '%';
$sql_params[] = '%' . $words[$i] . '%';
//process advanced filters
if ( ! empty ( $extra_filter ) ) {
$sql .= ' OR wse.cal_data LIKE UPPER( ? )';
$sql_params[] = '%' . $words[$i] . '%';
}
//close AND statement from above
$sql .= ')';
if ( ! empty ( $cat_filter ) ) {
$sql .= ' AND wec.cat_id = ? AND we.cal_id = wec.cal_id ';
$sql_params[] = $cat_filter;
}
if ( ! empty ( $extra_filter ) )
$sql .= ' AND we.cal_id = wse.cal_id ';
if ( ! empty ( $date_filter ) ) {
if ( $date_filter == 1 ) { //Past entries
$sql .= 'AND we.cal_date < ? ';
$sql_params[] = date ( 'Ymd' );
}
if ( $date_filter == 2 ) {//Upcoming entries
$sql .= 'AND we.cal_date >= ? ';
$sql_params[] = date ( 'Ymd' );
$order = 'ASC';
}
if ( $date_filter == 3 ) {//Use Date Range
$sql .= 'AND ( we.cal_date >= ? AND we.cal_date <= ? )';
$sql_params[] = $startDate;
$sql_params[] = $endDate;
}
}
$res = dbi_execute ( $sql . ' ORDER BY we.cal_date ' . $order
. ', we.cal_name', $sql_params );
if ( $res ) {
while ( $row = dbi_fetch_row ( $res ) ) {
$info[$matches]['id'] = $row[0];
$info[$matches]['text'] = $row[1] . ' ( ' . date_to_str ( $row[2] ) . ' )';
$info[$matches]['user'] = $row[3];
$matches++;
}
}
dbi_free_result ( $res );
}
}
ob_start ();
echo '
<p><strong>';
if ( $matches > 0 ) {
// Let update_translation.pl pick up translations.
// translate ( 'match found' ) translate ( 'matches found' )
echo $matches . ' '
. translate ( // line break to bypass update_translation.pl here.
'match' . ( $matches == 1 ? '' : 'es' ) . ' found' );
} else
echo translate ( 'No matches found' );
echo ": " . htmlentities ( $keywords ) . '</strong>.</p>';
// now sort by number of hits
if ( empty ( $error ) ) {
echo '
<ul>';
foreach ( $info as $result ) {
echo '
<li><a class="nav" href="view_entry.php?id=' . $result['id']
. '&user=' . $result['user'] . '">' . $result['text'] . '</a></li>';
}
echo '
</ul>';
}
echo '
<form action="search.php' . ( ! empty ( $advanced ) ? '?adv=1' : '' )
. '" style="margin-left: 13px;" method="post">
<input type="submit" value="'
. translate ( 'New Search' ) . '" /></form>';
ob_end_flush ();
echo print_trailer ();
?>