diff --git a/htroot/SettingsAck_p.html b/htroot/SettingsAck_p.html
index 43e5f7a8d..da82012ec 100644
--- a/htroot/SettingsAck_p.html
+++ b/htroot/SettingsAck_p.html
@@ -30,8 +30,8 @@ Your new administration account name is #[user]#. The password has been accepted
::
Your proxy access setting has been changed.
Your proxy account check has been disabled, since you did not supply a password.
- The new proxy IP filter is set to #[filter]#
- The proxy port is: #[port]#
+ The new proxy IP filter is set to
#(restart)#
::
Port rebinding will be done in a view seconds.
@@ -39,10 +39,10 @@ Your new administration account name is #[user]#. The password has been accepted
#(/restart)#
::
Your proxy access setting has been changed.
- Your new proxy account name is #[user]#. The password has been accepted.
+ Your new proxy account name is
- The new proxy IP filter is set to #[filter]#.
- The proxy port is: #[port]#
+ The new proxy IP filter is set to
#(restart)#
::
Port rebinding will be done in a view seconds.
The new parser settings where changed successfully.
Your proxy networking settings have been changed. Unable to bild the server to the new Port: #[port]# Unable to bild the server to the new Port:
diff --git a/source/de/anomic/server/serverAbstractSwitch.java b/source/de/anomic/server/serverAbstractSwitch.java
index 911cb8ea6..515f12b0b 100644
--- a/source/de/anomic/server/serverAbstractSwitch.java
+++ b/source/de/anomic/server/serverAbstractSwitch.java
@@ -217,6 +217,10 @@ public abstract class serverAbstractSwitch implements serverSwitch {
return dflt;
}
}
+
+ public boolean getConfigBool(String key, boolean dflt) {
+ return Boolean.valueOf(getConfig(key, Boolean.toString(dflt))).booleanValue();
+ }
public Iterator configKeys() {
return configProps.keySet().iterator();
diff --git a/yacy.init b/yacy.init
index 6aef05c16..e103079bb 100644
--- a/yacy.init
+++ b/yacy.init
@@ -534,6 +534,9 @@ isTransparentProxy=false
# Specifies if yacy should use the http connection keep-alive feature
connectionKeepAliveSupport=true
+# Specifies if the proxy should send the via header according to RFC
+proxy.sendViaHeader=true
+
# Configuration options needed to configure server port forwarding
portForwardingEnabled=false
portForwardingUseProxy=false
+ The proxy port is:
@@ -59,8 +59,8 @@ Auto pop-up of the Status page is now enabled
::
You are now permanently online. After a short while you should see the effect on the status page.
::
-The Peer Name is: #[peerName]#
-Your static Ip(or DynDns) is: #[staticIP]#
+The Peer Name is:
+Your static Ip(or DynDns) is:
::
Seed Settings changed.#(success)#::You are now a principal peer.#(/success)#
::
@@ -73,11 +73,11 @@ Please return to the settings page and modify the data.
The new setting is effective immediately, you don't need to re-start.
::
The submitted peer name is already used by another peer. Please choose a different name. The Peer name has not been changed.
-Your Peer Language is: #[peerLang]#
+Your Peer Language is:
::
The submitted peer name is not well-formed. Please choose a different name. The Peer name has not been changed.
Peer names must not contain characters other than (a-z, A-Z, 0-9, '-', '_') and must not be longer than 80 characters.
-Your Peer Language is: #[peerLang]#
+Your Peer Language is:
::
@@ -85,7 +85,10 @@ Parsing of the following mime-types was enabled:
#{parser}#
-
::
@@ -93,19 +96,28 @@ Seed Upload method was changed successfully.
#(success)#::
+#[parserMode]# #[enabledMime]#
+
#{/parser}#
#[parserMode]#
+ #[enabledMime]#
+
You are now a principal peer.#(/success)#
-
-::
+::
-Seed Upload Method: #[seedUploadMethod]#
+Seed File URL: #[seedURL]#
+
+Seed Upload Method:
+ #[seedUploadMethod]#
+
+
Seed File URL:
+ #[seedURL]#
::
@@ -113,15 +125,15 @@ Seed Upload method was changed successfully.
Transparent Proxy Support is:
- #[isTransparentProxy]#
+ #[isTransparentProxy]#
+Connection Keep-Alive Support is:
- #[connectionKeepAliveSupport]#
+ #[connectionKeepAliveSupport]#
+
+
Send via header is:
+ #[proxy.sendViaHeader]#
::
@@ -129,19 +141,19 @@ Seed Upload method was changed successfully.
Message Forwarding Support is:
- #[msgForwardingEnabled]#
+ #[msgForwardingEnabled]#
Message Forwarding Command:
- #[msgForwardingCmd]#
+ #[msgForwardingCmd]#
Recipient Address:
- #[msgForwardingTo]#
+ #[msgForwardingTo]#
::
@@ -154,7 +166,7 @@ You are now event-based online. After a short while you should see the ef
::
You are now in Cache Mode. Only Proxy-cache ist available in this mode. After a short while you should see the effect on the status page.
Port Forwarding Support is:
- #[portForwardingEnabled]#
+ #[portForwardingEnabled]#
Port Forwarding Port:
- #[portForwardingPort]#
+ #[portForwardingPort]#
Port Forwarding Host:
- #[portForwardingHostUser]#@#[portForwardingHost]#:#[portForwardingHostPort]#
+ #[portForwardingHostUser]#@#[portForwardingHost]#:#[portForwardingHostPort]#
Port Forwarding uses proxy:
- #[portForwardingUseProxy]#
+ #[portForwardingUseProxy]#
::
-
+
This values seems not to be a valid port configuration.
#(/info)#
With this you can specify if YaCy should support the HTTP connection keep-alive feature.
+
+
Send Via Header:
+
+ Specifies if the proxy should send the Via http header according to RFC 2616 Sect 14.45.
+
diff --git a/htroot/Settings_p.java b/htroot/Settings_p.java
index 52121b83f..24f10ccca 100644
--- a/htroot/Settings_p.java
+++ b/htroot/Settings_p.java
@@ -116,6 +116,7 @@ public final class Settings_p {
// http networking settings
prop.put("isTransparentProxy", env.getConfig("isTransparentProxy", "false").equals("true") ? 1 : 0);
prop.put("connectionKeepAliveSupport", env.getConfig("connectionKeepAliveSupport", "false").equals("true") ? 1 : 0);
+ prop.put("proxy.sendViaHeader", env.getConfig("proxy.sendViaHeader", "false").equals("true") ? 1 : 0);
// remote port forwarding settings
prop.put("portForwardingEnabled",env.getConfig("portForwardingEnabled","false").equals("true")? 1 : 0);
diff --git a/htroot/env/style.css b/htroot/env/style.css
index 1cb557335..de67cef5a 100644
--- a/htroot/env/style.css
+++ b/htroot/env/style.css
@@ -198,8 +198,15 @@ width: 16px;
}
.ResultDescription {
-color:#4070a0;
-font-style:bold;}
+ color:#4070a0;
+ font-weight:bold;
+}
.ResultDateYBR {
-color:#007050}
+ color:#007050
+}
+
+.settingsValue {
+ color:#556699;
+ font-weight:bold;
+}
diff --git a/source/de/anomic/http/httpHeader.java b/source/de/anomic/http/httpHeader.java
index 1e92a09fb..eb232cc27 100644
--- a/source/de/anomic/http/httpHeader.java
+++ b/source/de/anomic/http/httpHeader.java
@@ -62,6 +62,7 @@ import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.Collator;
+import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
@@ -69,6 +70,7 @@ import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
+import java.util.TimeZone;
import java.util.TreeMap;
import java.util.Vector;
@@ -94,35 +96,52 @@ public final class httpHeader extends TreeMap implements Map {
public static final String ACCEPT = "Accept";
public static final String ACCEPT_CHARSET = "Accept-Charset";
public static final String ACCEPT_LANGUAGE = "Accept-Language";
- public static final String KEEP_ALIVE = "Keep-Alive";
- public static final String USER_AGENT = "User-Agent";
+
+
public static final String HOST = "Host";
+
public static final String CONNECTION = "Connection";
+ public static final String PROXY_CONNECTION = "Proxy-Connection";
+ public static final String KEEP_ALIVE = "Keep-Alive";
+
public static final String REFERER = "Referer";
- public static final String ACCEPT_ENCODING = "Accept-Encoding";
- public static final String CONTENT_LENGTH = "Content-Length";
- public static final String CONTENT_TYPE = "Content-Type";
+ public static final String USER_AGENT = "User-Agent";
+
public static final String AUTHORIZATION = "Authorization";
public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
public static final String PROXY_AUTHORIZATION = "Proxy-Authorization";
public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate";
- public static final String PROXY_CONNECTION = "Proxy-Connection";
+
public static final String DATE = "Date";
public static final String SERVER = "Server";
- public static final String LAST_MODIFIED = "Last-modified";
- public static final String PRAGMA = "Pragma";
+
+ public static final String CONTENT_LENGTH = "Content-Length";
+ public static final String CONTENT_TYPE = "Content-Type";
+ public static final String CONTENT_MD5 = "Content-MD5";
+
public static final String SET_COOKIE = "Set-Cookie";
public static final String SET_COOKIE2 = "Set-Cookie2";
- public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
public static final String COOKIE = "Cookie";
public static final String EXPIRES = "Expires";
+
+
+ public static final String ACCEPT_ENCODING = "Accept-Encoding";
public static final String CONTENT_ENCODING = "Content-Encoding";
+ public static final String TRANSFER_ENCODING = "Transfer-Encoding";
+
+ public static final String ACCEPT_RANGES = "Accept-Ranges";
public static final String CONTENT_RANGE = "Content-Range";
public static final String RANGE = "Range";
+ public static final String IF_RANGE = "If-Range";
+
+ public static final String PRAGMA = "Pragma";
public static final String CACHE_CONTROL = "Cache-Control";
- public static final String TRANSFER_ENCODING = "Transfer-Encoding";
+ public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
+ public static final String LAST_MODIFIED = "Last-modified";
+
public static final String LOCATION = "Location";
public static final String ETAG = "ETag";
+ public static final String VIA = "Via";
public static final String X_CACHE = "X-Cache";
public static final String X_CACHE_LOOKUP = "X-Cache-Lookup";
@@ -360,29 +379,47 @@ public final class httpHeader extends TreeMap implements Map {
private static SimpleDateFormat EMLFormatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss", Locale.US);
public static Date parseHTTPDate(String s) {
- if ((s == null) || (s.length() < 9)) return new Date();
- s = s.trim();
- if (s.charAt(3) == ',') s = s.substring(5).trim(); // we skip the name of the day
- if (s.charAt(9) == ' ') s = s.substring(0, 7) + "20" + s.substring(7); // short year version
- if (s.charAt(2) == ',') s = s.substring(0, 2) + s.substring(3); // ommit comma after day of week
- if ((s.charAt(0) > '9') && (s.length() > 20) && (s.charAt(2) == ' ')) s = s.substring(3);
- if (s.length() > 20) s = s.substring(0, 20).trim(); // truncate remaining, since that must be wrong
+ try {
+ return parseHTTPDate(s,true);
+ } catch (ParseException e) {
+ //System.out.println("ERROR long version parse: " + e.getMessage() + " at position " + e.getErrorOffset());
+ serverLog.logSevere("HTTPC-header", "DATE ERROR (Parse): " + s);
+ return null;
+ } catch (java.lang.NumberFormatException e) {
+ //System.out.println("ERROR long version parse: " + e.getMessage() + " at position " + e.getErrorOffset());
+ serverLog.logSevere("HTTPC-header", "DATE ERROR (NumberFormat): " + s);
+ return null;
+ }
+ }
+
+ public static Date parseHTTPDate(String s,boolean ignoreTimezone) throws ParseException, NumberFormatException {
+
+ SimpleDateFormat formatter = EMLFormatter;
+ if ((s == null) || (s.length() < 9)) return null;
+ s = s.trim();
+ if (s.charAt(3) == ',') s = s.substring(5).trim(); // we skip the name of the day
+ if (s.charAt(9) == ' ') s = s.substring(0, 7) + "20" + s.substring(7); // short year version
+ if (s.charAt(2) == ',') s = s.substring(0, 2) + s.substring(3); // ommit comma after day of week
+ if ((s.charAt(0) > '9') && (s.length() > 20) && (s.charAt(2) == ' ')) s = s.substring(3);
+ if (s.length() > 20) {
+ if (!ignoreTimezone) {
+ formatter = (SimpleDateFormat) formatter.clone();
+ formatter.setTimeZone(TimeZone.getTimeZone(s.substring(20)));
+ }
+ s = s.substring(0, 20).trim(); // truncate remaining, since that must be wrong
+ }
if (s.indexOf("Mrz") > 0) s = s.replaceAll("Mrz", "March");
- try {
- return EMLFormatter.parse(s);
- } catch (java.text.ParseException e) {
- //System.out.println("ERROR long version parse: " + e.getMessage() + " at position " + e.getErrorOffset());
- serverLog.logSevere("HTTPC-header", "DATE ERROR (Parse): " + s);
- return new Date();
- } catch (java.lang.NumberFormatException e) {
- //System.out.println("ERROR long version parse: " + e.getMessage() + " at position " + e.getErrorOffset());
- serverLog.logSevere("HTTPC-header", "DATE ERROR (NumberFormat): " + s);
- return new Date();
- }
+
+ // parsing the date string
+ return formatter.parse(s);
}
private Date headerDate(String kind) {
- if (containsKey(kind)) return new Date(parseHTTPDate((String) get(kind)).getTime());
+ if (containsKey(kind)) {
+ Date parsedDate = parseHTTPDate((String) get(kind));
+ if (parsedDate == null) parsedDate = new Date();
+ return new Date(parsedDate.getTime());
+ }
return null;
}
@@ -406,6 +443,17 @@ public final class httpHeader extends TreeMap implements Map {
return headerDate(httpHeader.IF_MODIFIED_SINCE);
}
+ public Object ifRange() {
+ if (containsKey(httpHeader.IF_RANGE)) {
+ try {
+ Date rangeDate = parseHTTPDate((String) get(httpHeader.IF_RANGE),false);
+ if (rangeDate != null) return new Date(rangeDate.getTime());
+ } catch (Exception e) {}
+ return get(httpHeader.IF_RANGE);
+ }
+ return null;
+ }
+
public long age() {
Date lm = lastModified();
Date sd = date();
diff --git a/source/de/anomic/http/httpdProxyHandler.java b/source/de/anomic/http/httpdProxyHandler.java
index a0530bf64..53225857e 100644
--- a/source/de/anomic/http/httpdProxyHandler.java
+++ b/source/de/anomic/http/httpdProxyHandler.java
@@ -529,6 +529,9 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
// removing hop by hop headers
this.removeHopByHopHeaders(requestHeader);
+ // adding additional headers
+ setViaHeader(requestHeader, httpVer);
+
// send request
res = remote.GET(remotePath, requestHeader);
conProp.put(httpHeader.CONNECTION_PROP_CLIENT_REQUEST_HEADER,requestHeader);
@@ -555,7 +558,7 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
}
res.responseHeader.remove(httpHeader.CONTENT_LENGTH);
}
- }
+ }
// if (((String)requestHeader.get(httpHeader.ACCEPT_ENCODING,"")).indexOf("gzip") != -1) {
// zipped = new GZIPOutputStream((chunked != null) ? chunked : respond);
@@ -606,6 +609,9 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
// remove hop by hop headers
this.removeHopByHopHeaders(res.responseHeader);
+ // adding additional headers
+ setViaHeader(res.responseHeader, res.httpVer);
+
// sending the respond header back to the client
if (chunkedOut != null) {
res.responseHeader.put(httpHeader.TRANSFER_ENCODING, "chunked");
@@ -731,6 +737,9 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
// remove hop by hop headers
this.removeHopByHopHeaders(cachedResponseHeader);
+ // adding additional headers
+ setViaHeader(cachedResponseHeader, httpVer);
+
// replace date field in old header by actual date, this is according to RFC
cachedResponseHeader.put(httpHeader.DATE, httpc.dateString(httpc.nowDate()));
@@ -909,6 +918,9 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
// removing hop by hop headers
this.removeHopByHopHeaders(requestHeader);
+
+ // adding outgoing headers
+ setViaHeader(requestHeader, httpVer);
// open the connection: second is needed for [AS] patch
remote = (yAddress == null) ? newhttpc(host, port, timeout): newhttpc(yAddress, timeout);
@@ -924,6 +936,9 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
// removing hop by hop headers
this.removeHopByHopHeaders(res.responseHeader);
+ // adding outgoing headers
+ setViaHeader(res.responseHeader, res.httpVer);
+
// sending the server respond back to the client
httpd.sendRespondHeader(conProp,respond,httpVer,res.statusCode,res.statusText,res.responseHeader);
} catch (Exception e) {
@@ -995,6 +1010,9 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
// removing hop by hop headers
this.removeHopByHopHeaders(requestHeader);
+ // adding additional headers
+ setViaHeader(requestHeader, httpVer);
+
// sending the request
remote = (yAddress == null) ? newhttpc(host, port, timeout) : newhttpc(yAddress, timeout);
httpc.response res = remote.POST(remotePath, requestHeader, body);
@@ -1027,6 +1045,9 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
// remove hop by hop headers
this.removeHopByHopHeaders(res.responseHeader);
+ // adding additional headers
+ setViaHeader(res.responseHeader, res.httpVer);
+
// sending the respond header back to the client
if (chunked != null) {
res.responseHeader.put(httpHeader.TRANSFER_ENCODING, "chunked");
@@ -1485,6 +1506,24 @@ public final class httpdProxyHandler extends httpdAbstractHandler implements htt
return this.userAgentStr.toString();
}
+ private void setViaHeader(httpHeader header, String httpVer) {
+ if (!switchboard.getConfigBool("proxy.sendViaHeader", true)) return;
+
+ // getting header set by other proxies in the chain
+ StringBuffer viaValue = new StringBuffer();
+ if (header.containsKey(httpHeader.VIA)) viaValue.append((String)header.get(httpHeader.VIA));
+ if (viaValue.length() > 0) viaValue.append(", ");
+
+ // appending info about this peer
+ viaValue
+ .append(httpVer).append(" ")
+ .append(yacyCore.seedDB.mySeed.getName()).append(".yacy ")
+ .append("(YaCy ").append(switchboard.getConfig("vString", "0.0")).append(")");
+
+ // storing header back
+ header.put(httpHeader.VIA, viaValue.toString());
+ }
+
/**
* This function is used to generate a logging message according to the
* squid logging format. Changes will take effect immediately.