mirror of
https://github.com/internetarchive/heritrix3.git
synced 2026-09-22 21:55:54 +00:00
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* This file is part of the Heritrix web crawler (crawler.archive.org).
|
||||
*
|
||||
* Licensed to the Internet Archive (IA) by one or more individual
|
||||
* contributors.
|
||||
*
|
||||
* The IA licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.archive.crawler.selftest;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mortbay.jetty.Handler;
|
||||
import org.mortbay.jetty.Server;
|
||||
import org.mortbay.jetty.bio.SocketConnector;
|
||||
import org.mortbay.jetty.handler.DefaultHandler;
|
||||
import org.mortbay.jetty.handler.HandlerList;
|
||||
import org.mortbay.jetty.handler.ResourceHandler;
|
||||
import org.mortbay.jetty.servlet.ServletHandler;
|
||||
import org.mortbay.jetty.servlet.ServletHolder;
|
||||
|
||||
/**
|
||||
* Test form-based authentication
|
||||
*
|
||||
* @contributor stack
|
||||
* @contributor gojomo
|
||||
*/
|
||||
public class FormLoginSelfTest
|
||||
extends SelfTestBase
|
||||
{
|
||||
/**
|
||||
* Files to find as a list.
|
||||
*/
|
||||
final private static Set<String> EXPECTED = Collections.unmodifiableSet(
|
||||
new HashSet<String>(Arrays.asList(new String[] {
|
||||
"index.html", "login/login.html", "success.html", "robots.txt", "favicon.ico"
|
||||
})));
|
||||
|
||||
@Override
|
||||
protected void verify() throws Exception {
|
||||
Set<String> found = this.filesInArcs();
|
||||
assertEquals("wrong files in ARCs",EXPECTED,found);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startHttpServer() throws Exception {
|
||||
Server server = new Server();
|
||||
|
||||
SocketConnector sc = new SocketConnector();
|
||||
sc.setHost("127.0.0.1");
|
||||
sc.setPort(7777);
|
||||
server.addConnector(sc);
|
||||
ResourceHandler rhandler = new ResourceHandler();
|
||||
rhandler.setResourceBase(getSrcHtdocs().getAbsolutePath());
|
||||
|
||||
ServletHandler servletHandler = new ServletHandler();
|
||||
|
||||
HandlerList handlers = new HandlerList();
|
||||
handlers.setHandlers(new Handler[] {
|
||||
rhandler,
|
||||
servletHandler,
|
||||
new DefaultHandler() });
|
||||
server.setHandler(handlers);
|
||||
|
||||
ServletHolder holder = new ServletHolder(new FormAuthServlet());
|
||||
servletHandler.addServletWithMapping(holder, "/login/*");
|
||||
|
||||
this.httpServer = server;
|
||||
this.httpServer.start();
|
||||
}
|
||||
|
||||
protected String getSeedsString() {
|
||||
return "http://127.0.0.1:7777/index.html";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String changeGlobalConfig(String config) {
|
||||
String formLoginConfig =
|
||||
" <bean id='extractorForms' class='org.archive.modules.forms.ExtractorHTMLForms'/>\n"
|
||||
+ " <bean id='formFiller' class='org.archive.modules.forms.FormLoginProcessor'>\n"
|
||||
+ " <property name='loginUsername' value='Mr. Happy Pants' />\n"
|
||||
+ " <property name='loginPassword' value='xyzzy' />\n"
|
||||
+ " </bean>\n";
|
||||
config = config.replace("<!--@@MORE_EXTRACTORS@@-->", formLoginConfig);
|
||||
return super.changeGlobalConfig(config);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<a href="index.html">index</a>
|
||||
|
||||
<a href="link1.html">Link 1</a>
|
||||
|
||||
<a href="link2.html"> Link 2</a>
|
||||
|
||||
<a href="link3.html"> Link 3</a>
|
||||
|
||||
<a href="basic/index.html">Secure</a>
|
||||
@@ -0,0 +1,5 @@
|
||||
<form action="login/login.html" method="post">
|
||||
<input type="text" name="username"/>
|
||||
<input type="password" name="password"/>
|
||||
</form>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<a href="index.html">index</a>
|
||||
|
||||
<a href="link1.html">Link 1</a>
|
||||
|
||||
<a href="link2.html"> Link 2</a>
|
||||
|
||||
<a href="link3.html"> Link 3</a>
|
||||
@@ -0,0 +1,7 @@
|
||||
<a href="index.html">index</a>
|
||||
|
||||
<a href="link1.html">Link 1</a>
|
||||
|
||||
<a href="link2.html"> Link 2</a>
|
||||
|
||||
<a href="link3.html"> Link 3</a>
|
||||
@@ -0,0 +1,7 @@
|
||||
<a href="index.html">index</a>
|
||||
|
||||
<a href="link1.html">Link 1</a>
|
||||
|
||||
<a href="link2.html"> Link 2</a>
|
||||
|
||||
<a href="link3.html"> Link 3</a>
|
||||
@@ -0,0 +1,2 @@
|
||||
<a href="index.html">index</a>
|
||||
|
||||
@@ -124,6 +124,7 @@ crawlController.pauseAtStart=false
|
||||
<ref bean="extractorCss"/>
|
||||
<ref bean="extractorJs"/>
|
||||
<ref bean="extractorSwf"/>
|
||||
<!--@@MORE_EXTRACTORS@@-->
|
||||
<ref bean="arcWriterProcessor"/>
|
||||
</list>
|
||||
</property>
|
||||
|
||||
@@ -64,6 +64,7 @@ import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.AbstractExecutionAwareRequest;
|
||||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
import org.apache.http.config.ConnectionConfig;
|
||||
import org.apache.http.config.MessageConstraints;
|
||||
import org.apache.http.config.Registry;
|
||||
@@ -79,6 +80,8 @@ import org.apache.http.conn.socket.PlainConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.entity.ContentLengthStrategy;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.DefaultBHttpClientConnection;
|
||||
import org.apache.http.impl.client.BasicAuthCache;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
@@ -93,6 +96,7 @@ import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.http.protocol.HTTP;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.util.Args;
|
||||
import org.archive.modules.CoreAttributeConstants;
|
||||
import org.archive.modules.CrawlURI;
|
||||
import org.archive.modules.CrawlURI.FetchType;
|
||||
import org.archive.modules.Processor;
|
||||
@@ -175,8 +179,16 @@ class FetchHTTPRequest {
|
||||
}
|
||||
|
||||
if (curi.getFetchType() == FetchType.HTTP_POST) {
|
||||
this.request = new BasicExecutionAwareEntityEnclosingRequest("POST",
|
||||
requestLineUri, httpVersion);
|
||||
BasicExecutionAwareEntityEnclosingRequest postRequest = new BasicExecutionAwareEntityEnclosingRequest(
|
||||
"POST", requestLineUri, httpVersion);
|
||||
this.request = postRequest;
|
||||
String submitData = (String) curi.getData().get(CoreAttributeConstants.A_SUBMIT_DATA);
|
||||
if (submitData != null) {
|
||||
// XXX brittle, doesn't support multipart form data etc
|
||||
ContentType contentType = ContentType.create(URLEncodedUtils.CONTENT_TYPE, "UTF-8");
|
||||
StringEntity formEntity = new StringEntity(submitData, contentType);
|
||||
postRequest.setEntity(formEntity);
|
||||
}
|
||||
} else {
|
||||
this.request = new BasicExecutionAwareRequest("GET",
|
||||
requestLineUri, httpVersion);
|
||||
@@ -196,7 +208,7 @@ class FetchHTTPRequest {
|
||||
this.addedCredentials = populateTargetCredential();
|
||||
populateHttpProxyCredential();
|
||||
}
|
||||
|
||||
|
||||
protected void configureRequestHeaders() {
|
||||
if (fetcher.getAcceptCompression()) {
|
||||
request.addHeader("Accept-Encoding", "gzip,deflate");
|
||||
|
||||
@@ -21,14 +21,11 @@ package org.archive.modules.forms;
|
||||
|
||||
import static org.archive.modules.CoreAttributeConstants.A_WARC_RESPONSE_HEADERS;
|
||||
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import org.apache.commons.httpclient.URIException;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.archive.checkpointing.Checkpointable;
|
||||
@@ -45,6 +42,10 @@ import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
|
||||
/**
|
||||
* A step, post-ExtractorHTMLForms, where a followup CrawlURI to
|
||||
* attempt a form submission may be synthesized.
|
||||
@@ -119,24 +120,24 @@ public class FormLoginProcessor extends Processor implements Checkpointable {
|
||||
Logger.getLogger(FormLoginProcessor.class.getName());
|
||||
|
||||
// formProvince (String) -> count
|
||||
ConcurrentMap<String, AtomicLong> eligibleFormsSeenCount =
|
||||
protected LoadingCache<String, AtomicLong> eligibleFormsSeenCount =
|
||||
CacheBuilder.newBuilder()
|
||||
.<String, AtomicLong>build(
|
||||
new CacheLoader<String, AtomicLong>() {
|
||||
public AtomicLong load(String arg0) {
|
||||
return new AtomicLong(0L);
|
||||
}
|
||||
}).asMap();
|
||||
});
|
||||
|
||||
// formProvince (String) -> count
|
||||
ConcurrentMap<String, AtomicLong> eligibleFormsAttemptsCount =
|
||||
protected LoadingCache<String, AtomicLong> eligibleFormsAttemptsCount =
|
||||
CacheBuilder.newBuilder()
|
||||
.<String, AtomicLong>build(
|
||||
new CacheLoader<String, AtomicLong>() {
|
||||
public AtomicLong load(String arg0) {
|
||||
return new AtomicLong(0L);
|
||||
}
|
||||
}).asMap();
|
||||
});
|
||||
|
||||
/**
|
||||
* SURT prefix against which configured username/password is
|
||||
@@ -219,13 +220,17 @@ public class FormLoginProcessor extends Processor implements Checkpointable {
|
||||
for( Object formObject : curi.getDataList(ExtractorHTMLForms.A_HTML_FORM_OBJECTS)) {
|
||||
HTMLForm form = (HTMLForm) formObject;
|
||||
if(form.seemsLoginForm()) {
|
||||
eligibleFormsSeenCount.get(formProvince).incrementAndGet();
|
||||
if(eligibleFormsAttemptsCount.get(formProvince).get()<1) {
|
||||
eligibleFormsAttemptsCount.get(formProvince).incrementAndGet();
|
||||
createFormSubmissionAttempt(curi,form,formProvince);
|
||||
} else {
|
||||
// note decline-to-submit: in volume, may be signal of failed first login
|
||||
curi.getAnnotations().add("nosubmit:"+submitStatusFor(formProvince));
|
||||
try {
|
||||
eligibleFormsSeenCount.get(formProvince).incrementAndGet();
|
||||
if(eligibleFormsAttemptsCount.get(formProvince).get()<1) {
|
||||
eligibleFormsAttemptsCount.get(formProvince).incrementAndGet();
|
||||
createFormSubmissionAttempt(curi,form,formProvince);
|
||||
} else {
|
||||
// note decline-to-submit: in volume, may be signal of failed first login
|
||||
curi.getAnnotations().add("nosubmit:"+submitStatusFor(formProvince));
|
||||
}
|
||||
} catch (ExecutionException e) {
|
||||
throw new RuntimeException(e); // can't happen?
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -260,10 +265,9 @@ public class FormLoginProcessor extends Processor implements Checkpointable {
|
||||
submitCuri.setFetchType(FetchType.HTTP_POST);
|
||||
submitCuri.getData().put(
|
||||
CoreAttributeConstants.A_SUBMIT_DATA,
|
||||
templateForm.asHttpClientDataWith(
|
||||
templateForm.asFormDataString(
|
||||
getLoginUsername(),
|
||||
getLoginPassword()));
|
||||
//submitCuri.setSchedulingDirective(Math.max(curi.getSchedulingDirective()-1, 0));
|
||||
submitCuri.setSchedulingDirective(SchedulingConstants.HIGH);
|
||||
submitCuri.setForceFetch(true);
|
||||
curi.getOutCandidates().add(submitCuri);
|
||||
@@ -278,9 +282,13 @@ public class FormLoginProcessor extends Processor implements Checkpointable {
|
||||
}
|
||||
|
||||
protected String submitStatusFor(String formProvince) {
|
||||
return eligibleFormsAttemptsCount.get(formProvince).get()
|
||||
+","+eligibleFormsSeenCount.get(formProvince).get()
|
||||
+","+formProvince;
|
||||
try {
|
||||
return eligibleFormsAttemptsCount.get(formProvince).get()
|
||||
+","+eligibleFormsSeenCount.get(formProvince).get()
|
||||
+","+formProvince;
|
||||
} catch (ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -295,10 +303,10 @@ public class FormLoginProcessor extends Processor implements Checkpointable {
|
||||
protected void fromCheckpointJson(JSONObject json) throws JSONException {
|
||||
super.fromCheckpointJson(json);
|
||||
JSONUtils.putAllAtomicLongs(
|
||||
eligibleFormsAttemptsCount,
|
||||
eligibleFormsAttemptsCount.asMap(),
|
||||
json.getJSONObject("eligibleFormsAttemptsCount"));
|
||||
JSONUtils.putAllAtomicLongs(
|
||||
eligibleFormsSeenCount,
|
||||
eligibleFormsSeenCount.asMap(),
|
||||
json.getJSONObject("eligibleFormsSeenCount"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,12 @@
|
||||
package org.archive.modules.forms;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.httpclient.NameValuePair;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.archive.util.TextUtils;
|
||||
|
||||
/**
|
||||
* Simple representation of a discovered HTML Form.
|
||||
@@ -104,6 +106,7 @@ public class HTMLForm {
|
||||
* @param username
|
||||
* @param password
|
||||
* @return
|
||||
* @deprecated specific to a particular FetchHTTP implementation based on commons-httpclient, use {@link #asFormDataString(String, String)}
|
||||
*/
|
||||
public NameValuePair[] asHttpClientDataWith(String username, String password) {
|
||||
ArrayList<NameValuePair> data = new ArrayList<NameValuePair>(allInputs.size());
|
||||
@@ -119,6 +122,22 @@ public class HTMLForm {
|
||||
}
|
||||
return data.toArray(new NameValuePair[data.size()]);
|
||||
}
|
||||
|
||||
public String asFormDataString(String username, String password) {
|
||||
List<String> nameVals = new LinkedList<String>();
|
||||
|
||||
for (FormInput input : allInputs) {
|
||||
if(input == candidateUsernameInputs.get(0)) {
|
||||
nameVals.add(TextUtils.urlEscape(input.name) + "=" + TextUtils.urlEscape(username));
|
||||
} else if(input == candidatePasswordInputs.get(0)) {
|
||||
nameVals.add(TextUtils.urlEscape(input.name) + "=" + TextUtils.urlEscape(password));
|
||||
} else if (StringUtils.isNotEmpty(input.name) && StringUtils.isNotEmpty(input.value)) {
|
||||
nameVals.add(TextUtils.urlEscape(input.name) + "=" + TextUtils.urlEscape(input.value));
|
||||
}
|
||||
}
|
||||
|
||||
return StringUtils.join(nameVals, '&');
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
+28
@@ -20,12 +20,19 @@ package org.archive.state;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.commons.httpclient.URIException;
|
||||
import org.apache.commons.lang.SerializationUtils;
|
||||
import org.archive.modules.CrawlURI;
|
||||
import org.archive.net.UURI;
|
||||
import org.archive.net.UURIFactory;
|
||||
import org.archive.util.Recorder;
|
||||
import org.archive.util.TmpDirTestCase;
|
||||
|
||||
|
||||
/**
|
||||
@@ -213,4 +220,25 @@ public abstract class ModuleTestBase extends TestCase {
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected Recorder getRecorder() throws IOException {
|
||||
if (Recorder.getHttpRecorder() == null) {
|
||||
Recorder httpRecorder = new Recorder(TmpDirTestCase.tmpDir(),
|
||||
getClass().getName(), 16 * 1024, 512 * 1024);
|
||||
Recorder.setHttpRecorder(httpRecorder);
|
||||
}
|
||||
|
||||
return Recorder.getHttpRecorder();
|
||||
}
|
||||
|
||||
|
||||
protected CrawlURI makeCrawlURI(String uri) throws URIException,
|
||||
IOException {
|
||||
UURI uuri = UURIFactory.getInstance(uri);
|
||||
CrawlURI curi = new CrawlURI(uuri);
|
||||
curi.setSeed(true);
|
||||
curi.setRecorder(getRecorder());
|
||||
return curi;
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
@@ -52,8 +53,12 @@ import javax.net.ssl.SSLException;
|
||||
|
||||
import org.apache.commons.httpclient.URIException;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.NoHttpResponseException;
|
||||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.archive.httpclient.ConfigurableX509TrustManager.TrustLevel;
|
||||
import org.archive.modules.CoreAttributeConstants;
|
||||
import org.archive.modules.CrawlMetadata;
|
||||
import org.archive.modules.CrawlURI;
|
||||
import org.archive.modules.CrawlURI.FetchType;
|
||||
@@ -62,9 +67,6 @@ import org.archive.modules.credential.HttpAuthenticationCredential;
|
||||
import org.archive.modules.deciderules.RejectDecideRule;
|
||||
import org.archive.modules.recrawl.FetchHistoryProcessor;
|
||||
import org.archive.net.UURI;
|
||||
import org.archive.net.UURIFactory;
|
||||
import org.archive.util.Recorder;
|
||||
import org.archive.util.TmpDirTestCase;
|
||||
import org.jboss.netty.handler.codec.http.HttpRequest;
|
||||
import org.littleshoot.proxy.DefaultHttpProxyServer;
|
||||
import org.littleshoot.proxy.HttpFilter;
|
||||
@@ -94,25 +96,6 @@ public class FetchHTTPTests extends ProcessorTestBase {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
protected Recorder getRecorder() throws IOException {
|
||||
if (Recorder.getHttpRecorder() == null) {
|
||||
Recorder httpRecorder = new Recorder(TmpDirTestCase.tmpDir(),
|
||||
getClass().getName(), 16 * 1024, 512 * 1024);
|
||||
Recorder.setHttpRecorder(httpRecorder);
|
||||
}
|
||||
|
||||
return Recorder.getHttpRecorder();
|
||||
}
|
||||
|
||||
protected CrawlURI makeCrawlURI(String uri) throws URIException,
|
||||
IOException {
|
||||
UURI uuri = UURIFactory.getInstance(uri);
|
||||
CrawlURI curi = new CrawlURI(uuri);
|
||||
curi.setSeed(true);
|
||||
curi.setRecorder(getRecorder());
|
||||
return curi;
|
||||
}
|
||||
|
||||
protected void runDefaultChecks(CrawlURI curi, String... exclusionsArray)
|
||||
throws IOException, UnsupportedEncodingException {
|
||||
|
||||
@@ -130,7 +113,9 @@ public class FetchHTTPTests extends ProcessorTestBase {
|
||||
if (!exclusions.contains("hostHeader")) {
|
||||
assertTrue(requestString.contains("Host: localhost:7777\r\n"));
|
||||
}
|
||||
assertTrue(requestString.endsWith("\r\n\r\n"));
|
||||
if (!exclusions.contains("trailingCRLFCRLF")) {
|
||||
assertTrue(requestString.endsWith("\r\n\r\n"));
|
||||
}
|
||||
|
||||
// check sizes
|
||||
assertEquals(DEFAULT_PAYLOAD_STRING.length(), curi.getContentLength());
|
||||
@@ -147,7 +132,9 @@ public class FetchHTTPTests extends ProcessorTestBase {
|
||||
if (!exclusions.contains("fetchStatus")) {
|
||||
assertTrue(curi.getFetchStatus() == 200);
|
||||
}
|
||||
assertTrue(curi.getFetchType() == FetchType.HTTP_GET);
|
||||
if (!exclusions.contains("fetchTypeGET")) {
|
||||
assertTrue(curi.getFetchType() == FetchType.HTTP_GET);
|
||||
}
|
||||
|
||||
// check message body, i.e. "raw, possibly chunked-transfer-encoded message contents not including the leading headers"
|
||||
assertEquals(DEFAULT_PAYLOAD_STRING, messageBodyString(curi));
|
||||
@@ -703,8 +690,9 @@ public class FetchHTTPTests extends ProcessorTestBase {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
ServerSocket listeningSocket = null;
|
||||
try {
|
||||
ServerSocket listeningSocket = new ServerSocket(listenPort, 0, Inet4Address.getByName(listenAddress));
|
||||
listeningSocket = new ServerSocket(listenPort, 0, Inet4Address.getByName(listenAddress));
|
||||
listeningSocket.setSoTimeout(600);
|
||||
while (!isTimeToBeDone) {
|
||||
try {
|
||||
@@ -718,6 +706,12 @@ public class FetchHTTPTests extends ProcessorTestBase {
|
||||
// logger.warning("caught exception: " + e);
|
||||
} finally {
|
||||
// logger.info("all done suckers");
|
||||
if (listeningSocket != null) {
|
||||
try {
|
||||
listeningSocket.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -829,6 +823,26 @@ public class FetchHTTPTests extends ProcessorTestBase {
|
||||
fetcher().process(curi);
|
||||
assertTrue(httpRequestString(curi).contains("Host: example.com\r\n"));
|
||||
}
|
||||
|
||||
public void testHttpPost() throws Exception {
|
||||
CrawlURI curi = makeCrawlURI("http://localhost:7777/");
|
||||
curi.setFetchType(FetchType.HTTP_POST);
|
||||
|
||||
List<NameValuePair> params = new LinkedList<NameValuePair>();
|
||||
params.add(new BasicNameValuePair("name1", "value1"));
|
||||
params.add(new BasicNameValuePair("name1", "value2"));
|
||||
params.add(new BasicNameValuePair("funky name 2", "whoa crazy\t && 🍺 🍻 \n crazier \rooo"));
|
||||
String submitData = URLEncodedUtils.format(params, "UTF-8");
|
||||
assertEquals("name1=value1&name1=value2&funky+name+2=whoa+crazy%09+%26%26+%F0%9F%8D%BA+%F0%9F%8D%BB+%0A+crazier+%0Dooo", submitData);
|
||||
|
||||
curi.getData().put(CoreAttributeConstants.A_SUBMIT_DATA, submitData);
|
||||
fetcher().process(curi);
|
||||
|
||||
assertTrue(httpRequestString(curi).startsWith("POST / HTTP/1.0\r\n"));
|
||||
assertTrue(httpRequestString(curi).endsWith("\r\n\r\nname1=value1&name1=value2&funky+name+2=whoa+crazy%09+%26%26+%F0%9F%8D%BA+%F0%9F%8D%BB+%0A+crazier+%0Dooo"));
|
||||
assertEquals(FetchType.HTTP_POST, curi.getFetchType());
|
||||
runDefaultChecks(curi, "requestLine", "trailingCRLFCRLF", "fetchTypeGET");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FetchHTTP makeModule() throws IOException {
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* This file is part of the Heritrix web crawler (crawler.archive.org).
|
||||
*
|
||||
* Licensed to the Internet Archive (IA) by one or more individual
|
||||
* contributors.
|
||||
*
|
||||
* The IA licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.archive.modules.forms;
|
||||
|
||||
import static org.archive.modules.CoreAttributeConstants.A_WARC_RESPONSE_HEADERS;
|
||||
|
||||
import org.apache.commons.httpclient.NameValuePair;
|
||||
import org.apache.commons.httpclient.util.EncodingUtil;
|
||||
import org.archive.modules.CoreAttributeConstants;
|
||||
import org.archive.modules.CrawlURI;
|
||||
import org.archive.modules.ProcessorTestBase;
|
||||
import org.archive.modules.CrawlURI.FetchType;
|
||||
import org.archive.modules.forms.FormLoginProcessor;
|
||||
|
||||
public class FormLoginProcessorTest extends ProcessorTestBase {
|
||||
|
||||
public void testNoFormLogin() throws Exception {
|
||||
CrawlURI curi = makeCrawlURI("http://example.com/");
|
||||
|
||||
FormLoginProcessor p = (FormLoginProcessor) makeModule();
|
||||
p.setLoginUsername("jdoe");
|
||||
p.setLoginPassword("********");
|
||||
p.setApplicableSurtPrefix("http://(com,example,)");
|
||||
|
||||
p.process(curi);
|
||||
|
||||
assertEquals(1, curi.getDataList(A_WARC_RESPONSE_HEADERS).size());
|
||||
assertEquals("WARC-Simple-Form-Province-Status: 0,0,http://(com,example,)", curi.getDataList(A_WARC_RESPONSE_HEADERS).get(0));
|
||||
}
|
||||
|
||||
public void testFormLogin() throws Exception {
|
||||
CrawlURI curi = makeCrawlURI("http://example.com/");
|
||||
|
||||
HTMLForm form = new HTMLForm();
|
||||
form.addField("text", "username-form-field", "");
|
||||
form.addField("password", "password-form-field", "");
|
||||
form.setMethod("post");
|
||||
form.setAction("/login");
|
||||
curi.getDataList(ExtractorHTMLForms.A_HTML_FORM_OBJECTS).add(form);
|
||||
|
||||
FormLoginProcessor p = (FormLoginProcessor) makeModule();
|
||||
p.setLoginUsername("jdoe");
|
||||
p.setLoginPassword("********");
|
||||
p.setApplicableSurtPrefix("http://(com,example,)");
|
||||
|
||||
p.process(curi);
|
||||
assertEquals(1, curi.getDataList(A_WARC_RESPONSE_HEADERS).size());
|
||||
assertEquals("WARC-Simple-Form-Province-Status: 0,0,http://(com,example,)", curi.getDataList(A_WARC_RESPONSE_HEADERS).get(0));
|
||||
assertTrue(curi.getAnnotations().contains("submit:/login"));
|
||||
|
||||
assertEquals(1, curi.getOutCandidates().size());
|
||||
CrawlURI submitCuri = curi.getOutCandidates().toArray(new CrawlURI[0])[0];
|
||||
assertEquals("http://example.com/login", submitCuri.toString());
|
||||
assertEquals(FetchType.HTTP_POST, submitCuri.getFetchType());
|
||||
NameValuePair[] queryParams = (NameValuePair[]) submitCuri.getData().get(CoreAttributeConstants.A_SUBMIT_DATA);
|
||||
String queryString = EncodingUtil.formUrlEncode(queryParams, "UTF-8");
|
||||
assertEquals("username-form-field=jdoe&password-form-field=********", queryString);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user