xss protection

pull/338/head
Michael Christen 5 years ago
parent 090c0e56ab
commit 57484eb1cc

@ -112,24 +112,24 @@ public class yacysearch {
final boolean searchAllowed = sb.getConfigBool(SwitchboardConstants.PUBLIC_SEARCHPAGE, true) || adminAuthenticated; final boolean searchAllowed = sb.getConfigBool(SwitchboardConstants.PUBLIC_SEARCHPAGE, true) || adminAuthenticated;
boolean extendedSearchRights = adminAuthenticated; boolean extendedSearchRights = adminAuthenticated;
if(adminAuthenticated) { if(adminAuthenticated) {
authenticatedUserName = sb.getConfig(SwitchboardConstants.ADMIN_ACCOUNT_USER_NAME, "admin"); authenticatedUserName = sb.getConfig(SwitchboardConstants.ADMIN_ACCOUNT_USER_NAME, "admin");
} else { } else {
final UserDB.Entry user = sb.userDB != null ? sb.userDB.getUser(header) : null; final UserDB.Entry user = sb.userDB != null ? sb.userDB.getUser(header) : null;
if(user != null) { if(user != null) {
extendedSearchRights = user.hasRight(UserDB.AccessRight.EXTENDED_SEARCH_RIGHT); extendedSearchRights = user.hasRight(UserDB.AccessRight.EXTENDED_SEARCH_RIGHT);
authenticatedUserName = user.getUserName(); authenticatedUserName = user.getUserName();
} }
} }
final boolean localhostAccess = header.accessFromLocalhost(); final boolean localhostAccess = header.accessFromLocalhost();
final String promoteSearchPageGreeting = final String promoteSearchPageGreeting =
(env.getConfigBool(SwitchboardConstants.GREETING_NETWORK_NAME, false)) ? env.getConfig( (env.getConfigBool(SwitchboardConstants.GREETING_NETWORK_NAME, false)) ? env.getConfig(
"network.unit.description", "network.unit.description",
"") : env.getConfig(SwitchboardConstants.GREETING, ""); "") : env.getConfig(SwitchboardConstants.GREETING, "");
final String client = header.getRemoteAddr(); // the search client who initiated the search final String client = header.getRemoteAddr(); // the search client who initiated the search
// in case that the crawler is running and the search user is the peer admin, we expect that the user wants to check recently crawled document // in case that the crawler is running and the search user is the peer admin, we expect that the user wants to check recently crawled document
// to ensure that recent crawl results are inside the search results, we do a soft commit here. This is also important for live demos! // to ensure that recent crawl results are inside the search results, we do a soft commit here. This is also important for live demos!
if (extendedSearchRights && sb.getThread(SwitchboardConstants.CRAWLJOB_LOCAL_CRAWL).getJobCount() > 0) { if (extendedSearchRights && sb.getThread(SwitchboardConstants.CRAWLJOB_LOCAL_CRAWL).getJobCount() > 0) {
@ -137,13 +137,14 @@ public class yacysearch {
} }
final boolean focus = (post == null) ? true : post.get("focus", "1").equals("1"); final boolean focus = (post == null) ? true : post.get("focus", "1").equals("1");
// get query // get query
final String originalquerystring = (post == null) ? "" : post.get("query", post.get("search", "")).trim(); String originalquerystring = (post == null) ? "" : post.get("query", post.get("search", "")).trim();
originalquerystring = originalquerystring.replace('<', ' ').replace('>', ' '); // light xss protection
String querystring = originalquerystring; String querystring = originalquerystring;
CacheStrategy snippetFetchStrategy = (post == null) ? null : CacheStrategy.parse(post.get("verify", sb.getConfig("search.verify", ""))); CacheStrategy snippetFetchStrategy = (post == null) ? null : CacheStrategy.parse(post.get("verify", sb.getConfig("search.verify", "")));
final servletProperties prop = new servletProperties(); final servletProperties prop = new servletProperties();
prop.put("topmenu", sb.getConfigBool("publicTopmenu", true) ? 1 : 0); prop.put("topmenu", sb.getConfigBool("publicTopmenu", true) ? 1 : 0);
prop.put("authSearch", authenticatedUserName != null); prop.put("authSearch", authenticatedUserName != null);
// produce vocabulary navigation sidebars // produce vocabulary navigation sidebars
Collection<Tagging> vocabularies = LibraryProvider.autotagging.getVocabularies(); Collection<Tagging> vocabularies = LibraryProvider.autotagging.getVocabularies();
@ -161,7 +162,7 @@ public class yacysearch {
final boolean rss = "rss.atom".contains(EXT); final boolean rss = "rss.atom".contains(EXT);
final boolean json = EXT.equals("json"); final boolean json = EXT.equals("json");
prop.put("promoteSearchPageGreeting", promoteSearchPageGreeting); prop.put("promoteSearchPageGreeting", promoteSearchPageGreeting);
// adding some additional properties needed for the rss feed // adding some additional properties needed for the rss feed
String peerContext = YaCyDefaultServlet.getContext(header, sb); String peerContext = YaCyDefaultServlet.getContext(header, sb);
prop.put("searchBaseURL", peerContext + "/yacysearch.html"); prop.put("searchBaseURL", peerContext + "/yacysearch.html");
@ -172,7 +173,7 @@ public class yacysearch {
boolean p2pmode = sb.peers != null && sb.peers.sizeConnected() > 0 && indexReceiveGranted; boolean p2pmode = sb.peers != null && sb.peers.sizeConnected() > 0 && indexReceiveGranted;
boolean global = post == null || (!post.get("resource-switch", post.get("resource", "global")).equals("local") && p2pmode); boolean global = post == null || (!post.get("resource-switch", post.get("resource", "global")).equals("local") && p2pmode);
boolean stealthmode = p2pmode && !global; boolean stealthmode = p2pmode && !global;
if ( post == null || indexSegment == null || env == null || !searchAllowed ) { if ( post == null || indexSegment == null || env == null || !searchAllowed ) {
if (indexSegment == null) ConcurrentLog.info("yacysearch", "indexSegment == null"); if (indexSegment == null) ConcurrentLog.info("yacysearch", "indexSegment == null");
// we create empty entries for template strings // we create empty entries for template strings
@ -214,18 +215,18 @@ public class yacysearch {
return prop; return prop;
} }
if (post.containsKey("auth") && authenticatedUserName == null) { if (post.containsKey("auth") && authenticatedUserName == null) {
/* /*
* Access to authentication protected features is explicitely requested here * Access to authentication protected features is explicitely requested here
* but no authentication is provided : ask now for authentication. * but no authentication is provided : ask now for authentication.
* Wihout this, after timeout of HTTP Digest authentication nonce, browsers no more send authentication information * Wihout this, after timeout of HTTP Digest authentication nonce, browsers no more send authentication information
* and as this page is not private, protected features would simply be hidden without asking browser again for authentication. * and as this page is not private, protected features would simply be hidden without asking browser again for authentication.
* (see mantis 766 : http://mantis.tokeek.de/view.php?id=766) * * (see mantis 766 : http://mantis.tokeek.de/view.php?id=766) *
*/ */
prop.authenticationRequired(); prop.authenticationRequired();
return prop; return prop;
} }
// check for JSONP // check for JSONP
if ( post.containsKey("callback") ) { if ( post.containsKey("callback") ) {
final String jsonp = post.get("callback") + "(["; final String jsonp = post.get("callback") + "([";
@ -245,7 +246,7 @@ public class yacysearch {
// time zone // time zone
int timezoneOffset = post.getInt("timezoneOffset", 0); int timezoneOffset = post.getInt("timezoneOffset", 0);
// collect search attributes // collect search attributes
// check an determine items per page (max of [100 or configured default]} // check an determine items per page (max of [100 or configured default]}
@ -295,18 +296,18 @@ public class yacysearch {
// find search domain // find search domain
final Classification.ContentDomain contentdom = post == null || !post.containsKey("contentdom") ? ContentDomain.ALL : ContentDomain.contentdomParser(post.get("contentdom", "all")); final Classification.ContentDomain contentdom = post == null || !post.containsKey("contentdom") ? ContentDomain.ALL : ContentDomain.contentdomParser(post.get("contentdom", "all"));
// Strict/extended content domain constraint : configured setting may be overriden by request param // Strict/extended content domain constraint : configured setting may be overriden by request param
final boolean strictContentDom = !Boolean.FALSE.toString().equalsIgnoreCase(post.get("strictContentDom", final boolean strictContentDom = !Boolean.FALSE.toString().equalsIgnoreCase(post.get("strictContentDom",
sb.getConfig(SwitchboardConstants.SEARCH_STRICT_CONTENT_DOM, sb.getConfig(SwitchboardConstants.SEARCH_STRICT_CONTENT_DOM,
String.valueOf(SwitchboardConstants.SEARCH_STRICT_CONTENT_DOM_DEFAULT)))); String.valueOf(SwitchboardConstants.SEARCH_STRICT_CONTENT_DOM_DEFAULT))));
/* Maximum number of suggestions to display in the first results page */ /* Maximum number of suggestions to display in the first results page */
final int meanMax = post.getInt("meanCount", 0); final int meanMax = post.getInt("meanCount", 0);
boolean jsResort = global boolean jsResort = global
&& (contentdom == ContentDomain.ALL || contentdom == ContentDomain.TEXT) // For now JavaScript resorting can only be applied for text search && (contentdom == ContentDomain.ALL || contentdom == ContentDomain.TEXT) // For now JavaScript resorting can only be applied for text search
&& sb.getConfigBool(SwitchboardConstants.SEARCH_JS_RESORT, SwitchboardConstants.SEARCH_JS_RESORT_DEFAULT); && sb.getConfigBool(SwitchboardConstants.SEARCH_JS_RESORT, SwitchboardConstants.SEARCH_JS_RESORT_DEFAULT);
// check the search tracker // check the search tracker
TreeSet<Long> trackerHandles = sb.localSearchTracker.get(client); TreeSet<Long> trackerHandles = sb.localSearchTracker.get(client);
@ -328,16 +329,16 @@ public class yacysearch {
ConcurrentLog.warn("LOCAL_SEARCH", "ACCESS CONTROL: BLACKLISTED CLIENT FROM " ConcurrentLog.warn("LOCAL_SEARCH", "ACCESS CONTROL: BLACKLISTED CLIENT FROM "
+ client + client
+ " gets no permission to search"); + " gets no permission to search");
if (!"html".equals(EXT)) { if (!"html".equals(EXT)) {
/* API request : return the relevant HTTP status */ /* API request : return the relevant HTTP status */
throw new TemplateProcessingException("You are not allowed to search the web with this peer.", throw new TemplateProcessingException("You are not allowed to search the web with this peer.",
HttpStatus.SC_FORBIDDEN); HttpStatus.SC_FORBIDDEN);
} }
} else if ( !extendedSearchRights && !localhostAccess && !intranetMode ) { } else if ( !extendedSearchRights && !localhostAccess && !intranetMode ) {
// in case that we do a global search or we want to fetch snippets, we check for DoS cases // in case that we do a global search or we want to fetch snippets, we check for DoS cases
final int accInThreeSeconds; final int accInThreeSeconds;
final int accInOneMinute; final int accInOneMinute;
final int accInTenMinutes; final int accInTenMinutes;
synchronized ( trackerHandles ) { synchronized ( trackerHandles ) {
accInThreeSeconds = accInThreeSeconds =
trackerHandles.tailSet(Long.valueOf(System.currentTimeMillis() - 3000)).size(); trackerHandles.tailSet(Long.valueOf(System.currentTimeMillis() - 3000)).size();
@ -348,14 +349,14 @@ public class yacysearch {
} }
// protections against too strong YaCy network load, reduces remote search // protections against too strong YaCy network load, reduces remote search
if ( global ) { if ( global ) {
if (accInTenMinutes >= sb.getConfigInt(SearchAccessRateConstants.PUBLIC_MAX_P2P_ACCESS_10MN.getKey(), if (accInTenMinutes >= sb.getConfigInt(SearchAccessRateConstants.PUBLIC_MAX_P2P_ACCESS_10MN.getKey(),
SearchAccessRateConstants.PUBLIC_MAX_P2P_ACCESS_10MN.getDefaultValue()) SearchAccessRateConstants.PUBLIC_MAX_P2P_ACCESS_10MN.getDefaultValue())
|| accInOneMinute >= sb.getConfigInt( || accInOneMinute >= sb.getConfigInt(
SearchAccessRateConstants.PUBLIC_MAX_P2P_ACCESS_1MN.getKey(), SearchAccessRateConstants.PUBLIC_MAX_P2P_ACCESS_1MN.getKey(),
SearchAccessRateConstants.PUBLIC_MAX_P2P_ACCESS_1MN.getDefaultValue()) SearchAccessRateConstants.PUBLIC_MAX_P2P_ACCESS_1MN.getDefaultValue())
|| accInThreeSeconds >= sb.getConfigInt( || accInThreeSeconds >= sb.getConfigInt(
SearchAccessRateConstants.PUBLIC_MAX_P2P_ACCESS_3S.getKey(), SearchAccessRateConstants.PUBLIC_MAX_P2P_ACCESS_3S.getKey(),
SearchAccessRateConstants.PUBLIC_MAX_P2P_ACCESS_3S.getDefaultValue())) { SearchAccessRateConstants.PUBLIC_MAX_P2P_ACCESS_3S.getDefaultValue())) {
global = false; global = false;
jsResort = false; jsResort = false;
ConcurrentLog.warn("LOCAL_SEARCH", "ACCESS CONTROL: CLIENT FROM " ConcurrentLog.warn("LOCAL_SEARCH", "ACCESS CONTROL: CLIENT FROM "
@ -369,13 +370,13 @@ public class yacysearch {
+ "/600s, " + "/600s, "
+ " requests, disallowed global search"); + " requests, disallowed global search");
} else if (accInTenMinutes >= sb.getConfigInt(SearchAccessRateConstants.PUBLIC_MAX_P2P_JSRESORT_ACCESS_10MN.getKey(), } else if (accInTenMinutes >= sb.getConfigInt(SearchAccessRateConstants.PUBLIC_MAX_P2P_JSRESORT_ACCESS_10MN.getKey(),
SearchAccessRateConstants.PUBLIC_MAX_P2P_JSRESORT_ACCESS_10MN.getDefaultValue()) SearchAccessRateConstants.PUBLIC_MAX_P2P_JSRESORT_ACCESS_10MN.getDefaultValue())
|| accInOneMinute >= sb.getConfigInt( || accInOneMinute >= sb.getConfigInt(
SearchAccessRateConstants.PUBLIC_MAX_P2P_JSRESORT_ACCESS_1MN.getKey(), SearchAccessRateConstants.PUBLIC_MAX_P2P_JSRESORT_ACCESS_1MN.getKey(),
SearchAccessRateConstants.PUBLIC_MAX_P2P_JSRESORT_ACCESS_1MN.getDefaultValue()) SearchAccessRateConstants.PUBLIC_MAX_P2P_JSRESORT_ACCESS_1MN.getDefaultValue())
|| accInThreeSeconds >= sb.getConfigInt( || accInThreeSeconds >= sb.getConfigInt(
SearchAccessRateConstants.PUBLIC_MAX_P2P_JSRESORT_ACCESS_3S.getKey(), SearchAccessRateConstants.PUBLIC_MAX_P2P_JSRESORT_ACCESS_3S.getKey(),
SearchAccessRateConstants.PUBLIC_MAX_P2P_JSRESORT_ACCESS_3S.getDefaultValue())) { SearchAccessRateConstants.PUBLIC_MAX_P2P_JSRESORT_ACCESS_3S.getDefaultValue())) {
jsResort = false; jsResort = false;
ConcurrentLog.warn("LOCAL_SEARCH", "ACCESS CONTROL: CLIENT FROM " ConcurrentLog.warn("LOCAL_SEARCH", "ACCESS CONTROL: CLIENT FROM "
+ client + client
@ -391,15 +392,15 @@ public class yacysearch {
} }
// protection against too many remote server snippet loads (protects traffic on server) // protection against too many remote server snippet loads (protects traffic on server)
if ( snippetFetchStrategy != null && snippetFetchStrategy.isAllowedToFetchOnline() ) { if ( snippetFetchStrategy != null && snippetFetchStrategy.isAllowedToFetchOnline() ) {
if (accInTenMinutes >= sb.getConfigInt( if (accInTenMinutes >= sb.getConfigInt(
SearchAccessRateConstants.PUBLIC_MAX_REMOTE_SNIPPET_ACCESS_10MN.getKey(), SearchAccessRateConstants.PUBLIC_MAX_REMOTE_SNIPPET_ACCESS_10MN.getKey(),
SearchAccessRateConstants.PUBLIC_MAX_REMOTE_SNIPPET_ACCESS_10MN.getDefaultValue()) SearchAccessRateConstants.PUBLIC_MAX_REMOTE_SNIPPET_ACCESS_10MN.getDefaultValue())
|| accInOneMinute >= sb.getConfigInt( || accInOneMinute >= sb.getConfigInt(
SearchAccessRateConstants.PUBLIC_MAX_REMOTE_SNIPPET_ACCESS_1MN.getKey(), SearchAccessRateConstants.PUBLIC_MAX_REMOTE_SNIPPET_ACCESS_1MN.getKey(),
SearchAccessRateConstants.PUBLIC_MAX_REMOTE_SNIPPET_ACCESS_1MN.getDefaultValue()) SearchAccessRateConstants.PUBLIC_MAX_REMOTE_SNIPPET_ACCESS_1MN.getDefaultValue())
|| accInThreeSeconds >= sb.getConfigInt( || accInThreeSeconds >= sb.getConfigInt(
SearchAccessRateConstants.PUBLIC_MAX_REMOTE_SNIPPET_ACCESS_3S.getKey(), SearchAccessRateConstants.PUBLIC_MAX_REMOTE_SNIPPET_ACCESS_3S.getKey(),
SearchAccessRateConstants.PUBLIC_MAX_REMOTE_SNIPPET_ACCESS_3S.getDefaultValue())) { SearchAccessRateConstants.PUBLIC_MAX_REMOTE_SNIPPET_ACCESS_3S.getDefaultValue())) {
snippetFetchStrategy = CacheStrategy.CACHEONLY; snippetFetchStrategy = CacheStrategy.CACHEONLY;
ConcurrentLog.warn("LOCAL_SEARCH", "ACCESS CONTROL: CLIENT FROM " ConcurrentLog.warn("LOCAL_SEARCH", "ACCESS CONTROL: CLIENT FROM "
+ client + client
@ -415,23 +416,23 @@ public class yacysearch {
} }
// general load protection // general load protection
String timePeriodMsg = ""; String timePeriodMsg = "";
if (accInTenMinutes >= sb.getConfigInt(SearchAccessRateConstants.PUBLIC_MAX_ACCESS_10MN.getKey(), if (accInTenMinutes >= sb.getConfigInt(SearchAccessRateConstants.PUBLIC_MAX_ACCESS_10MN.getKey(),
SearchAccessRateConstants.PUBLIC_MAX_ACCESS_10MN.getDefaultValue())) { SearchAccessRateConstants.PUBLIC_MAX_ACCESS_10MN.getDefaultValue())) {
block = true; block = true;
timePeriodMsg = "ten minutes"; timePeriodMsg = "ten minutes";
prop.put("num-results_blockReason", 2); prop.put("num-results_blockReason", 2);
} else if (accInOneMinute >= sb.getConfigInt(SearchAccessRateConstants.PUBLIC_MAX_ACCESS_1MN.getKey(), } else if (accInOneMinute >= sb.getConfigInt(SearchAccessRateConstants.PUBLIC_MAX_ACCESS_1MN.getKey(),
SearchAccessRateConstants.PUBLIC_MAX_ACCESS_1MN.getDefaultValue())) { SearchAccessRateConstants.PUBLIC_MAX_ACCESS_1MN.getDefaultValue())) {
block = true; block = true;
timePeriodMsg = "one minute"; timePeriodMsg = "one minute";
prop.put("num-results_blockReason", 3); prop.put("num-results_blockReason", 3);
} else if (accInThreeSeconds >= sb.getConfigInt(SearchAccessRateConstants.PUBLIC_MAX_ACCESS_3S.getKey(), } else if (accInThreeSeconds >= sb.getConfigInt(SearchAccessRateConstants.PUBLIC_MAX_ACCESS_3S.getKey(),
SearchAccessRateConstants.PUBLIC_MAX_ACCESS_3S.getDefaultValue())) { SearchAccessRateConstants.PUBLIC_MAX_ACCESS_3S.getDefaultValue())) {
block = true; block = true;
timePeriodMsg = "three seconds"; timePeriodMsg = "three seconds";
prop.put("num-results_blockReason", 4); prop.put("num-results_blockReason", 4);
} }
if(block) { if(block) {
ConcurrentLog.warn("LOCAL_SEARCH", "ACCESS CONTROL: CLIENT FROM " ConcurrentLog.warn("LOCAL_SEARCH", "ACCESS CONTROL: CLIENT FROM "
+ client + client
+ ": " + ": "
@ -442,21 +443,21 @@ public class yacysearch {
+ accInTenMinutes + accInTenMinutes
+ "/600s, " + "/600s, "
+ " requests, disallowed search"); + " requests, disallowed search");
if (!"html".equals(EXT)) { if (!"html".equals(EXT)) {
/* /*
* API request : return the relevant HTTP status (429 - Too Many Requests - see * API request : return the relevant HTTP status (429 - Too Many Requests - see
* https://tools.ietf.org/html/rfc6585#section-4) * https://tools.ietf.org/html/rfc6585#section-4)
*/ */
throw new TemplateProcessingException( throw new TemplateProcessingException(
"You have reached the maximum allowed number of accesses to this search service within " "You have reached the maximum allowed number of accesses to this search service within "
+ timePeriodMsg + ". Please try again later or log in as administrator or as a user with extended search right.", + timePeriodMsg + ". Please try again later or log in as administrator or as a user with extended search right.",
429); 429);
} }
} }
} }
if (block) { if (block) {
prop.put("num-results", 5); prop.put("num-results", 5);
} else { } else {
String urlmask = (post == null) ? ".*" : post.get("urlmaskfilter", ".*"); // the expression must be a subset of the java Match syntax described in http://lucene.apache.org/core/4_4_0/core/org/apache/lucene/util/automaton/RegExp.html String urlmask = (post == null) ? ".*" : post.get("urlmaskfilter", ".*"); // the expression must be a subset of the java Match syntax described in http://lucene.apache.org/core/4_4_0/core/org/apache/lucene/util/automaton/RegExp.html
String tld = null; String tld = null;
@ -475,7 +476,7 @@ public class yacysearch {
// read collection // read collection
modifier.collection = post.get("collection", modifier.collection); // post arguments may overrule parsed collection values modifier.collection = post.get("collection", modifier.collection); // post arguments may overrule parsed collection values
int stp = querystring.indexOf('*'); int stp = querystring.indexOf('*');
if (stp >= 0) { if (stp >= 0) {
// if the star appears as a single entry, use the catchallstring // if the star appears as a single entry, use the catchallstring
@ -554,7 +555,7 @@ public class yacysearch {
if (mt != null) { if (mt != null) {
metatags.add(mt); metatags.add(mt);
} else { } else {
} }
} }
} }
@ -587,13 +588,13 @@ public class yacysearch {
querystring = querystring.replace("/heuristic", ""); querystring = querystring.replace("/heuristic", "");
modifier.add("/heuristic"); modifier.add("/heuristic");
} }
final String tldModifierPrefix = "tld:"; final String tldModifierPrefix = "tld:";
final int tldp = querystring.indexOf(tldModifierPrefix, 0); final int tldp = querystring.indexOf(tldModifierPrefix, 0);
if (tldp >= 0) { if (tldp >= 0) {
int ftb = querystring.indexOf(' ', tldp); int ftb = querystring.indexOf(' ', tldp);
if (ftb == -1) { if (ftb == -1) {
ftb = querystring.length(); ftb = querystring.length();
} }
tld = querystring.substring(tldp + tldModifierPrefix.length(), ftb); tld = querystring.substring(tldp + tldModifierPrefix.length(), ftb);
querystring = querystring.replace(tldModifierPrefix + tld, ""); querystring = querystring.replace(tldModifierPrefix + tld, "");
@ -602,20 +603,20 @@ public class yacysearch {
tld = tld.substring(1); tld = tld.substring(1);
} }
if (tld.length() == 0) { if (tld.length() == 0) {
tld = null; tld = null;
} else { } else {
try { try {
/* Convert to the same lower case ASCII Compatible Encoding that is used in normalized URLs */ /* Convert to the same lower case ASCII Compatible Encoding that is used in normalized URLs */
tld = IDN.toASCII(tld, 0); tld = IDN.toASCII(tld, 0);
} catch(final IllegalArgumentException e){ } catch(final IllegalArgumentException e){
ConcurrentLog.warn("LOCAL_SEARCH", "Failed to convert tld modifier value " + tld + "to ASCII Compatible Encoding (ACE)", e); ConcurrentLog.warn("LOCAL_SEARCH", "Failed to convert tld modifier value " + tld + "to ASCII Compatible Encoding (ACE)", e);
} }
/* Domain name in an URL is case insensitive : convert now modifier to lower case for further processing over normalized URLs */ /* Domain name in an URL is case insensitive : convert now modifier to lower case for further processing over normalized URLs */
tld = tld.toLowerCase(Locale.ROOT); tld = tld.toLowerCase(Locale.ROOT);
} }
} }
if (urlmask == null || urlmask.isEmpty()) urlmask = ".*"; //if no urlmask was given if (urlmask == null || urlmask.isEmpty()) urlmask = ".*"; //if no urlmask was given
// read the language from the language-restrict option 'lr' // read the language from the language-restrict option 'lr'
@ -644,12 +645,12 @@ public class yacysearch {
// filter out stopwords // filter out stopwords
final SortedSet<String> filtered = SetTools.joinConstructiveByTest(qg.getIncludeWords(), Switchboard.stopwords); //find matching stopwords final SortedSet<String> filtered = SetTools.joinConstructiveByTest(qg.getIncludeWords(), Switchboard.stopwords); //find matching stopwords
qg.removeIncludeWords(filtered); qg.removeIncludeWords(filtered);
// if a minus-button was hit, remove a special reference first // if a minus-button was hit, remove a special reference first
if ( post != null && post.containsKey("deleteref") ) { if ( post != null && post.containsKey("deleteref") ) {
try { try {
if ( !sb.verifyAuthentication(header) ) { if ( !sb.verifyAuthentication(header) ) {
prop.authenticationRequired(); prop.authenticationRequired();
return prop; return prop;
} }
@ -680,7 +681,7 @@ public class yacysearch {
// if a plus-button was hit, create new voting message // if a plus-button was hit, create new voting message
if ( post != null && post.containsKey("recommendref") ) { if ( post != null && post.containsKey("recommendref") ) {
if ( !sb.verifyAuthentication(header) ) { if ( !sb.verifyAuthentication(header) ) {
prop.authenticationRequired(); prop.authenticationRequired();
return prop; return prop;
} }
final String recommendHash = post.get("recommendref", ""); // urlhash final String recommendHash = post.get("recommendref", ""); // urlhash
@ -783,10 +784,10 @@ public class yacysearch {
sb.getConfigSet("search.navigation")); sb.getConfigSet("search.navigation"));
theQuery.setStrictContentDom(strictContentDom); theQuery.setStrictContentDom(strictContentDom);
theQuery.setMaxSuggestions(meanMax); theQuery.setMaxSuggestions(meanMax);
theQuery.setStandardFacetsMaxCount(sb.getConfigInt(SwitchboardConstants.SEARCH_NAVIGATION_MAXCOUNT, theQuery.setStandardFacetsMaxCount(sb.getConfigInt(SwitchboardConstants.SEARCH_NAVIGATION_MAXCOUNT,
QueryParams.FACETS_STANDARD_MAXCOUNT_DEFAULT)); QueryParams.FACETS_STANDARD_MAXCOUNT_DEFAULT));
theQuery.setDateFacetMaxCount(sb.getConfigInt(SwitchboardConstants.SEARCH_NAVIGATION_DATES_MAXCOUNT, theQuery.setDateFacetMaxCount(sb.getConfigInt(SwitchboardConstants.SEARCH_NAVIGATION_DATES_MAXCOUNT,
QueryParams.FACETS_DATE_MAXCOUNT_DEFAULT)); QueryParams.FACETS_DATE_MAXCOUNT_DEFAULT));
EventTracker.delete(EventTracker.EClass.SEARCH); EventTracker.delete(EventTracker.EClass.SEARCH);
EventTracker.update(EventTracker.EClass.SEARCH, new ProfilingGraph.EventSearch( EventTracker.update(EventTracker.EClass.SEARCH, new ProfilingGraph.EventSearch(
theQuery.id(true), theQuery.id(true),
@ -837,9 +838,9 @@ public class yacysearch {
sb.getConfigLong( sb.getConfigLong(
SwitchboardConstants.REMOTESEARCH_MAXTIME_USER, SwitchboardConstants.REMOTESEARCH_MAXTIME_USER,
sb.getConfigLong(SwitchboardConstants.REMOTESEARCH_MAXTIME_DEFAULT, 3000))); sb.getConfigLong(SwitchboardConstants.REMOTESEARCH_MAXTIME_DEFAULT, 3000)));
if(post.getBoolean("resortCachedResults") && cachedEvent == theSearch) { if(post.getBoolean("resortCachedResults") && cachedEvent == theSearch) {
theSearch.resortCachedResults(); theSearch.resortCachedResults();
} }
if ( startRecord == 0 && extendedSearchRights && !stealthmode ) { if ( startRecord == 0 && extendedSearchRights && !stealthmode ) {
@ -888,9 +889,9 @@ public class yacysearch {
try { try {
suggestion = meanIt.next().toString(); suggestion = meanIt.next().toString();
prop.put("didYouMean_suggestions_" + meanCount + "_word", suggestion); prop.put("didYouMean_suggestions_" + meanCount + "_word", suggestion);
prop.put("didYouMean_suggestions_" + meanCount + "_url", prop.put("didYouMean_suggestions_" + meanCount + "_url",
QueryParams.navUrlWithNewQueryString(RequestHeader.FileType.HTML, 0, theQuery, QueryParams.navUrlWithNewQueryString(RequestHeader.FileType.HTML, 0, theQuery,
suggestion, authenticatedUserName != null)); suggestion, authenticatedUserName != null));
prop.put("didYouMean_suggestions_" + meanCount + "_sep", "|"); prop.put("didYouMean_suggestions_" + meanCount + "_sep", "|");
meanCount++; meanCount++;
} catch (final ConcurrentModificationException e) { } catch (final ConcurrentModificationException e) {
@ -926,7 +927,7 @@ public class yacysearch {
prop.put("geoinfo_loc", i); prop.put("geoinfo_loc", i);
prop.put("geoinfo", "1"); prop.put("geoinfo", "1");
} }
// update the search tracker // update the search tracker
try { try {
synchronized ( trackerHandles ) { synchronized ( trackerHandles ) {
@ -957,17 +958,17 @@ public class yacysearch {
prop.put("num-results_globalresults_remoteResourceSize", Formatter.number(theSearch.remote_rwi_stored.get() + theSearch.remote_solr_stored.get(), true)); prop.put("num-results_globalresults_remoteResourceSize", Formatter.number(theSearch.remote_rwi_stored.get() + theSearch.remote_solr_stored.get(), true));
prop.put("num-results_globalresults_remoteIndexCount", Formatter.number(theSearch.remote_rwi_available.get() + theSearch.remote_solr_available.get(), true)); prop.put("num-results_globalresults_remoteIndexCount", Formatter.number(theSearch.remote_rwi_available.get() + theSearch.remote_solr_available.get(), true));
prop.put("num-results_globalresults_remotePeerCount", Formatter.number(theSearch.remote_rwi_peerCount.get() + theSearch.remote_solr_peerCount.get(), true)); prop.put("num-results_globalresults_remotePeerCount", Formatter.number(theSearch.remote_rwi_peerCount.get() + theSearch.remote_solr_peerCount.get(), true));
prop.put("jsResort", jsResort); prop.put("jsResort", jsResort);
prop.put("num-results_jsResort", jsResort); prop.put("num-results_jsResort", jsResort);
/* In p2p mode only and if JavaScript resorting is not enabled, add a link allowing user to resort already drained results, /* In p2p mode only and if JavaScript resorting is not enabled, add a link allowing user to resort already drained results,
* eventually including fetched results with higher ranks from the Solr and RWI stacks */ * eventually including fetched results with higher ranks from the Solr and RWI stacks */
prop.put("resortEnabled", !jsResort && global && !stealthmode && theSearch.resortCacheAllowed.availablePermits() > 0 ? 1 : 0); prop.put("resortEnabled", !jsResort && global && !stealthmode && theSearch.resortCacheAllowed.availablePermits() > 0 ? 1 : 0);
prop.put("resortEnabled_url", prop.put("resortEnabled_url",
QueryParams.navurlBase(RequestHeader.FileType.HTML, theQuery, null, true, authenticatedUserName != null) QueryParams.navurlBase(RequestHeader.FileType.HTML, theQuery, null, true, authenticatedUserName != null)
.append("&startRecord=").append(startRecord).append("&resortCachedResults=true") .append("&startRecord=").append(startRecord).append("&resortCachedResults=true")
.toString()); .toString());
// generate the search result lines; the content will be produced by another servlet // generate the search result lines; the content will be produced by another servlet
for ( int i = 0; i < theQuery.itemsPerPage(); i++ ) { for ( int i = 0; i < theQuery.itemsPerPage(); i++ ) {
@ -1005,36 +1006,36 @@ public class yacysearch {
prop.put("depth", "0"); prop.put("depth", "0");
prop.put("localQuery", theSearch.query.isLocal() ? "1" : "0"); prop.put("localQuery", theSearch.query.isLocal() ? "1" : "0");
prop.put("jsResort_localQuery", theSearch.query.isLocal() ? "1" : "0"); prop.put("jsResort_localQuery", theSearch.query.isLocal() ? "1" : "0");
final boolean showLogin = sb.getConfigBool(SwitchboardConstants.SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN, final boolean showLogin = sb.getConfigBool(SwitchboardConstants.SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN,
SwitchboardConstants.SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN_DEFAULT); SwitchboardConstants.SEARCH_PUBLIC_TOP_NAV_BAR_LOGIN_DEFAULT);
if(showLogin) { if(showLogin) {
if(authenticatedUserName != null) { if(authenticatedUserName != null) {
/* Show the name of the authenticated user */ /* Show the name of the authenticated user */
prop.put("showLogin", 1); prop.put("showLogin", 1);
prop.put("showLogin_userName", authenticatedUserName); prop.put("showLogin_userName", authenticatedUserName);
} else { } else {
/* Show a login link */ /* Show a login link */
prop.put("showLogin", 2); prop.put("showLogin", 2);
prop.put("showLogin_loginURL", prop.put("showLogin_loginURL",
QueryParams.navurlBase(RequestHeader.FileType.HTML, theQuery, null, true, true).toString()); QueryParams.navurlBase(RequestHeader.FileType.HTML, theQuery, null, true, true).toString());
} }
} else { } else {
prop.put("showLogin", 0); prop.put("showLogin", 0);
} }
} }
prop.put("focus", focus ? 1 : 0); // focus search field prop.put("focus", focus ? 1 : 0); // focus search field
prop.put("searchagain", global ? "1" : "0"); prop.put("searchagain", global ? "1" : "0");
String former = originalquerystring.replaceAll(Segment.catchallString, "*"); String former = originalquerystring.replaceAll(Segment.catchallString, "*"); // hide catchallString in output
prop.putHTML("former", former); prop.putHTML("former", former);
try { try {
prop.put("formerEncoded", URLEncoder.encode(former, StandardCharsets.UTF_8.name())); prop.put("formerEncoded", URLEncoder.encode(former, StandardCharsets.UTF_8.name()));
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
ConcurrentLog.warn("LOCAL_SEARCH", "Unsupported UTF-8 encoding!"); ConcurrentLog.warn("LOCAL_SEARCH", "Unsupported UTF-8 encoding!");
prop.put("formerEncoded", former); prop.put("formerEncoded", former);
} }
prop.put("count", itemsPerPage); prop.put("count", itemsPerPage);
prop.put("offset", startRecord); prop.put("offset", startRecord);
prop.put("resource", global ? "global" : "local"); prop.put("resource", global ? "global" : "local");

@ -64,31 +64,31 @@ public class yacysearchtrailer {
@SuppressWarnings({ }) @SuppressWarnings({ })
public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) { public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) {
if (post == null) { if (post == null) {
throw new TemplateMissingParameterException("The eventID parameter is required"); throw new TemplateMissingParameterException("The eventID parameter is required");
} }
final serverObjects prop = new serverObjects(); final serverObjects prop = new serverObjects();
final Switchboard sb = (Switchboard) env; final Switchboard sb = (Switchboard) env;
final String eventID = post.get("eventID", ""); final String eventID = post.get("eventID", "");
final boolean adminAuthenticated = sb.verifyAuthentication(header); final boolean adminAuthenticated = sb.verifyAuthentication(header);
final UserDB.Entry user = sb.userDB != null ? sb.userDB.getUser(header) : null; final UserDB.Entry user = sb.userDB != null ? sb.userDB.getUser(header) : null;
final boolean authenticated = adminAuthenticated || user != null; final boolean authenticated = adminAuthenticated || user != null;
if (post.containsKey("auth") && !authenticated) { if (post.containsKey("auth") && !authenticated) {
/* /*
* Authenticated search is explicitely requested here * Authenticated search is explicitely requested here
* but no authentication is provided : ask now for authentication. * but no authentication is provided : ask now for authentication.
* Wihout this, after timeout of HTTP Digest authentication nonce, browsers no more send authentication information * Wihout this, after timeout of HTTP Digest authentication nonce, browsers no more send authentication information
* and as this page is not private, protected features would simply be hidden without asking browser again for authentication. * and as this page is not private, protected features would simply be hidden without asking browser again for authentication.
* (see mantis 766 : http://mantis.tokeek.de/view.php?id=766) * * (see mantis 766 : http://mantis.tokeek.de/view.php?id=766) *
*/ */
prop.authenticationRequired(); prop.authenticationRequired();
return prop; return prop;
} }
// find search event // find search event
final SearchEvent theSearch = SearchEventCache.getEvent(eventID); final SearchEvent theSearch = SearchEventCache.getEvent(eventID);
if (theSearch == null) { if (theSearch == null) {
@ -96,14 +96,13 @@ public class yacysearchtrailer {
return prop; return prop;
} }
final RequestHeader.FileType fileType = header.fileType(); final RequestHeader.FileType fileType = header.fileType();
final boolean clustersearch = sb.isRobinsonMode() && sb.getConfig(SwitchboardConstants.CLUSTER_MODE, "").equals(SwitchboardConstants.CLUSTER_MODE_PUBLIC_CLUSTER); final boolean clustersearch = sb.isRobinsonMode() && sb.getConfig(SwitchboardConstants.CLUSTER_MODE, "").equals(SwitchboardConstants.CLUSTER_MODE_PUBLIC_CLUSTER);
final boolean indexReceiveGranted = sb.getConfigBool(SwitchboardConstants.INDEX_RECEIVE_ALLOW_SEARCH, true) || clustersearch; final boolean indexReceiveGranted = sb.getConfigBool(SwitchboardConstants.INDEX_RECEIVE_ALLOW_SEARCH, true) || clustersearch;
boolean p2pmode = sb.peers != null && sb.peers.sizeConnected() > 0 && indexReceiveGranted; boolean p2pmode = sb.peers != null && sb.peers.sizeConnected() > 0 && indexReceiveGranted;
boolean global = post == null || (!post.get("resource-switch", post.get("resource", "global")).equals("local") && p2pmode); boolean global = post == null || (!post.get("resource-switch", post.get("resource", "global")).equals("local") && p2pmode);
boolean stealthmode = p2pmode && !global; boolean stealthmode = p2pmode && !global;
// compose search navigation // compose search navigation
ContentDomain contentdom = theSearch.getQuery().contentdom; ContentDomain contentdom = theSearch.getQuery().contentdom;
prop.put("searchdomswitches", prop.put("searchdomswitches",
@ -112,35 +111,36 @@ public class yacysearchtrailer {
|| sb.getConfigBool("search.video", true) || sb.getConfigBool("search.video", true)
|| sb.getConfigBool("search.image", true) || sb.getConfigBool("search.image", true)
|| sb.getConfigBool("search.app", true) ? 1 : 0); || sb.getConfigBool("search.app", true) ? 1 : 0);
final String originalquerystring = post.get("query", post.get("search", "")).trim(); String originalquerystring = post.get("query", post.get("search", "")).trim();
originalquerystring = originalquerystring.replace('<', ' ').replace('>', ' '); // light xss protection
final String former = originalquerystring.replaceAll(Segment.catchallString, "*"); final String former = originalquerystring.replaceAll(Segment.catchallString, "*");
final CacheStrategy snippetFetchStrategy = CacheStrategy.parse(post.get("verify", sb.getConfig("search.verify", ""))); final CacheStrategy snippetFetchStrategy = CacheStrategy.parse(post.get("verify", sb.getConfig("search.verify", "")));
final String snippetFetchStrategyName = snippetFetchStrategy == null final String snippetFetchStrategyName = snippetFetchStrategy == null
? sb.getConfig("search.verify", CacheStrategy.IFFRESH.toName()) ? sb.getConfig("search.verify", CacheStrategy.IFFRESH.toName())
: snippetFetchStrategy.toName(); : snippetFetchStrategy.toName();
final int startRecord = post.getInt("startRecord", post.getInt("offset", post.getInt("start", 0))); final int startRecord = post.getInt("startRecord", post.getInt("offset", post.getInt("start", 0)));
/* Maximum number of suggestions to display in the first results page */ /* Maximum number of suggestions to display in the first results page */
final int meanMax = post.getInt("meanCount", 0); final int meanMax = post.getInt("meanCount", 0);
prop.put("resource-switches", adminAuthenticated && (stealthmode || global)); prop.put("resource-switches", adminAuthenticated && (stealthmode || global));
prop.put("resource-switches_global", adminAuthenticated && global); prop.put("resource-switches_global", adminAuthenticated && global);
appendSearchFormValues("resource-switches_", post, prop, global, theSearch, former, snippetFetchStrategyName, startRecord, meanMax); appendSearchFormValues("resource-switches_", post, prop, global, theSearch, former, snippetFetchStrategyName, startRecord, meanMax);
/* The search event has been found : we can render ranking switches */ /* The search event has been found : we can render ranking switches */
prop.put("ranking-switches", true); prop.put("ranking-switches", true);
appendSearchFormValues("ranking-switches_", post, prop, global, theSearch, former, snippetFetchStrategyName, startRecord, meanMax); appendSearchFormValues("ranking-switches_", post, prop, global, theSearch, former, snippetFetchStrategyName, startRecord, meanMax);
/* Add information about the current navigators generation (number of updates since their initialization) */ /* Add information about the current navigators generation (number of updates since their initialization) */
prop.put("ranking-switches_nav-generation", theSearch.getNavGeneration()); prop.put("ranking-switches_nav-generation", theSearch.getNavGeneration());
prop.put("ranking-switches_contextRanking", !former.contains(" /date")); prop.put("ranking-switches_contextRanking", !former.contains(" /date"));
prop.put("ranking-switches_contextRanking_formerWithoutDate", former.replace(" /date", "")); prop.put("ranking-switches_contextRanking_formerWithoutDate", former.replace(" /date", ""));
prop.put("ranking-switches_dateRanking", former.contains(" /date")); prop.put("ranking-switches_dateRanking", former.contains(" /date"));
prop.put("ranking-switches_dateRanking_former", former); prop.put("ranking-switches_dateRanking_former", former);
appendSearchFormValues("searchdomswitches_", post, prop, global, theSearch, former, snippetFetchStrategyName, startRecord, meanMax); appendSearchFormValues("searchdomswitches_", post, prop, global, theSearch, former, snippetFetchStrategyName, startRecord, meanMax);
prop.put("searchdomswitches_searchtext", sb.getConfigBool("search.text", true) ? 1 : 0); prop.put("searchdomswitches_searchtext", sb.getConfigBool("search.text", true) ? 1 : 0);
prop.put("searchdomswitches_searchaudio", sb.getConfigBool("search.audio", true) ? 1 : 0); prop.put("searchdomswitches_searchaudio", sb.getConfigBool("search.audio", true) ? 1 : 0);
prop.put("searchdomswitches_searchvideo", sb.getConfigBool("search.video", true) ? 1 : 0); prop.put("searchdomswitches_searchvideo", sb.getConfigBool("search.video", true) ? 1 : 0);
@ -151,7 +151,7 @@ public class yacysearchtrailer {
prop.put("searchdomswitches_searchvideo_check", (contentdom == ContentDomain.VIDEO) ? "1" : "0"); prop.put("searchdomswitches_searchvideo_check", (contentdom == ContentDomain.VIDEO) ? "1" : "0");
prop.put("searchdomswitches_searchimage_check", (contentdom == ContentDomain.IMAGE) ? "1" : "0"); prop.put("searchdomswitches_searchimage_check", (contentdom == ContentDomain.IMAGE) ? "1" : "0");
prop.put("searchdomswitches_searchapp_check", (contentdom == ContentDomain.APP) ? "1" : "0"); prop.put("searchdomswitches_searchapp_check", (contentdom == ContentDomain.APP) ? "1" : "0");
appendSearchFormValues("searchdomswitches_strictContentDomSwitch_", post, prop, global, theSearch, former, snippetFetchStrategyName, startRecord, meanMax); appendSearchFormValues("searchdomswitches_strictContentDomSwitch_", post, prop, global, theSearch, former, snippetFetchStrategyName, startRecord, meanMax);
prop.put("searchdomswitches_strictContentDomSwitch", (contentdom != ContentDomain.TEXT && contentdom != ContentDomain.ALL) ? 1 : 0); prop.put("searchdomswitches_strictContentDomSwitch", (contentdom != ContentDomain.TEXT && contentdom != ContentDomain.ALL) ? 1 : 0);
prop.put("searchdomswitches_strictContentDomSwitch_strictContentDom", theSearch.getQuery().isStrictContentDom() ? 1 : 0); prop.put("searchdomswitches_strictContentDomSwitch_strictContentDom", theSearch.getQuery().isStrictContentDom() ? 1 : 0);
@ -189,8 +189,8 @@ public class yacysearchtrailer {
count = entry.getValue(); count = entry.getValue();
prop.put(fileType, "nav-topics_element_" + i + "_modifier", name); prop.put(fileType, "nav-topics_element_" + i + "_modifier", name);
prop.put(fileType, "nav-topics_element_" + i + "_name", name); prop.put(fileType, "nav-topics_element_" + i + "_name", name);
prop.putUrlEncoded(fileType, "nav-topics_element_" + i + "_url", QueryParams prop.putUrlEncoded(fileType, "nav-topics_element_" + i + "_url", QueryParams
.navurl(fileType, 0, theSearch.query, name, false, authenticated).toString()); .navurl(fileType, 0, theSearch.query, name, false, authenticated).toString());
prop.put("nav-topics_element_" + i + "_count", count); prop.put("nav-topics_element_" + i + "_count", count);
int fontsize = TOPWORDS_MINSIZE + (TOPWORDS_MAXSIZE - TOPWORDS_MINSIZE) * (count - mincount) / (1 + maxcount - mincount); int fontsize = TOPWORDS_MINSIZE + (TOPWORDS_MAXSIZE - TOPWORDS_MINSIZE) * (count - mincount) / (1 + maxcount - mincount);
fontsize = Math.max(TOPWORDS_MINSIZE, fontsize - (name.length() - 5)); fontsize = Math.max(TOPWORDS_MINSIZE, fontsize - (name.length() - 5));
@ -203,7 +203,7 @@ public class yacysearchtrailer {
i--; i--;
prop.put("nav-topics_element_" + i + "_nl", 0); prop.put("nav-topics_element_" + i + "_nl", 0);
} }
// protocol navigators // protocol navigators
if (theSearch.protocolNavigator == null || theSearch.protocolNavigator.isEmpty()) { if (theSearch.protocolNavigator == null || theSearch.protocolNavigator.isEmpty()) {
prop.put("nav-protocols", 0); prop.put("nav-protocols", 0);
@ -233,15 +233,15 @@ public class yacysearchtrailer {
prop.put("nav-protocols_element_" + i + "_on", 0); prop.put("nav-protocols_element_" + i + "_on", 0);
prop.put("nav-protocols_element_" + i + "_onclick", 0); prop.put("nav-protocols_element_" + i + "_onclick", 0);
prop.put(fileType, "nav-protocols_element_" + i + "_modifier", nav); prop.put(fileType, "nav-protocols_element_" + i + "_modifier", nav);
url = QueryParams.navurl(fileType, 0, theSearch.query, rawNav, false, authenticated).toString(); url = QueryParams.navurl(fileType, 0, theSearch.query, rawNav, false, authenticated).toString();
} else { } else {
neg++; neg++;
prop.put("nav-protocols_element_" + i + "_on", 1); prop.put("nav-protocols_element_" + i + "_on", 1);
prop.put("nav-protocols_element_" + i + "_onclick", 1); prop.put("nav-protocols_element_" + i + "_onclick", 1);
prop.put(fileType, "nav-protocols_element_" + i + "_modifier", "-" + nav); prop.put(fileType, "nav-protocols_element_" + i + "_modifier", "-" + nav);
url = QueryParams url = QueryParams
.navUrlWithSingleModifierRemoved(fileType, 0, theSearch.query, rawNav, authenticated) .navUrlWithSingleModifierRemoved(fileType, 0, theSearch.query, rawNav, authenticated)
.toString(); .toString();
} }
prop.put(fileType, "nav-protocols_element_" + i + "_name", name); prop.put(fileType, "nav-protocols_element_" + i + "_name", name);
prop.put("nav-protocols_element_" + i + "_onclick_url", url); prop.put("nav-protocols_element_" + i + "_onclick_url", url);
@ -278,7 +278,7 @@ public class yacysearchtrailer {
if (name.length() < 10) continue; if (name.length() < 10) continue;
count = theSearch.dateNavigator.get(name); count = theSearch.dateNavigator.get(name);
if(count == 0) { if(count == 0) {
continue; continue;
} }
String shortname = name.substring(0, 10); String shortname = name.substring(0, 10);
long d = Instant.parse(name).toEpochMilli(); long d = Instant.parse(name).toEpochMilli();
@ -301,7 +301,7 @@ public class yacysearchtrailer {
pos++; pos++;
prop.put("nav-dates_element_" + i + "_on", 1); prop.put("nav-dates_element_" + i + "_on", 1);
} else { } else {
neg++; neg++;
prop.put("nav-dates_element_" + i + "_on", 0); prop.put("nav-dates_element_" + i + "_on", 0);
} }
prop.put(fileType, "nav-dates_element_" + i + "_name", shortname); prop.put(fileType, "nav-dates_element_" + i + "_name", shortname);
@ -347,7 +347,7 @@ public class yacysearchtrailer {
navUrl = QueryParams.navUrlWithSingleModifierRemoved(fileType, 0, theSearch.query, rawNav, authenticated); navUrl = QueryParams.navUrlWithSingleModifierRemoved(fileType, 0, theSearch.query, rawNav, authenticated);
} }
prop.put(fileType, "nav-vocabulary_" + navvoccount + "_element_" + i + "_name", name); prop.put(fileType, "nav-vocabulary_" + navvoccount + "_element_" + i + "_name", name);
prop.putUrlEncoded(fileType, "nav-vocabulary_" + navvoccount + "_element_" + i + "_url", navUrl); prop.putUrlEncoded(fileType, "nav-vocabulary_" + navvoccount + "_element_" + i + "_url", navUrl);
prop.put(fileType, "nav-vocabulary_" + navvoccount + "_element_" + i + "_id", "vocabulary_" + navname + "_" + i); prop.put(fileType, "nav-vocabulary_" + navvoccount + "_element_" + i + "_id", "vocabulary_" + navname + "_" + i);
prop.put("nav-vocabulary_" + navvoccount + "_element_" + i + "_count", count); prop.put("nav-vocabulary_" + navvoccount + "_element_" + i + "_count", count);
prop.put("nav-vocabulary_" + navvoccount + "_element_" + i + "_nl", 1); prop.put("nav-vocabulary_" + navvoccount + "_element_" + i + "_nl", 1);
@ -376,35 +376,35 @@ public class yacysearchtrailer {
prop.put("navs_" + ni + "_displayname", navi.getDisplayName()); prop.put("navs_" + ni + "_displayname", navi.getDisplayName());
prop.put("navs_" + ni + "_name", naviname); prop.put("navs_" + ni + "_name", naviname);
prop.put("navs_" + ni + "_count", navi.size()); prop.put("navs_" + ni + "_count", navi.size());
final int navSort; final int navSort;
if(navi.getSort() == null) { if(navi.getSort() == null) {
navSort = 0; navSort = 0;
} else { } else {
if(navi.getSort().getSortType() == NavigatorSortType.COUNT) { if(navi.getSort().getSortType() == NavigatorSortType.COUNT) {
if(navi.getSort().getSortDir() == NavigatorSortDirection.DESC) { if(navi.getSort().getSortDir() == NavigatorSortDirection.DESC) {
navSort = 0; navSort = 0;
} else { } else {
navSort = 1; navSort = 1;
} }
} else { } else {
if(navi.getSort().getSortDir() == NavigatorSortDirection.DESC) { if(navi.getSort().getSortDir() == NavigatorSortDirection.DESC) {
navSort = 2; navSort = 2;
} else { } else {
navSort = 3; navSort = 3;
} }
} }
} }
prop.put("navs_" + ni + "_navSort", navSort); prop.put("navs_" + ni + "_navSort", navSort);
navigatorIterator = navi.navigatorKeys(); navigatorIterator = navi.navigatorKeys();
int i = 0, pos = 0, neg = 0; int i = 0, pos = 0, neg = 0;
String nav, rawNav; String nav, rawNav;
while (i < theSearch.getQuery().getStandardFacetsMaxCount() && navigatorIterator.hasNext()) { while (i < theSearch.getQuery().getStandardFacetsMaxCount() && navigatorIterator.hasNext()) {
name = navigatorIterator.next(); name = navigatorIterator.next();
count = navi.get(name); count = navi.get(name);
if (count == 0) { if (count == 0) {
/* This entry has a zero count, but the next may be positive */ /* This entry has a zero count, but the next may be positive */
continue; continue;
} }
@ -420,24 +420,24 @@ public class yacysearchtrailer {
pos++; pos++;
prop.put("navs_" + ni + "_element_" + i + "_on", 1); prop.put("navs_" + ni + "_element_" + i + "_on", 1);
prop.put(fileType, "navs_" + ni + "_element_" + i + "_modifier", nav); prop.put(fileType, "navs_" + ni + "_element_" + i + "_modifier", nav);
navUrl = QueryParams.navurl(fileType, 0, theSearch.query, rawNav, false, authenticated).toString(); navUrl = QueryParams.navurl(fileType, 0, theSearch.query, rawNav, false, authenticated).toString();
} else { } else {
neg++; neg++;
prop.put("navs_" + ni + "_element_" + i + "_on", 0); prop.put("navs_" + ni + "_element_" + i + "_on", 0);
prop.put(fileType, "navs_" + ni + "_element_" + i + "_modifier", "-" + nav); prop.put(fileType, "navs_" + ni + "_element_" + i + "_modifier", "-" + nav);
navUrl = QueryParams.navUrlWithSingleModifierRemoved(fileType, 0, theSearch.query, rawNav, navUrl = QueryParams.navUrlWithSingleModifierRemoved(fileType, 0, theSearch.query, rawNav,
authenticated); authenticated);
} }
prop.put(fileType, "navs_" + ni + "_element_" + i + "_name", navi.getElementDisplayName(name)); prop.put(fileType, "navs_" + ni + "_element_" + i + "_name", navi.getElementDisplayName(name));
prop.putUrlEncoded(fileType, "navs_" + ni + "_element_" + i + "_url", navUrl); prop.putUrlEncoded(fileType, "navs_" + ni + "_element_" + i + "_url", navUrl);
prop.put(fileType, "navs_" + ni + "_element_" + i + "_id", naviname + "_" + i); prop.put(fileType, "navs_" + ni + "_element_" + i + "_id", naviname + "_" + i);
prop.put("navs_" + ni + "_element_" + i + "_count", count); prop.put("navs_" + ni + "_element_" + i + "_count", count);
prop.put("navs_" + ni + "_element_" + i + "_nl", 1); prop.put("navs_" + ni + "_element_" + i + "_nl", 1);
i++; i++;
} }
if(i == 0) { if(i == 0) {
/* The navigator has only entries with value==0 : this is equivalent to empty navigator */ /* The navigator has only entries with value==0 : this is equivalent to empty navigator */
continue; continue;
} }
prop.put("navs_" + ni + "_element", i); prop.put("navs_" + ni + "_element", i);
prop.put("navs_" + ni + "_count", i); prop.put("navs_" + ni + "_count", i);
@ -491,10 +491,10 @@ public class yacysearchtrailer {
* @param startRecord the zero based index of the first record to return * @param startRecord the zero based index of the first record to return
* @param meanMax the maximum number of suggestions ("Did you mean") to propose * @param meanMax the maximum number of suggestions ("Did you mean") to propose
*/ */
private static void appendSearchFormValues(final String templatePrefix, final serverObjects post, final serverObjects prop, private static void appendSearchFormValues(final String templatePrefix, final serverObjects post, final serverObjects prop,
boolean global, final SearchEvent theSearch, final String former, final String snippetFetchStrategyName, boolean global, final SearchEvent theSearch, final String former, final String snippetFetchStrategyName,
final int startRecord, final int meanMax) { final int startRecord, final int meanMax) {
prop.putHTML(templatePrefix + "former", former); prop.putHTML(templatePrefix + "former", former);
prop.put(templatePrefix + "authSearch", post.containsKey("auth")); prop.put(templatePrefix + "authSearch", post.containsKey("auth"));
prop.put(templatePrefix + "contentdom", post.get("contentdom", "text")); prop.put(templatePrefix + "contentdom", post.get("contentdom", "text"));
prop.put(templatePrefix + "strictContentDom", String.valueOf(theSearch.getQuery().isStrictContentDom())); prop.put(templatePrefix + "strictContentDom", String.valueOf(theSearch.getQuery().isStrictContentDom()));
@ -507,7 +507,7 @@ public class yacysearchtrailer {
prop.put(templatePrefix + "depth", "0"); prop.put(templatePrefix + "depth", "0");
prop.put(templatePrefix + "constraint", (theSearch.getQuery().constraint == null) ? "" : theSearch.getQuery().constraint.exportB64()); prop.put(templatePrefix + "constraint", (theSearch.getQuery().constraint == null) ? "" : theSearch.getQuery().constraint.exportB64());
prop.put(templatePrefix + "meanCount", meanMax); prop.put(templatePrefix + "meanCount", meanMax);
} }
} }
//http://localhost:8090/yacysearch.html?query=java+&amp;maximumRecords=10&amp;resource=local&amp;verify=cacheonly&amp;nav=hosts,authors,namespace,topics,filetype,protocol&amp;urlmaskfilter=ftp://.*&amp;prefermaskfilter=&amp;constraint=&amp;contentdom=text&amp;former=java+%2Fftp&amp;startRecord=0 //http://localhost:8090/yacysearch.html?query=java+&amp;maximumRecords=10&amp;resource=local&amp;verify=cacheonly&amp;nav=hosts,authors,namespace,topics,filetype,protocol&amp;urlmaskfilter=ftp://.*&amp;prefermaskfilter=&amp;constraint=&amp;contentdom=text&amp;former=java+%2Fftp&amp;startRecord=0

Loading…
Cancel
Save