/** depth-first search */
	private static NamingService searchNamingService(NamingService ns, String srch)
	{
		String name = ns.getName();
		if (name.equals(srch) || basename(name).equals(srch) || name.equals(DEFAULT_NS))
			return ns;
		List<NamingService> list = ns.getNamingServices();
		if (list != null) {
			for (NamingService nss : list) {
				NamingService rv = searchNamingService(nss, srch);
				if (rv != null)
					return rv;
			}
		}
		return null;		
	}
Beispiel #2
0
    /**
     *  Very simple web server.
     *
     *  Serve local files in the docs/ directory, for CSS and images in
     *  error pages, using the reserved address proxy.i2p
     *  (similar to p.p in privoxy).
     *  This solves the problems with including links to the router console,
     *  as assuming the router console is at 127.0.0.1 leads to broken
     *  links if it isn't.
     *
     *  Ignore all request headers (If-Modified-Since, etc.)
     *
     *  There is basic protection here -
     *  FileUtil.readFile() prevents traversal above the base directory -
     *  but inproxy/gateway ops would be wise to block proxy.i2p to prevent
     *  exposing the docs/ directory or perhaps other issues through
     *  uncaught vulnerabilities.
     *  Restrict to the /themes/ directory for now.
     *
     *  @param targetRequest decoded path only, non-null
     *  @param query raw (encoded), may be null
     */
    public static void serveLocalFile(OutputStream out, String method, String targetRequest, String query, String proxyNonce) {
        //System.err.println("targetRequest: \"" + targetRequest + "\"");
        // a home page message for the curious...
        if (targetRequest.equals("/")) {
            try {
                out.write(("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nCache-Control: max-age=86400\r\n\r\nI2P HTTP proxy OK").getBytes());
                out.flush();
            } catch (IOException ioe) {}
            return;
        }
        if ((method.equals("GET") || method.equals("HEAD")) &&
            targetRequest.startsWith("/themes/") &&
            !targetRequest.contains("..")) {
            String filename = null;
            try {
                filename = targetRequest.substring(8); // "/themes/".length
            } catch (IndexOutOfBoundsException ioobe) {
                 return;
            }
            // theme hack
            if (filename.startsWith("console/default/"))
                filename = filename.replaceFirst("default", I2PAppContext.getGlobalContext().getProperty("routerconsole.theme", "light"));
            File themesDir = new File(I2PAppContext.getGlobalContext().getBaseDir(), "docs/themes");
            File file = new File(themesDir, filename);
            if (file.exists() && !file.isDirectory()) {
                String type;
                if (filename.endsWith(".css"))
                    type = "text/css";
                else if (filename.endsWith(".ico"))
                    type = "image/x-icon";
                else if (filename.endsWith(".png"))
                    type = "image/png";
                else if (filename.endsWith(".jpg"))
                    type = "image/jpeg";
                else type = "text/html";
                try {
                    out.write("HTTP/1.1 200 OK\r\nContent-Type: ".getBytes());
                    out.write(type.getBytes());
                    out.write("\r\nCache-Control: max-age=86400\r\n\r\n".getBytes());
                    FileUtil.readFile(filename, themesDir.getAbsolutePath(), out);
                } catch (IOException ioe) {}
                return;
            }
        }

        // Add to addressbook (form submit)
        // Parameters are url, host, dest, nonce, and master | router | private.
        // Do the add and redirect.
        if (targetRequest.equals("/add")) {
            Map<String, String> opts = new HashMap(8);
            // this only works if all keys are followed by =value
            StringTokenizer tok = new StringTokenizer(query, "=&;");
            while (tok.hasMoreTokens()) {
                String k = tok.nextToken();
                if (!tok.hasMoreTokens())
                    break;
                String v = tok.nextToken();
                opts.put(decode(k), decode(v));
            }

            String url = opts.get("url");
            String host = opts.get("host");
            String b64Dest = opts.get("dest");
            String nonce = opts.get("nonce");
            String referer = opts.get("referer");
            String book = "privatehosts.txt";
            if (opts.get("master") != null)
                book = "userhosts.txt";
            else if (opts.get("router") != null)
                book = "hosts.txt";
            Destination dest = null;
            if (b64Dest != null) {
                try {
                    dest = new Destination(b64Dest);
                } catch (DataFormatException dfe) {
                    System.err.println("Bad dest to save?" + b64Dest);
                }
            }
            //System.err.println("url          : \"" + url           + "\"");
            //System.err.println("host         : \"" + host          + "\"");
            //System.err.println("b64dest      : \"" + b64Dest       + "\"");
            //System.err.println("book         : \"" + book          + "\"");
            //System.err.println("nonce        : \"" + nonce         + "\"");
            if (proxyNonce.equals(nonce) && url != null && host != null && dest != null) {
                try {
                    NamingService ns = I2PAppContext.getGlobalContext().namingService();
                    Properties nsOptions = new Properties();
                    nsOptions.setProperty("list", book);
                    if (referer != null && referer.startsWith("http")) {
                        String from = "<a href=\"" + referer + "\">" + referer + "</a>";
                        nsOptions.setProperty("s", _("Added via address helper from {0}", from));
                    } else {
                        nsOptions.setProperty("s", _("Added via address helper"));
                    }
                    boolean success = ns.put(host, dest, nsOptions);
                    writeRedirectPage(out, success, host, book, url);
                    return;
                } catch (IOException ioe) {}
            }
            try {
                out.write(ERR_ADD);
                out.flush();
            } catch (IOException ioe) {}
            return;
        }
        try {
            out.write(ERR_404);
            out.flush();
        } catch (IOException ioe) {}
    }
	/**
	 *  Load addressbook and apply filter, returning messages about this.
	 *  To control memory, don't load the whole addressbook if we can help it...
	 *  only load what is searched for.
	 */
	@Override
	public String getLoadBookMessages()
	{
		if (isDirect())
			return super.getLoadBookMessages();
		NamingService service = getNamingService();
		Debug.debug("Searching within " + service + " with filename=" + getFileName() + " and with filter=" + filter + " and with search=" + search);
		String message = "";
		try {
			LinkedList<AddressBean> list = new LinkedList<AddressBean>();
			Map<String, Destination> results;
			Properties searchProps = new Properties();
			// only blockfile needs this
			searchProps.setProperty("list", getFileName());
			if (filter != null) {
				String startsAt = filter.equals("0-9") ? "[0-9]" : filter;
				searchProps.setProperty("startsWith", startsAt);
			}
			if (isPrefiltered()) {
				// Only limit if we not searching or filtering, so we will
				// know the total number of results
				if (beginIndex > 0)
					searchProps.setProperty("skip", Integer.toString(beginIndex));
				int limit = 1 + endIndex - beginIndex;
				if (limit > 0)
					searchProps.setProperty("limit", Integer.toString(limit));
			}
			if (search != null && search.length() > 0)
				searchProps.setProperty("search", search.toLowerCase(Locale.US));
			results = service.getEntries(searchProps);

			Debug.debug("Result count: " + results.size());
			for (Map.Entry<String, Destination> entry : results.entrySet()) {
				String name = entry.getKey();
				if( filter != null && filter.length() > 0 ) {
					if (filter.equals("0-9")) {
						char first = name.charAt(0);
						if( first < '0' || first > '9' )
							continue;
					}
					else if( ! name.toLowerCase(Locale.US).startsWith( filter.toLowerCase(Locale.US) ) ) {
						continue;
					}
				}
				if( search != null && search.length() > 0 ) {
					if( name.indexOf( search ) == -1 ) {
						continue;
					}
				}
				String destination = entry.getValue().toBase64();
				if (destination != null) {
					list.addLast( new AddressBean( name, destination ) );
				} else {
					// delete it too?
					System.err.println("Bad entry " + name + " in database " + service.getName());
				}
			}
			AddressBean array[] = list.toArray(new AddressBean[list.size()]);
			Arrays.sort( array, sorter );
			entries = array;

			message = generateLoadMessage();
		}
		catch (Exception e) {
			Debug.debug( e.getClass().getName() + ": " + e.getMessage() );
		}
		if( message.length() > 0 )
			message = "<p>" + message + "</p>";
		return message;
	}