* EepHead, PartialEepGet, SSLEepGet:

- Convert to getopt (ticket #1173)
 * EepHead, PartialEepGet:
   - New option -c for clearnet (no proxy), same as -p:0
   - New option -o, same as EepGet
   - Proxy option -p with host name arg only (no ':') now allowed
   - Add proxy auth support with -u and -x options (ticket #1173)
 * EepGet:
   - Catch error in -h option
   - Cleanups
This commit is contained in:
zzz
2014-02-06 14:18:51 +00:00
parent 0d028122a6
commit deec84713f
4 changed files with 243 additions and 95 deletions

View File

@@ -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);

View File

@@ -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;
}
if (url == null) {
usage();
return;
error = true;
}
if (error || args.length - g.getOptind() != 1) {
usage();
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() + "]");

View File

@@ -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;
}
if (url == null) {
usage();
return;
error = true;
}
String saveAs = suggestName(url);
if (error || args.length - g.getOptind() != 1) {
usage();
System.exit(1);
}
String url = args[g.getOptind()];
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))

View File

@@ -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");
}
/**