diff --git a/core/java/src/net/i2p/util/EepGet.java b/core/java/src/net/i2p/util/EepGet.java
index 1a6e23a011fe84a73823de2263cc44ef6e3a3056..2f59baeac7ce8cced513b80ae111dc1fdd102e14 100644
--- a/core/java/src/net/i2p/util/EepGet.java
+++ b/core/java/src/net/i2p/util/EepGet.java
@@ -92,7 +92,7 @@ public class EepGet {
 
     // following for proxy digest auth
     // only created via addAuthorization()
-    private AuthState _authState;
+    protected AuthState _authState;
 
     /** this will be replaced by the HTTP Proxy if we are using it */
     protected static final String USER_AGENT = "Wget/1.11.4";
@@ -175,7 +175,6 @@ public class EepGet {
         long inactivityTimeout = INACTIVITY_TIMEOUT;
         String etag = null;
         String saveAs = null;
-        String url = null;
         List<String> extra = null;
         String username = null;
         String password = null;
@@ -233,13 +232,18 @@ public class EepGet {
                     break;
 
                 case 'h':
-                    if (extra == null)
-                        extra = new ArrayList<String>(2);
                     String a = g.getOptarg();
-                    String key = a.substring(0, a.indexOf('='));
-                    String val = a.substring(a.indexOf('=')+1);
-                    extra.add(key);
-                    extra.add(val);
+                    int eq = a.indexOf('=');
+                    if (eq > 0) {
+                        if (extra == null)
+                            extra = new ArrayList<String>(2);
+                        String key = a.substring(0, eq);
+                        String val = a.substring(eq + 1);
+                        extra.add(key);
+                        extra.add(val);
+                    } else {
+                        error = true;
+                    }
                     break;
 
                 case 'u':
@@ -262,12 +266,11 @@ public class EepGet {
             error = true;
         }
 
-        int remaining = args.length - g.getOptind();
-        if (error || remaining != 1) {
+        if (error || args.length - g.getOptind() != 1) {
             usage();
             System.exit(1);
         }
-        url = args[g.getOptind()];
+        String url = args[g.getOptind()];
 
         if (saveAs == null)
             saveAs = suggestName(url);
@@ -349,7 +352,7 @@ public class EepGet {
     }
 
     private static void usage() {
-        System.err.println("eepget [-p 127.0.0.1:4444] [-c] [-o outputFile]\n" +
+        System.err.println("eepget [-p 127.0.0.1[:4444]] [-c] [-o outputFile]\n" +
                            "       [-n #retries] (default 5)\n" +
                            "       [-m markSize] (default 1024)\n" +
                            "       [-l lineLen]  (default 40)\n" +
@@ -697,8 +700,6 @@ public class EepGet {
                     throw new IOException("Proxy requires authentication");
                 if (as.authSent)
                     throw new IOException("Proxy authentication failed");  // ignore stale
-                if (as.authChallenge == null)
-                    throw new IOException("Bad proxy auth response");
                 if (_log.shouldLog(Log.INFO)) _log.info("Adding auth");
                 // actually happens in getRequest()
             } else {
@@ -1379,7 +1380,6 @@ public class EepGet {
      *  Add basic authorization header for the proxy.
      *  Only added if the request is going through a proxy.
      *  Must be called before fetch().
-     *  Not supported by EepHead.
      *
      *  @since 0.8.9
      */
@@ -1469,7 +1469,7 @@ public class EepGet {
     /**
      *  @since 0.9.12
      */
-    private enum AUTH_MODE {NONE, BASIC, DIGEST, UNKNOWN}
+    protected enum AUTH_MODE {NONE, BASIC, DIGEST, UNKNOWN}
 
     /**
      *  Manage the authentication parameters
@@ -1479,7 +1479,7 @@ public class EepGet {
      *
      *  @since 0.9.12
      */
-    private class AuthState {
+    protected class AuthState {
         private final String username;
         private final String password;
         // as recvd in 407
@@ -1517,7 +1517,7 @@ public class EepGet {
                 // better than NONE only
                 if (authMode == AUTH_MODE.NONE) {
                     authMode = AUTH_MODE.UNKNOWN;
-                    authChallenge = "";
+                    authChallenge = null;
                 }
             }
             nonceCount = 0;
@@ -1533,6 +1533,8 @@ public class EepGet {
                            Base64.encode(DataHelper.getUTF8(username + ':' + password), true);
 
                 case DIGEST:
+                    if (authChallenge == null)
+                        throw new IOException("Bad proxy auth response");
                     if (args == null)
                         args = parseAuthArgs(authChallenge);
                     Map<String, String> outArgs = generateAuthArgs(method, uri);
diff --git a/core/java/src/net/i2p/util/EepHead.java b/core/java/src/net/i2p/util/EepHead.java
index 53650408835e147c9896be070e732fbba7dafbcc..c1ddb62828001a4661c0e877ae10030b84a6328d 100644
--- a/core/java/src/net/i2p/util/EepHead.java
+++ b/core/java/src/net/i2p/util/EepHead.java
@@ -1,10 +1,15 @@
 package net.i2p.util;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.net.URL;
 
+import gnu.getopt.Getopt;
+
 import net.i2p.I2PAppContext;
 
 /**
@@ -51,39 +56,86 @@ public class EepHead extends EepGet {
         int proxyPort = 4444;
         int numRetries = 0;
         int inactivityTimeout = 60*1000;
-        String url = null;
+        String username = null;
+        String password = null;
+        boolean error = false;
+        Getopt g = new Getopt("eephead", args, "p:cn:t:u:x:");
         try {
-            for (int i = 0; i < args.length; i++) {
-                if (args[i].equals("-p")) {
-                    proxyHost = args[i+1].substring(0, args[i+1].indexOf(':'));
-                    String port = args[i+1].substring(args[i+1].indexOf(':')+1);
-                    proxyPort = Integer.parseInt(port);
-                    i++;
-                } else if (args[i].equals("-n")) {
-                    numRetries = Integer.parseInt(args[i+1]);
-                    i++;
-                } else if (args[i].equals("-t")) {
-                    inactivityTimeout = 1000 * Integer.parseInt(args[i+1]);
-                    i++;
-                } else if (args[i].startsWith("-")) {
-                    usage();
-                    return;
-                } else {
-                    url = args[i];
-                }
-            }
+            int c;
+            while ((c = g.getopt()) != -1) {
+              switch (c) {
+                case 'p':
+                    String s = g.getOptarg();
+                    int colon = s.indexOf(':');
+                    if (colon >= 0) {
+                        // Todo IPv6 [a:b:c]:4444
+                        proxyHost = s.substring(0, colon);
+                        String port = s.substring(colon + 1);
+                        proxyPort = Integer.parseInt(port);
+                    } else {
+                        proxyHost = s;
+                        // proxyPort remains default
+                    }
+                    break;
+
+                case 'c':
+                    // no proxy, same as -p :0
+                    proxyHost = "";
+                    proxyPort = 0;
+                    break;
+
+                case 'n':
+                    numRetries = Integer.parseInt(g.getOptarg());
+                    break;
+
+                case 't':
+                    inactivityTimeout = 1000 * Integer.parseInt(g.getOptarg());
+                    break;
+
+                case 'u':
+                    username = g.getOptarg();
+                    break;
+
+                case 'x':
+                    password = g.getOptarg();
+                    break;
+
+                case '?':
+                case ':':
+                default:
+                    error = true;
+                    break;
+              }  // switch
+            } // while
         } catch (Exception e) {
             e.printStackTrace();
-            usage();
-            return;
+            error = true;
         }
-        
-        if (url == null) {
+
+        if (error || args.length - g.getOptind() != 1) {
             usage();
-            return;
+            System.exit(1);
         }
-
+        String url = args[g.getOptind()];
+        
         EepHead get = new EepHead(I2PAppContext.getGlobalContext(), proxyHost, proxyPort, numRetries, url);
+        if (username != null) {
+            if (password == null) {
+                try {
+                    BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
+                    do {
+                        System.err.print("Proxy password: ");
+                        password = r.readLine();
+                        if (password == null)
+                            throw new IOException();
+                        password = password.trim();
+                    } while (password.length() <= 0);
+                } catch (IOException ioe) {
+                    System.exit(1);
+                }
+            }
+            get.addAuthorization(username, password);
+        }
         if (get.fetch(45*1000, -1, inactivityTimeout)) {
             System.err.println("Content-Type: " + get.getContentType());
             System.err.println("Content-Length: " + get.getContentLength());
@@ -96,7 +148,11 @@ public class EepHead extends EepGet {
     }
     
     private static void usage() {
-        System.err.println("EepHead [-p 127.0.0.1:4444] [-n #retries] [-t timeout] url");
+        System.err.println("EepHead [-p 127.0.0.1[:4444]] [-c]\n" +
+                           "        [-n #retries] (default 0)\n" +
+                           "        [-t timeout]  (default 60 sec)\n" +
+                           "        [-u username] [-x password] url\n" +
+                           "        (use -c or -p :0 for no proxy)");
     }
     
     /** return true if the URL was completely retrieved */
@@ -138,10 +194,24 @@ public class EepHead extends EepGet {
             //} catch (MalformedURLException mue) {
             //    throw new IOException("Redirected from an invalid URL");
             //}
-            _redirects++;
-            if (_redirects > 5)
-                throw new IOException("Too many redirects: to " + _redirectLocation);
-            if (_log.shouldLog(Log.INFO)) _log.info("Redirecting to " + _redirectLocation);
+            AuthState as = _authState;
+            if (_responseCode == 407) {
+                if (!_shouldProxy)
+                    throw new IOException("Proxy auth response from non-proxy");
+                if (as == null)
+                    throw new IOException("Proxy requires authentication");
+                if (as.authSent)
+                    throw new IOException("Proxy authentication failed");  // ignore stale
+                if (_log.shouldLog(Log.INFO)) _log.info("Adding auth");
+                // actually happens in getRequest()
+            } else {
+                _redirects++;
+                if (_redirects > 5)
+                    throw new IOException("Too many redirects: to " + _redirectLocation);
+                if (_log.shouldLog(Log.INFO)) _log.info("Redirecting to " + _redirectLocation);
+                if (as != null)
+                    as.authSent = false;
+            }
 
             // reset some important variables, we don't want to save the values from the redirect
             _bytesRemaining = -1;
@@ -212,6 +282,11 @@ public class EepHead extends EepGet {
         buf.append("Accept-Encoding: \r\n");
         // This will be replaced if we are going through I2PTunnelHTTPClient
         buf.append("User-Agent: " + USER_AGENT + "\r\n");
+        if (_authState != null && _shouldProxy && _authState.authMode != AUTH_MODE.NONE) {
+            buf.append("Proxy-Authorization: ");
+            buf.append(_authState.getAuthHeader("HEAD", urlToSend));
+            buf.append("\r\n");
+        }
         buf.append("Connection: close\r\n\r\n");
         if (_log.shouldLog(Log.DEBUG))
             _log.debug("Request: [" + buf.toString() + "]");
diff --git a/core/java/src/net/i2p/util/PartialEepGet.java b/core/java/src/net/i2p/util/PartialEepGet.java
index 4f3cf95519676799bbfdfe177ac337352fc3482a..baab6e0397d2b557e6a76df453d7a9904e070a93 100644
--- a/core/java/src/net/i2p/util/PartialEepGet.java
+++ b/core/java/src/net/i2p/util/PartialEepGet.java
@@ -1,12 +1,16 @@
 package net.i2p.util;
 
+import java.io.BufferedReader;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Locale;
 
+import gnu.getopt.Getopt;
+
 import net.i2p.I2PAppContext;
 
 /**
@@ -50,46 +54,99 @@ public class PartialEepGet extends EepGet {
         int proxyPort = 4444;
         // 40 sig + 16 version for .suds
         long size = 56;
-        String url = null;
+        String saveAs = null;
+        String username = null;
+        String password = null;
+        boolean error = false;
+        Getopt g = new Getopt("partialeepget", args, "p:cl:o:u:x:");
         try {
-            for (int i = 0; i < args.length; i++) {
-                if (args[i].equals("-p")) {
-                    proxyHost = args[i+1].substring(0, args[i+1].indexOf(':'));
-                    String port = args[i+1].substring(args[i+1].indexOf(':')+1);
-                    proxyPort = Integer.parseInt(port);
-                    i++;
-                } else if (args[i].equals("-l")) {
-                    size = Long.parseLong(args[i+1]);
-                    i++;
-                } else if (args[i].startsWith("-")) {
-                    usage();
-                    return;
-                } else {
-                    url = args[i];
-                }
-            }
+            int c;
+            while ((c = g.getopt()) != -1) {
+              switch (c) {
+                case 'p':
+                    String s = g.getOptarg();
+                    int colon = s.indexOf(':');
+                    if (colon >= 0) {
+                        // Todo IPv6 [a:b:c]:4444
+                        proxyHost = s.substring(0, colon);
+                        String port = s.substring(colon + 1);
+                        proxyPort = Integer.parseInt(port);
+                    } else {
+                        proxyHost = s;
+                        // proxyPort remains default
+                    }
+                    break;
+
+                case 'c':
+                    // no proxy, same as -p :0
+                    proxyHost = "";
+                    proxyPort = 0;
+                    break;
+
+                case 'l':
+                    size = Long.parseLong(g.getOptarg());
+                    break;
+
+                case 'o':
+                    saveAs = g.getOptarg();
+                    break;
+
+                case 'u':
+                    username = g.getOptarg();
+                    break;
+
+                case 'x':
+                    password = g.getOptarg();
+                    break;
+
+                case '?':
+                case ':':
+                default:
+                    error = true;
+                    break;
+              }  // switch
+            } // while
         } catch (Exception e) {
             e.printStackTrace();
-            usage();
-            return;
+            error = true;
         }
-        
-        if (url == null) {
+
+        if (error || args.length - g.getOptind() != 1) {
             usage();
-            return;
+            System.exit(1);
         }
+        String url = args[g.getOptind()];
 
-        String saveAs = suggestName(url);
+        if (saveAs == null)
+            saveAs = suggestName(url);
         OutputStream out;
         try {
             // resume from a previous eepget won't work right doing it this way
             out = new FileOutputStream(saveAs);
         } catch (IOException ioe) {
             System.err.println("Failed to create output file " + saveAs);
-            return;
+            out = null; // dummy for compiler
+            System.exit(1);
         }
 
         EepGet get = new PartialEepGet(I2PAppContext.getGlobalContext(), proxyHost, proxyPort, out, url, size);
+        if (username != null) {
+            if (password == null) {
+                try {
+                    BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
+                    do {
+                        System.err.print("Proxy password: ");
+                        password = r.readLine();
+                        if (password == null)
+                            throw new IOException();
+                        password = password.trim();
+                    } while (password.length() <= 0);
+                } catch (IOException ioe) {
+                    System.exit(1);
+                }
+            }
+            get.addAuthorization(username, password);
+        }
         get.addStatusListener(get.new CLIStatusListener(1024, 40));
         if (get.fetch(45*1000, -1, 60*1000)) {
             System.err.println("Last-Modified: " + get.getLastModified());
@@ -101,8 +158,10 @@ public class PartialEepGet extends EepGet {
     }
     
     private static void usage() {
-        System.err.println("PartialEepGet [-p 127.0.0.1:4444] [-l #bytes] url\n" +
-                           "              (use -p :0 for no proxy)");
+        System.err.println("PartialEepGet [-p 127.0.0.1[:4444]] [-c] [-o outputFile]\n" +
+                           "              [-l #bytes] (default 56)\n" +
+                           "              [-u username] [-x password] url\n" +
+                           "              (use -c or -p :0 for no proxy)");
     }
     
     @Override
@@ -158,6 +217,11 @@ public class PartialEepGet extends EepGet {
         // This will be replaced if we are going through I2PTunnelHTTPClient
         if(!uaOverridden)
             buf.append("User-Agent: " + USER_AGENT + "\r\n");
+        if (_authState != null && _shouldProxy && _authState.authMode != AUTH_MODE.NONE) {
+            buf.append("Proxy-Authorization: ");
+            buf.append(_authState.getAuthHeader("GET", urlToSend));
+            buf.append("\r\n");
+        }
         buf.append("\r\n");
 
         if (_log.shouldLog(Log.DEBUG))
diff --git a/core/java/src/net/i2p/util/SSLEepGet.java b/core/java/src/net/i2p/util/SSLEepGet.java
index 81b728b57262706d97260314c6c33cc3c20d6fbf..9236d6cae989428912b69b01593940b786e4f6ed 100644
--- a/core/java/src/net/i2p/util/SSLEepGet.java
+++ b/core/java/src/net/i2p/util/SSLEepGet.java
@@ -58,6 +58,8 @@ import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
 
+import gnu.getopt.Getopt;
+
 import net.i2p.I2PAppContext;
 import net.i2p.crypto.CertUtil;
 import net.i2p.crypto.KeyStoreUtil;
@@ -147,29 +149,34 @@ public class SSLEepGet extends EepGet {
      * SSLEepGet -s https://foo/bar
      */ 
     public static void main(String args[]) {
-        String url = null;
         boolean saveCerts = false;
+        boolean error = false;
+        Getopt g = new Getopt("ssleepget", args, "s");
         try {
-            for (int i = 0; i < args.length; i++) {
-                if (args[i].equals("-s")) {
+            int c;
+            while ((c = g.getopt()) != -1) {
+              switch (c) {
+                case 's':
                     saveCerts = true;
-                } else if (args[i].startsWith("-")) {
-                    usage();
-                    return;
-                } else {
-                    url = args[i];
-                }
-            }
+                    break;
+
+                case '?':
+                case ':':
+                default:
+                    error = true;
+                    break;
+              }  // switch
+            } // while
         } catch (Exception e) {
             e.printStackTrace();
-            usage();
-            return;
+            error = true;
         }
-        
-        if (url == null) {
+
+        if (error || args.length - g.getOptind() != 1) {
             usage();
-            return;
+            System.exit(1);
         }
+        String url = args[g.getOptind()];
 
         String saveAs = suggestName(url);
         OutputStream out;
@@ -191,8 +198,8 @@ public class SSLEepGet extends EepGet {
     }
     
     private static void usage() {
-        System.err.println("Usage: SSLEepGet https://url");
-        System.err.println("To save unknown certs, use: SSLEepGet -s https://url");
+        System.err.println("Usage: SSLEepGet https://url\n" +
+                           "To save unknown certs, use: SSLEepGet -s https://url");
     }
 
     /**