import java.io.* ; import java.net.* ; import java.util.* ; /** DesktopProxy - a very simple proxy to allow non localhost requestors to connect to the Google Desktop proxy. Uses: - allow others to search/view your files, emails, chats, web history - install on a file server and allow searching of files Dangers: - Google Desktop was explicitly implemented to only allow access from localhost requestors. Do you really want random others looking at these items on your PC? - Maybe Google (the real web Google) will crawl your proxy... Futures: - Part of a distributed search system which searches all PC's on a network for content - Limit types of searches (document base, result type, file type, ...), allow search but block retrieval, ... Author: Kent Fitch, http://www.projectcomputing.com Please read http://www.projectcomputing.com/resources/desktopProxy Version 0.1, 23 Oct 2004 To build: javac DesktopProxy.java create manifest info in classInfo.txt: Main-Class: DesktopProxy (then newline) jar -cmvf classInfo.txt DesktopProxy.jar *.class To run: java -jar DesktopProxy.jar or dont bother with the jar and run: java DesktopProxy **/ class DesktopProxy { public static final String VERSION = "0.1" ; public static final String GOOGLE_DESKTOP_HOST = "localhost" ; public static final int GOOGLE_DESKTOP_PORT = 4664 ; public static final int PROXY_PORT = 8088 ; public static final String PREVOD = "S%3A%5CDokumenty%5CMarketing%5CJAN%C4%8CA%5CKonkurence+prodan%C3%A9+p%C5%99%C3%ADstroje%2Exls"; public static final String KODOVANI1 = "UTF-8" ; public static final String KODOVANI2 = "ISO-8859-1" ; public static final String KODOVANI3 = "US-ASCII" ; static int port = PROXY_PORT ; static String[] allowIPAddresses = null ; static boolean[] allowIPAddressExactMatch = null ; static Logger log ; private static final String DEFAULT_PROPFILE_NAME = "proxyParms.txt" ; public static final int timeout = 5000 ; public static void main(String[] parms) throws Exception { loadParms(parms) ; //System.out.println("UTF-8"+URLDecoder.decode(PREVOD,KODOVANI1)) ; //System.out.println("ISO-8859-1"+URLDecoder.decode(PREVOD,KODOVANI2)) ; //System.out.println("US-ASCII"+URLDecoder.decode(PREVOD,KODOVANI3)) ; System.out.println("Desktop Proxy Version " + VERSION + " initialised\n\n" + "Your local files, email, chat logs and web history are now searchable and\n" + "viewable by others.\n\n" + "CRTL-C to stop") ; ServerSocket ss = new ServerSocket(port, 100) ; while (true) new Thread(new ConnectionProcessor(ss.accept())).start() ; } /** parms are: port (default to PROXY_PORT) allowIPAddresses (defaults to just 127.0.0.1. Comma separated list with wildcard trailing characters,eg: 10.1.1.*,10.1.2.12,10.1.2.1*,10.8* would permit 10.1.1.200, 10.1.2.12, 10.1.2.18, 10.1.2.108, 10.8.4.123 etc 127.0.0.1 is always allowed) logFile (no default) **/ private static void loadParms(String[] parms) throws Exception { String propFileName = (parms.length > 0) ? parms[0] : DEFAULT_PROPFILE_NAME ; Properties p = new Properties() ; try { p.load(new FileInputStream(propFileName)) ; } catch (Exception e) { System.err.println("Error reading property file: " + propFileName + " - defaults parameters applied") ; return ; } try { port = Integer.parseInt(p.getProperty("port")) ; } catch (Exception e) { } try { ArrayList addr = new ArrayList() ; StringTokenizer st = new StringTokenizer(p.getProperty("allowIPAddresses"), ",") ; while (st.hasMoreTokens()) { String s = st.nextToken().trim() ; if (s.length() > 0) addr.add(s) ; } allowIPAddresses = new String[addr.size()] ; addr.toArray(allowIPAddresses) ; allowIPAddressExactMatch = new boolean[allowIPAddresses.length] ; for (int i=0;i= 0) { allowIPAddressExactMatch[i] = false ; allowIPAddresses[i] = allowIPAddresses[i].substring(0, j) ; } else allowIPAddressExactMatch[i] = true ; } } catch (Exception e) { } String logFileName = p.getProperty("logFile") ; if (logFileName != null) { try { log = new Logger(logFileName) ; } catch (Exception e) { System.err.println("Error opening or writing log file: " + logFileName + " - logging disabled") ; log = null ; } } } } class ConnectionProcessor implements Runnable { final static int INBUFLEN = 2048 ; private Socket s ; String remoteAddr ; ConnectionProcessor (Socket s) { this.s = s ; } public void run() { boolean ok = false ; remoteAddr = s.getInetAddress().getHostAddress() ; if ("127.0.0.1".equals(remoteAddr) || "localhost".equals(remoteAddr)) ok = true ; else if (DesktopProxy.allowIPAddresses != null) { for (int i=0;i 0)) { String str = new String(buf, 0, c) ; first = false ; // what to do - first unescape //System.out.println(str) ; String decodeStr = URLDecoder.decode(str,KODOVANI) ; if ((decodeStr.indexOf("/options&") > 0) || (decodeStr.indexOf("/delete&") > 0)) { // hmmm.. variants possible? s.getOutputStream().write("HTTP/1.0 403 Forbidden\r\n\r\n".getBytes()) ; break ; } boolean passThru = true ; String resourceToReturn = null ; if (decodeStr.startsWith("GET /redir?url=") && (decodeStr.length() > 18)) { // file redirect - we read and send if (decodeStr.substring(16, 18).equals(":\\")) { int i = decodeStr.indexOf("&") ; resourceToReturn = decodeStr.substring(15, i); //System.out.println("Poslat soubor "+resourceToReturn); passThru = false ; } } else if (decodeStr.startsWith("GET /redir?url=")) { // possible nonlocal http if (!decodeStr.startsWith("GET /redir?url=http://127.0.0.1:4664/")) { // just issue a redirect back to the user String redirUrl = str.substring(15) ; int i = redirUrl.indexOf("&") ; if (i < 0) i = redirUrl.indexOf(" ") ; if (i > 0) { // found a likely real terminator redirUrl = redirUrl.substring(0, i) ; os.write("HTTP/1.0 301 Redirect\r\n".getBytes()) ; os.write(("Location: " + redirUrl + "\r\n\r\n").getBytes()) ; passThru = false ; } } } if (DesktopProxy.log != null) { int i = decodeStr.indexOf("\r") ; if (i < 0) i = 50 ; DesktopProxy.log.write(remoteAddr + " " + decodeStr.substring(4, i)) ; } if (passThru) { otherSideSocket = new Socket(DesktopProxy.GOOGLE_DESKTOP_HOST, DesktopProxy.GOOGLE_DESKTOP_PORT) ; // otherSideSocket.setSoTimeout(DesktopProxy.timeout) ; // otherSideSocket.setSoLinger(true, DesktopProxy.timeout) ; rin = otherSideSocket.getInputStream() ; ros = otherSideSocket.getOutputStream() ; new Thread(new SendThread(os, rin, s, otherSideSocket)).start() ; } else { sendResource(resourceToReturn, os) ; //System.out.println("resourceToReturn="+resourceToReturn) ; return ; } } if (c < 1) break ; if (ros != null) ros.write(buf, 0, c) ; } } catch (Exception e) { // ignore } is.close() ; if ((otherSideSocket != null) && (!otherSideSocket.isClosed())) otherSideSocket.close() ; } private void sendResource(String resourceToReturn, OutputStream os) throws Exception { String contentType = "nenalezeno" ; int i = resourceToReturn.lastIndexOf(".") ; if (i > 0) { String type = resourceToReturn.substring(i+1).trim().toLowerCase() ; // yukk - convert to hashmap, augment/replace from parm file... if (type.equals("bmp")) contentType = "image/bmp" ; else if (type.equals("csv")) contentType = "application/vnd.ms-excel" ; else if (type.equals("doc")) contentType = "application/msword" ; else if (type.equals("ppt")) contentType = "application/vnd.ms-powerpoint" ; else if (type.equals("xls")) contentType = "application/vnd.ms-excel" ; } //String obracene = URI.toURL(resourceToReturn); byte[] obracene = (new String(resourceToReturn)).getBytes() ; byte[] lomitko = (new String("\\")).getBytes() ; byte[] nahradit = (new String("/")).getBytes() ; for (int k=0;k\r\n\r\n".getBytes()) ; os.write("".getBytes()); os.write("".getBytes()); os.write("".getBytes()); os.write("\r\n\r\n".getBytes()); os.write("

Odkaz na nalezený soubor:

".getBytes()); if (contentType.equals("nenalezeno")){ os.write("".getBytes()); os.write(resourceToReturn.getBytes()); os.write("".getBytes()); os.write("

Kliknutím na odkazu levým tlačítkem myši dojde k jeho otevření v intetnetovém prohlížeči. Při kliknutí levým tlačítkem se otevře soubor přímo na serveru a všechny provedené změny se ukládají na SERVER!".getBytes()); os.write("

Kliknutím na odkazu pravým tlačítkem myši dojde k rozbalení nabídky s možností Uložit cíl jako ...

".getBytes()); os.write("

TIP
Pro otevření souboru přímo v přidružené aplikaci odkaz označíme, zkopírujeme (Ctrl+C) a vložíme (Ctrl+V) do aplikace průzkumník Windows do řádku Adresa. Následným stiskem klávesy Enter dojde k otevření souboru v přidružené aplikaci (např. MS Word, Excel apod.). Zde se opět zpracovává soubor přímo ze serveru a všechny změny se tedy ukládají na SERVERU!".getBytes()); } if (!contentType.equals("nenalezeno")){ os.write("".getBytes()); os.write(obracene); os.write("".getBytes()); os.write("

 

".getBytes()); os.write("

 

".getBytes()); os.write("

 

".getBytes()); os.write("

 

".getBytes()); //původní odkaz ... os.write("
".getBytes()); os.write("Přímý odkaz pro otevření v IE nebo průzkumíku Windows ".getBytes()); os.write(resourceToReturn.getBytes()); os.write("".getBytes()); os.write("
".getBytes()); } os.write("
".getBytes()); os.write("

 

© 2004 Ing. Pavel Ševčík - BAS Rudice spol. s r.o.

".getBytes()); os.write("".getBytes()); os.write("
".getBytes()); } } class SendThread implements Runnable { private static final int OUTBUFLEN = 1024*48 ; static final byte[] substituteHostPort = (new String("127.0.0.1:4664")).getBytes() ; static final byte[] substituteRedir = (new String("'/redir?url=")).getBytes() ; static final byte[] replacementRedir = (new String("'file://")).getBytes() ; OutputStream os ; InputStream rin ; Socket s1 ; Socket s2 ; byte[] replacementHostPort ; byte[] buf = new byte[OUTBUFLEN] ; int maxLen, readStart ; SendThread(OutputStream os, InputStream rin, Socket s1, Socket s2) { this.os = os ; this.rin = rin ; this.s1 = s1 ; this.s2 = s2 ; String locAddress = s1.getLocalAddress().getHostAddress() + ":" + DesktopProxy.port ; replacementHostPort = locAddress.getBytes() ; } public void run() { maxLen = OUTBUFLEN ; readStart = 0 ; try { while (true) { //System.out.println("OUT read") ; int c = rin.read(buf, readStart, maxLen) ; //if (c > 0) System.out.println(new String(buf, 0, c)) ; if (c < 1) break ; readStart += c ; maxLen = maxLen - c ; //if (readStart > (OUTBUFLEN / 10)) flush() ; } flush() ; os.close() ; rin.close() ; } catch (Exception e) { System.err.println("exception in SendThread:" + e) ; e.printStackTrace() ; } } private void flush() throws Exception { if (readStart < 1) return ; int runStart = 0 ; //System.out.println("flush readStart="+readStart) ; for (int i=0;i runStart) os.write(buf, runStart, i - runStart) ; os.write(replacementRedir, 0, replacementRedir.length) ; i += substituteRedir.length ; //zde zpracovat kódování souboru a odstranit parametry za & int pozice = i+300; if (pozice > readStart){ pozice = readStart; } String str = new String(buf, i, pozice) ; int x = str.indexOf("&src=1") ; int y = str.indexOf("'>") ; String cesta = str.substring(0,x); String KODOVANI = "UTF-8"; String cestazm = URLDecoder.decode(cesta,KODOVANI); KODOVANI = "US-ASCII"; cestazm = URLEncoder.encode(cestazm,KODOVANI); //cestazm = cestazm.concat("' charset="+'"'+"windows-1250"+'"'); byte[] cestabuf = (new String(cestazm)).getBytes() ; os.write(cestabuf,0,cestabuf.length); //System.out.println("x "+x+" y "+y) ; //System.out.println(cestazm) ; i += y; //zohledneni vynechaneho retezce runStart = i; } **/ if (!match2 && match) { // matched at i if (i > runStart) os.write(buf, runStart, i - runStart) ; os.write(replacementHostPort, 0, replacementHostPort.length) ; i += substituteHostPort.length ; runStart = i ; //System.out.println(" subs, I,runstart increased to " + i) ; } } os.write(buf, runStart, readStart - runStart) ; readStart = 0 ; maxLen = OUTBUFLEN ; } } class Logger { FileWriter log = null ; Logger(String logFileName) throws Exception { log = new FileWriter(logFileName, true) ; // append write("log opened") ; if (log == null) throw new Exception("Cant write to log file") ; } void write(String logMsg) { try { log.write((new Date()).toString() + " " + logMsg + "\n") ; log.flush() ; } catch (Exception e) { log = null ; } } }