package uc.protocols.hub;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import logger.LoggerFactory;
import org.apache.log4j.Logger;
import uc.IUser;
import uc.crypto.HashValue;
import uc.files.filelist.OwnFileList.SearchParameter;
import uc.files.search.FileSearch;
import uc.files.search.SearchType;
import uc.protocols.ConnectionProtocol;
import uc.protocols.DCProtocol;
import uc.user.User;
public class Search extends AbstractNMDCHubProtocolCommand {
private static Logger logger = LoggerFactory.make();
private static final Pattern //splits search terms
dollarsplit = Pattern.compile(Pattern.quote("$"));
/**
* search for a TTH
*/
private final Pattern tthSearch;
/**
* usual search
*/
private final Pattern normalSearch;
public Search() {
String filesearchending = "(?:([1-8])\\?(.*))"; //capture for the search term
String tthending = "(?:(9)\\?TTH:("+TTH+"))"; //capture for TTH
String activewho = "(?:"+IPv4+":"+PORT+")";
String passivewho = "(?:Hub:"+NMDCNICK+")";
String who = "(?:"+activewho+"|"+passivewho+")";
tthSearch = Pattern.compile(prefix+" ("+who+") "+"([TF])\\?([TF])\\?("+FILESIZE+")\\?"+tthending);
normalSearch = Pattern.compile(prefix+" ("+who+") "+"([TF])\\?([TF])\\?("+FILESIZE+")\\?"+filesearchending);
}
/**
* $Search 17.12.85.3:3746 F?T?0?9?TTH:TO32WPD6AQE7VA7654HEAM5GKFQGIL7F2BEKFNA active
* $Search Hub:SomeNick F?T?0?9?TTH:TO32WPD6AQE7VA7654HEAM5GKFQGIL7F2BEKFNA passive
* <search string> ::= <size restricted>?<is max size>?<size>?<data type>?<search pattern>
*
* called from command received when a search command was received from the hub
*
* @param command - the search command
*/
@Override
public void handle(Hub hub,String command) throws IOException {
if (hub.getFavHub().isChatOnly()) {
return;
}
logger.debug("searchreceived("+command+")");
Matcher m = null;
boolean passive;
//Set<FilelistFile> found;
if ((m = normalSearch.matcher(command)).matches()) {
boolean sizerestricted = m.group(2).equals("T");
boolean maxsize = m.group(3).equals("T");
long size = Long.parseLong(m.group(4));
SearchType searchType = SearchType.getNMDC(Integer.parseInt(m.group(5)));
String[] searchkeys = DCProtocol.reverseReplaces(dollarsplit.split(m.group(6)));
HashSet<String> keys = new HashSet<String>(Arrays.<String>asList(searchkeys));
keys.remove("");
keys.remove(".");
passive = m.group(1).startsWith("Hub:");
User searcherUsr = null;
InetSocketAddress searcherIp = null;
if (passive) {
searcherUsr = hub.getUserByNick(m.group(1).substring(4));
} else {
searcherIp = ConnectionProtocol.inetFromString(m.group(1), 412);
}
long minSize = sizerestricted && !maxsize ? size : 0 ;// (maxsize? 0 : size ) : 0;
long maxSize = sizerestricted && maxsize ? size : Long.MAX_VALUE; // (maxsize? size : Long.MAX_VALUE) : Long.MAX_VALUE;
SearchParameter sp = new SearchParameter(keys,Collections.<String>emptySet(),minSize,
maxSize,-1,searchType.getEndings(),searchType.equals(SearchType.FOLDER));
hub.searchReceived(sp, passive, searcherUsr,searcherIp,null,null);
} else if ((m = tthSearch.matcher(command)).matches()) {
HashValue tth = HashValue.createHash(m.group(6));
passive = m.group(1).startsWith("Hub:");
User searcherUsr = null;
InetSocketAddress searcherIp = null;
if (passive) {
searcherUsr = hub.getUserByNick(m.group(1).substring(4));
} else {
searcherIp = ConnectionProtocol.inetFromString(m.group(1), 412);
}
hub.searchReceived(tth, passive, searcherUsr,searcherIp,null,null);
} else {
logger.debug("illegal search received: "+command);
return;
}
}
/* public static void main(String[] args) {
String search = "$Search 89.48.12.197:3333 F?T?0?9?TTH:4CLZLU7TCB6C4YTHN7JNOIA7F7VQVJV5762AYJA";
//String search2 = "$Search 89.48.12.197:3333 F?T?0?5?norm$als$earch";
Search sr = new Search(null);
Matcher m = sr.tthSearch.matcher(search);
boolean matches = m.matches();
System.out.println(matches);
if (matches) {
for (int i=0 ; i <= 6;i++)
System.out.println(m.group(i));
}
} */
/** ex: nmdcsearch from dcpp wiki
* $Search 64.78.55.32:412 T?T?500000?1?Gentoo$2005 active
* $Search Hub:SomeNick T?T?500000?1?Gentoo$2005 passive
* $Search 17.12.85.3:3746 F?T?0?9?TTH:TO32WPD6AQE7VA7654HEAM5GKFQGIL7F2BEKFNA active
* $Search Hub:SomeNick F?T?0?9?TTH:TO32WPD6AQE7VA7654HEAM5GKFQGIL7F2BEKFNA passive
*
* $Search <ip>:<port> <searchstring> active
* $Search Hub:<requestornick> <searchstring> passive <requestornick> is the Nick of the Passive User doing the Search.
*
* <searchstring> ::= <sizerestricted>?<ismaxsize>?<size>?<datatype>?<searchpattern>
*
*
* Search sends a search to the hub..
* registering listener is done somewhere else! @see Search
*
* @param search - the search command pattern
*/
public static void sendSearch(Hub hub,FileSearch search) {
IUser self = hub.getSelf();
String command="$Search "+
(self.isUDPActive() ?
self.getIp().getHostAddress()
+":"+self.getUdpPort()+" ":
"Hub:%[myNI] ");
if (search.getSize() == -1) {
command += "F?F?0" ;
} else {
command += "T?"+search.getComparisonEnum().getNMDCC()+"?"+search.getSize();
}
command += "?"+search.getSearchType().getNMDC()+"?";
String[] words = DCProtocol.doReplaces(search.getSearchString()).split(" ");
StringBuilder searchstring= new StringBuilder();
for (String word: words) { //remove all strings starting with -
if (!word.startsWith("-")) {
searchstring.append(word).append('$');
}
}
//if the search is too short we don't send it...
if (searchstring.length() > 3 ) {
searchstring.deleteCharAt(searchstring.length()-1);
//searchstring = searchstring.substring(0, searchstring.length()-1); //cut away the last $ produced in loop above
//finish the command by adding the produced search pattern
command += (search.getSearchType() == SearchType.TTH ? "TTH:":"");
command += searchstring+"|";
hub.sendRaw(command); //command is finished...so send it..
logger.debug("sending search: "+command);
}
}
}