2004-03-15 22:17:17 -05:00
// Author: Kelvin Tan (kelvint at apache.org)
2002-12-03 06:47:26 -05:00
// JavaScript Lucene Query Validator
// Version: $Id$
2004-01-10 08:28:33 -05:00
// Tested: IE 6.0.2800 and Mozilla Firebird 0.7
// Special characters are + - && || ! ( ) { } [ ] ^ " ~ * ? : \
// Special words are (case-sensitive) AND NOT OR
2002-05-08 11:56:58 -04:00
2002-12-04 19:22:50 -05:00
// Makes wildcard queries case-insensitive if true.
2003-12-15 21:22:02 -05:00
// Refer to http://www.mail-archive.com/lucene-user@jakarta.apache.org/msg00646.html
2002-12-04 19:22:50 -05:00
var wildcardCaseInsensitive = true ;
// Mutator method for wildcardCaseInsensitive.
// @param Should wildcard queries be case-insensitive?
function setWildcardCaseInsensitive ( bool )
{
wildcardCaseInsensitive = bool ;
}
2004-03-15 22:17:17 -05:00
// Should the user be prompted with an alert box if validation fails?
2004-01-10 08:28:33 -05:00
var alertUser = true ;
function setAlertUser ( bool )
{
alertUser = bool ;
}
2002-05-08 11:56:58 -04:00
// validates a lucene query.
// @param Form field that contains the query
function doCheckLuceneQuery ( queryField )
{
2004-03-15 22:17:17 -05:00
return doCheckLuceneQueryValue ( queryField . value )
}
// validates a lucene query.
// @param query string
function doCheckLuceneQueryValue ( query )
{
2002-05-08 11:56:58 -04:00
if ( query != null && query . length > 0 )
{
2004-03-15 22:17:17 -05:00
query = removeEscapes ( query ) ;
2004-01-10 08:28:33 -05:00
// check for allowed characters
2004-03-15 22:17:17 -05:00
if ( ! checkAllowedCharacters ( query ) ) return false ;
2004-01-10 08:28:33 -05:00
2004-03-15 22:17:17 -05:00
// check * is used properly
if ( ! checkAsterisk ( query ) ) return false ;
2004-01-10 08:28:33 -05:00
// check for && usage
2004-03-15 22:17:17 -05:00
if ( ! checkAmpersands ( query ) ) return false ;
2004-01-10 08:28:33 -05:00
// check ^ is used properly
2004-03-15 22:17:17 -05:00
if ( ! checkCaret ( query ) ) return false ;
2004-01-10 08:28:33 -05:00
// check ~ is used properly
2004-03-15 22:17:17 -05:00
if ( ! checkSquiggle ( query ) ) return false ;
2004-01-10 08:28:33 -05:00
// check ! is used properly
2004-03-15 22:17:17 -05:00
if ( ! checkExclamationMark ( query ) ) return false ;
2004-01-10 08:28:33 -05:00
// check question marks are used properly
2004-03-15 22:17:17 -05:00
if ( ! checkQuestionMark ( query ) ) return false ;
2004-01-10 08:28:33 -05:00
2002-05-08 11:56:58 -04:00
// check parentheses are used properly
2004-03-15 22:17:17 -05:00
if ( ! checkParentheses ( query ) ) return false ;
2002-05-08 11:56:58 -04:00
// check '+' and '-' are used properly
2004-03-15 22:17:17 -05:00
if ( ! checkPlusMinus ( query ) ) return false ;
2004-01-10 08:28:33 -05:00
// check AND, OR and NOT are used properly
2004-03-15 22:17:17 -05:00
if ( ! checkANDORNOT ( query ) ) return false ;
2002-12-03 06:47:26 -05:00
2002-05-08 11:56:58 -04:00
// check that quote marks are closed
2004-03-15 22:17:17 -05:00
if ( ! checkQuotes ( query ) ) return false ;
2002-12-03 06:47:26 -05:00
2002-05-08 11:56:58 -04:00
// check ':' is used properly
2004-03-15 22:17:17 -05:00
if ( ! checkColon ( query ) ) return false ;
2002-12-03 06:47:26 -05:00
if ( wildcardCaseInsensitive )
{
if ( query . indexOf ( "*" ) != - 1 )
{
2003-12-15 21:22:02 -05:00
var i = query . indexOf ( ':' ) ;
if ( i == - 1 )
{
2004-03-26 02:43:22 -05:00
query . value = query . toLowerCase ( ) ;
2003-12-15 21:22:02 -05:00
}
else // found a wildcard field search
{
2004-03-26 02:43:22 -05:00
query . value = query . substring ( 0 , i ) + query . substring ( i ) . toLowerCase ( ) ;
2003-12-15 21:22:02 -05:00
}
2002-12-03 06:47:26 -05:00
}
}
2002-05-08 11:56:58 -04:00
return true ;
}
}
2004-03-15 22:17:17 -05:00
// remove the escape character and the character immediately following it
function removeEscapes ( query )
{
return query . replace ( /\\./g , "" ) ;
}
function checkAllowedCharacters ( query )
{
2005-01-04 10:38:49 -05:00
matches = query . match ( /[^a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\^~\\@#\/$%'= ]/ ) ;
2004-03-15 22:17:17 -05:00
if ( matches != null && matches . length > 0 )
{
2004-05-17 07:53:59 -04:00
if ( alertUser ) alert ( "Invalid search query! The allowed characters are a-z A-Z 0-9. _ + - : () \" & * ? | ! {} [ ] ^ ~ \\ @ = # % $ ' /. Please try again." )
2004-03-15 22:17:17 -05:00
return false ;
}
return true ;
}
function checkAsterisk ( query )
{
matches = query . match ( /^[\*]*$|[\s]\*|^\*[^\s]/ ) ;
if ( matches != null )
{
if ( alertUser ) alert ( "Invalid search query! The wildcard (*) character must be preceded by at least one alphabet or number. Please try again." )
return false ;
}
return true ;
}
function checkAmpersands ( query )
{
// NB: doesn't handle term1 && term2 && term3 in Firebird 0.7
matches = query . match ( /[&]{2}/ ) ;
if ( matches != null && matches . length > 0 )
{
2005-01-04 10:38:49 -05:00
matches = query . match ( /^([a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\^~\\@#\/$%'=]+( && )?[a-zA-Z0-9_+\-:.()\"*?|!{}\[\]\^~\\@#\/$%'=]+[ ]*)+$/ ) ; // note missing & in pattern
2004-03-15 22:17:17 -05:00
if ( matches == null )
{
if ( alertUser ) alert ( "Invalid search query! Queries containing the special characters && must be in the form: term1 && term2. Please try again." )
return false ;
}
}
return true ;
}
function checkCaret ( query )
{
2005-01-04 10:38:49 -05:00
//matches = query.match(/^[^\^]*$|^([a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\~\\@#\/]+(\^[\d]+)?[ ]*)+$/); // note missing ^ in pattern
2004-03-15 22:17:17 -05:00
matches = query . match ( /[^\\]\^([^\s]*[^0-9.]+)|[^\\]\^$/ ) ;
if ( matches != null )
{
if ( alertUser ) alert ( "Invalid search query! The caret (^) character must be preceded by alphanumeric characters and followed by numbers. Please try again." )
return false ;
}
return true ;
}
function checkSquiggle ( query )
{
2005-01-04 10:38:49 -05:00
//matches = query.match(/^[^~]*$|^([a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\^\\@#\/]+(~[\d.]+|[^\\]\\~)?[ ]*)+$/); // note missing ~ in pattern
2004-03-15 22:17:17 -05:00
matches = query . match ( /[^\\]~[^\s]*[^0-9\s]+/ ) ;
if ( matches != null )
{
if ( alertUser ) alert ( "Invalid search query! The tilde (~) character must be preceded by alphanumeric characters and followed by numbers. Please try again." )
return false ;
}
return true ;
}
function checkExclamationMark ( query )
{
2004-05-17 07:53:59 -04:00
// foo! is not a query, but !foo is. hmmmm...
// NB: doesn't handle term1 ! term2 ! term3 or term1 !term2
2005-01-04 10:38:49 -05:00
matches = query . match ( /^[^!]*$|^([a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\^~\\@#\/$%'=]+( ! )?[a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\^~\\@#\/$%'=]+[ ]*)+$/ ) ;
2004-03-15 22:17:17 -05:00
if ( matches == null || matches . length == 0 )
{
if ( alertUser ) alert ( "Invalid search query! Queries containing the special character ! must be in the form: term1 ! term2. Please try again." )
return false ;
2004-05-17 07:53:59 -04:00
}
2004-03-15 22:17:17 -05:00
return true ;
}
function checkQuestionMark ( query )
{
2005-01-04 10:38:49 -05:00
matches = query . match ( /^(\?)|([^a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\^~\\@#\/$%'=]\?+)/ ) ;
2004-03-15 22:17:17 -05:00
if ( matches != null && matches . length > 0 )
{
if ( alertUser ) alert ( "Invalid search query! The question mark (?) character must be preceded by at least one alphabet or number. Please try again." )
return false ;
}
return true ;
}
function checkParentheses ( query )
{
var hasLeft = false ;
var hasRight = false ;
matchLeft = query . match ( /[(]/g ) ;
if ( matchLeft != null ) hasLeft = true
matchRight = query . match ( /[)]/g ) ;
if ( matchRight != null ) hasRight = true ;
if ( hasLeft || hasRight )
{
if ( hasLeft && ! hasRight || hasRight && ! hasLeft )
{
if ( alertUser ) alert ( "Invalid search query! Parentheses must be closed. Please try again." )
return false ;
}
else
{
var number = matchLeft . length + matchRight . length ;
if ( ( number % 2 ) > 0 || matchLeft . length != matchRight . length )
{
if ( alertUser ) alert ( "Invalid search query! Parentheses must be closed. Please try again." )
return false ;
}
}
matches = query . match ( /\(\)/ ) ;
if ( matches != null )
{
if ( alertUser ) alert ( "Invalid search query! Parentheses must contain at least one character. Please try again." )
return false ;
}
}
return true ;
}
function checkPlusMinus ( query )
{
2005-01-04 10:38:49 -05:00
matches = query . match ( /^[^\n+\-]*$|^([+-]?[a-zA-Z0-9_:.()\"*?&|!{}\[\]\^~\\@#\/$%'=]+[ ]?)+$/ ) ;
2004-03-15 22:17:17 -05:00
if ( matches == null || matches . length == 0 )
{
if ( alertUser ) alert ( "Invalid search query! '+' and '-' modifiers must be followed by at least one alphabet or number. Please try again." )
return false ;
}
return true ;
}
function checkANDORNOT ( query )
{
matches = query . match ( /AND|OR|NOT/ ) ;
if ( matches != null && matches . length > 0 )
{
2005-01-04 10:38:49 -05:00
matches = query . match ( /^([a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\^~\\@\/#$%'=]+\s*((AND )|(OR )|(AND NOT )|(NOT ))?[a-zA-Z0-9_+\-:.()\"*?&|!{}\[\]\^~\\@\/#$%'=]+[ ]*)+$/ ) ;
2004-05-17 07:53:59 -04:00
if ( matches == null || matches . length == 0 )
2004-03-15 22:17:17 -05:00
{
2004-05-17 07:53:59 -04:00
if ( alertUser ) alert ( "Invalid search query! Queries containing AND/OR/NOT must be in the form: term1 AND|OR|NOT|AND NOT term2 Please try again." )
return false ;
2004-03-15 22:17:17 -05:00
}
2004-05-17 07:53:59 -04:00
// its difficult to distinguish AND/OR/... from the usual [a-zA-Z] because they're...words!
matches = query . match ( /^((AND )|(OR )|(AND NOT )|(NOT ))|((AND)|(OR)|(AND NOT )|(NOT))[ ]*$/ )
if ( matches != null && matches . length > 0 )
2004-03-15 22:17:17 -05:00
{
2004-05-17 07:53:59 -04:00
if ( alertUser ) alert ( "Invalid search query! Queries containing AND/OR/NOT must be in the form: term1 AND|OR|NOT|AND NOT term2 Please try again." )
2004-03-15 22:17:17 -05:00
return false ;
}
}
return true ;
}
function checkQuotes ( query )
{
matches = query . match ( /\"/g ) ;
if ( matches != null && matches . length > 0 )
{
var number = matches . length ;
if ( ( number % 2 ) > 0 )
{
if ( alertUser ) alert ( "Invalid search query! Please close all quote (\") marks." ) ;
return false ;
}
matches = query . match ( /""/ ) ;
if ( matches != null )
{
if ( alertUser ) alert ( "Invalid search query! Quotes must contain at least one character. Please try again." )
return false ;
}
}
return true ;
}
function checkColon ( query )
{
matches = query . match ( /[^\\\s]:[\s]|[^\\\s]:$|[\s][^\\]?:|^[^\\\s]?:/ ) ;
if ( matches != null )
{
if ( alertUser ) alert ( "Invalid search query! Field declarations (:) must be preceded by at least one alphabet or number and followed by at least one alphabet or number. Please try again." )
return false ;
}
return true ;
}