Changeset 54f0cae


Ignore:
Timestamp:
Feb 24, 2012 5:58:54 PM (8 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
e1c9402d
Parents:
eeb9ee0
Message:

refactor proxy.i2p server to its own class

Location:
apps/i2ptunnel/java/src/net/i2p/i2ptunnel
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java

    reeb9ee0 r54f0cae  
    3737import net.i2p.data.Destination;
    3838import net.i2p.data.Hash;
     39import net.i2p.i2ptunnel.localServer.LocalHTTPServer;
    3940import net.i2p.util.EventDispatcher;
    40 import net.i2p.util.FileUtil;
    4141import net.i2p.util.Log;
    4242import net.i2p.util.PortMapper;
     
    310310    }
    311311
    312     private static final String LOCAL_SERVER = "proxy.i2p";
     312    public static final String LOCAL_SERVER = "proxy.i2p";
    313313    private static final boolean DEFAULT_GZIP = true;
    314314    /** all default to false */
     
    799799                    out.write(ERR_HELPER_DISABLED);
    800800                } else {
    801                     serveLocalFile(out, method, targetRequest, _proxyNonce);
     801                    LocalHTTPServer.serveLocalFile(out, method, targetRequest, _proxyNonce);
    802802                }
    803803                s.close();
     
    10471047    }
    10481048
    1049     private static void writeFooter(OutputStream out) throws IOException {
     1049    /**
     1050     *  Public only for LocalHTTPServer, not for general use
     1051     */
     1052    public static void writeFooter(OutputStream out) throws IOException {
    10501053        // the css is hiding this div for now, but we'll keep it here anyway
    10511054        out.write("<div class=\"proxyfooter\"><p><i>I2P HTTP Proxy Server<br>Generated on: ".getBytes());
     
    11971200    }
    11981201
    1199     private final static byte[] ERR_404 =
    1200         ("HTTP/1.1 404 Not Found\r\n"+
    1201          "Content-Type: text/plain\r\n"+
    1202          "\r\n"+
    1203          "HTTP Proxy local file not found")
    1204         .getBytes();
    1205 
    1206     private final static byte[] ERR_ADD =
    1207         ("HTTP/1.1 409 Bad\r\n"+
    1208          "Content-Type: text/plain\r\n"+
    1209          "\r\n"+
    1210          "Add to addressbook failed - bad parameters")
    1211         .getBytes();
    1212 
    12131202    private final static byte[] ERR_HELPER_DISABLED =
    12141203        ("HTTP/1.1 403 Disabled\r\n"+
     
    12181207        .getBytes();
    12191208
    1220     /**
    1221      *  Very simple web server.
    1222      *
    1223      *  Serve local files in the docs/ directory, for CSS and images in
    1224      *  error pages, using the reserved address proxy.i2p
    1225      *  (similar to p.p in privoxy).
    1226      *  This solves the problems with including links to the router console,
    1227      *  as assuming the router console is at 127.0.0.1 leads to broken
    1228      *  links if it isn't.
    1229      *
    1230      *  Ignore all request headers (If-Modified-Since, etc.)
    1231      *
    1232      *  There is basic protection here -
    1233      *  FileUtil.readFile() prevents traversal above the base directory -
    1234      *  but inproxy/gateway ops would be wise to block proxy.i2p to prevent
    1235      *  exposing the docs/ directory or perhaps other issues through
    1236      *  uncaught vulnerabilities.
    1237      *  Restrict to the /themes/ directory for now.
    1238      *
    1239      *  @param targetRequest "proxy.i2p/themes/foo.png HTTP/1.1"
    1240      */
    1241     private static void serveLocalFile(OutputStream out, String method, String targetRequest, String proxyNonce) {
    1242         //System.err.println("targetRequest: \"" + targetRequest + "\"");
    1243         // a home page message for the curious...
    1244         if (targetRequest.startsWith(LOCAL_SERVER + "/ ")) {
    1245             try {
    1246                 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());
    1247                 out.flush();
    1248             } catch (IOException ioe) {}
    1249             return;
    1250         }
    1251         if ((method.equals("GET") || method.equals("HEAD")) &&
    1252             targetRequest.startsWith(LOCAL_SERVER + "/themes/") &&
    1253             !targetRequest.contains("..")) {
    1254             int space = targetRequest.indexOf(' ');
    1255             String filename = null;
    1256             try {
    1257                 filename = targetRequest.substring(LOCAL_SERVER.length() + 8, space); // "/themes/".length
    1258             } catch (IndexOutOfBoundsException ioobe) {
    1259                  return;
    1260             }
    1261             // theme hack
    1262             if (filename.startsWith("console/default/"))
    1263                 filename = filename.replaceFirst("default", I2PAppContext.getGlobalContext().getProperty("routerconsole.theme", "light"));
    1264             File themesDir = new File(_errorDir, "themes");
    1265             File file = new File(themesDir, filename);
    1266             if (file.exists() && !file.isDirectory()) {
    1267                 String type;
    1268                 if (filename.endsWith(".css"))
    1269                     type = "text/css";
    1270                 else if (filename.endsWith(".ico"))
    1271                     type = "image/x-icon";
    1272                 else if (filename.endsWith(".png"))
    1273                     type = "image/png";
    1274                 else if (filename.endsWith(".jpg"))
    1275                     type = "image/jpeg";
    1276                 else type = "text/html";
    1277                 try {
    1278                     out.write("HTTP/1.1 200 OK\r\nContent-Type: ".getBytes());
    1279                     out.write(type.getBytes());
    1280                     out.write("\r\nCache-Control: max-age=86400\r\n\r\n".getBytes());
    1281                     FileUtil.readFile(filename, themesDir.getAbsolutePath(), out);
    1282                 } catch (IOException ioe) {}
    1283                 return;
    1284             }
    1285         }
    1286 
    1287         // Add to addressbook (form submit)
    1288         // Parameters are url, host, dest, nonce, and master | router | private.
    1289         // Do the add and redirect.
    1290         if (targetRequest.startsWith(LOCAL_SERVER + "/add?")) {
    1291             int spc = targetRequest.indexOf(' ');
    1292             String query = targetRequest.substring(LOCAL_SERVER.length() + 5, spc);   // "/add?".length()
    1293             Map<String, String> opts = new HashMap(8);
    1294             StringTokenizer tok = new StringTokenizer(query, "=&;");
    1295             while (tok.hasMoreTokens()) {
    1296                 String k = tok.nextToken();
    1297                 if (!tok.hasMoreTokens())
    1298                     break;
    1299                 String v = tok.nextToken();
    1300                 opts.put(decode(k), decode(v));
    1301             }
    1302 
    1303             String url = opts.get("url");
    1304             String host = opts.get("host");
    1305             String b64Dest = opts.get("dest");
    1306             String nonce = opts.get("nonce");
    1307             String book = "privatehosts.txt";
    1308             if (opts.get("master") != null)
    1309                 book = "userhosts.txt";
    1310             else if (opts.get("router") != null)
    1311                 book = "hosts.txt";
    1312             Destination dest = null;
    1313             if (b64Dest != null) {
    1314                 try {
    1315                     dest = new Destination(b64Dest);
    1316                 } catch (DataFormatException dfe) {
    1317                     System.err.println("Bad dest to save?" + b64Dest);
    1318                 }
    1319             }
    1320             //System.err.println("url          : \"" + url           + "\"");
    1321             //System.err.println("host         : \"" + host          + "\"");
    1322             //System.err.println("b64dest      : \"" + b64Dest       + "\"");
    1323             //System.err.println("book         : \"" + book          + "\"");
    1324             //System.err.println("nonce        : \"" + nonce         + "\"");
    1325             if (proxyNonce.equals(nonce) && url != null && host != null && dest != null) {
    1326                 try {
    1327                     NamingService ns = I2PAppContext.getGlobalContext().namingService();
    1328                     Properties nsOptions = new Properties();
    1329                     nsOptions.setProperty("list", book);
    1330                     nsOptions.setProperty("s", _("Added via address helper"));
    1331                     boolean success = ns.put(host, dest, nsOptions);
    1332                     writeRedirectPage(out, success, host, book, url);
    1333                     return;
    1334                 } catch (IOException ioe) {}
    1335             }
    1336             try {
    1337                 out.write(ERR_ADD);
    1338                 out.flush();
    1339             } catch (IOException ioe) {}
    1340             return;
    1341         }
    1342         try {
    1343             out.write(ERR_404);
    1344             out.flush();
    1345         } catch (IOException ioe) {}
    1346     }
    1347 
    1348     /** @since 0.8.7 */
    1349     private static void writeRedirectPage(OutputStream out, boolean success, String host, String book, String url) throws IOException {
    1350         out.write(("HTTP/1.1 200 OK\r\n"+
    1351                   "Content-Type: text/html; charset=UTF-8\r\n"+
    1352                   "\r\n"+
    1353                   "<html><head>"+
    1354                   "<title>" + _("Redirecting to {0}", host) + "</title>\n" +
    1355                   "<link rel=\"shortcut icon\" href=\"http://proxy.i2p/themes/console/images/favicon.ico\" >\n" +
    1356                   "<link href=\"http://proxy.i2p/themes/console/default/console.css\" rel=\"stylesheet\" type=\"text/css\" >\n" +
    1357                   "<meta http-equiv=\"Refresh\" content=\"1; url=" + url + "\">\n" +
    1358                   "</head><body>\n" +
    1359                   "<div class=logo>\n" +
    1360                   "<a href=\"http://127.0.0.1:7657/\" title=\"" + _("Router Console") + "\"><img src=\"http://proxy.i2p/themes/console/images/i2plogo.png\" alt=\"I2P Router Console\" border=\"0\"></a><hr>\n" +
    1361                   "<a href=\"http://127.0.0.1:7657/config\">" + _("Configuration") + "</a> <a href=\"http://127.0.0.1:7657/help.jsp\">" + _("Help") + "</a> <a href=\"http://127.0.0.1:7657/susidns/index\">" + _("Addressbook") + "</a>\n" +
    1362                   "</div>" +
    1363                   "<div class=warning id=warning>\n" +
    1364                   "<h3>" +
    1365                   (success ?
    1366                            _("Saved {0} to the {1} addressbook, redirecting now.", host, book) :
    1367                            _("Failed to save {0} to the {1} addressbook, redirecting now.", host, book)) +
    1368                   "</h3>\n<p><a href=\"" + url + "\">" +
    1369                   _("Click here if you are not redirected automatically.") +
    1370                   "</a></p></div>").getBytes("UTF-8"));
    1371         writeFooter(out);
    1372         out.flush();
    1373     }
    1374 
    1375     /**
    1376      *  Decode %xx encoding
    1377      *  @since 0.8.7
    1378      */
    1379     private static String decode(String s) {
    1380         if (!s.contains("%"))
    1381             return s;
    1382         StringBuilder buf = new StringBuilder(s.length());
    1383         for (int i = 0; i < s.length(); i++) {
    1384             char c = s.charAt(i);
    1385             if (c != '%') {
    1386                 buf.append(c);
    1387             } else {
    1388                 try {
    1389                     buf.append((char) Integer.parseInt(s.substring(++i, (++i) + 1), 16));
    1390                 } catch (IndexOutOfBoundsException ioobe) {
    1391                     break;
    1392                 } catch (NumberFormatException nfe) {
    1393                     break;
    1394                 }
    1395             }
    1396         }
    1397         return buf.toString();
    1398     }
    1399 
    14001209    private static final String BUNDLE_NAME = "net.i2p.i2ptunnel.web.messages";
    14011210
Note: See TracChangeset for help on using the changeset viewer.