Skip to content

Commit 9cdb6ea

Browse files
author
Lakshitha Gunasekara
authored
Merge pull request #216 from RAVEENSR/master
Fix not honouring the non Proxy ports
2 parents 78cb059 + af3ac87 commit 9cdb6ea

File tree

1 file changed

+202
-8
lines changed

1 file changed

+202
-8
lines changed

components/hostobjects/org.jaggeryjs.hostobjects.xhr/src/main/java/org/jaggeryjs/hostobjects/xhr/XMLHttpRequestHostObject.java

Lines changed: 202 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.util.ArrayList;
3737
import java.util.List;
3838
import java.util.Map;
39+
import java.util.StringTokenizer;
3940
import java.util.concurrent.Callable;
4041
import java.util.concurrent.ExecutorService;
4142
import java.util.concurrent.Executors;
@@ -66,6 +67,9 @@ public class XMLHttpRequestHostObject extends ScriptableObject {
6667
private Function onreadystatechange;
6768

6869
private static final String hostObjectName = "XMLHttpRequest";
70+
protected static final String HTTP_PROXY_HOST = "http.proxyHost";
71+
protected static final String HTTP_PROXY_PORT = "http.proxyPort";
72+
protected static final String HTTP_NON_PROXY_HOSTS = "http.nonProxyHosts";
6973

7074
private Context context = null;
7175

@@ -91,10 +95,6 @@ public class XMLHttpRequestHostObject extends ScriptableObject {
9195

9296
public XMLHttpRequestHostObject() {
9397
httpClient = new HttpClient(new MultiThreadedHttpConnectionManager());
94-
ProxyHost proxyConfig = getProxyConfig();
95-
if (proxyConfig != null) {
96-
httpClient.getHostConfiguration().setProxyHost(proxyConfig);
97-
}
9898
}
9999

100100
@Override
@@ -552,6 +552,9 @@ public Object call() throws Exception {
552552

553553
private static void executeRequest(Context cx, XMLHttpRequestHostObject xhr) throws ScriptException {
554554
try {
555+
String host = xhr.method.getURI().getHost();
556+
ProxyHost proxyHost = getProxyConfig(host);
557+
xhr.httpClient.getHostConfiguration().setProxyHost(proxyHost);
555558
xhr.httpClient.executeMethod(xhr.method);
556559
xhr.statusLine = xhr.method.getStatusLine();
557560
xhr.responseHeaders = xhr.method.getResponseHeaders();
@@ -594,12 +597,17 @@ private static boolean isInvalidHeader(String header) {
594597
return false;
595598
}
596599

597-
private ProxyHost getProxyConfig() {
600+
private static ProxyHost getProxyConfig(String host) {
598601

599602
ProxyHost proxyConfig = null;
600603

601-
String proxyHost = System.getProperty("http.proxyHost");
602-
String proxyPortStr = System.getProperty("http.proxyPort");
604+
String proxyHost = System.getProperty(HTTP_PROXY_HOST);
605+
String proxyPortStr = System.getProperty(HTTP_PROXY_PORT);
606+
String nonProxyHosts = System.getProperty(HTTP_NON_PROXY_HOSTS);
607+
608+
if (isHostInNonProxyList(host, nonProxyHosts)) {
609+
return null;
610+
}
603611

604612
int proxyPort = -1;
605613
if (proxyHost != null) {
@@ -621,4 +629,190 @@ private ProxyHost getProxyConfig() {
621629
return proxyConfig;
622630
}
623631

624-
}
632+
/**
633+
* Check if the specified host is in the list of non proxy hosts.
634+
*
635+
* @param host host name
636+
* @param nonProxyHosts string containing the list of non proxy hosts
637+
* @return true/false
638+
*/
639+
public static boolean isHostInNonProxyList(String host, String nonProxyHosts) {
640+
if ((nonProxyHosts == null) || (host == null)) {
641+
return false;
642+
}
643+
644+
/*
645+
* The http.nonProxyHosts system property is a list enclosed in
646+
* double quotes with items separated by a vertical bar.
647+
*/
648+
StringTokenizer tokenizer = new StringTokenizer(nonProxyHosts, "|\"");
649+
650+
while (tokenizer.hasMoreTokens()) {
651+
String pattern = tokenizer.nextToken();
652+
if (match(pattern, host, false)) {
653+
return true;
654+
}
655+
}
656+
return false;
657+
}
658+
659+
/**
660+
* Matches a string against a pattern. The pattern contains two special
661+
* characters:
662+
* '*' which means zero or more characters,
663+
*
664+
* @param pattern the (non-null) pattern to match against
665+
* @param str the (non-null) string that must be matched against the
666+
* pattern
667+
* @param isCaseSensitive
668+
* @return <code>true</code> when the string matches against the pattern,
669+
* <code>false</code> otherwise.
670+
*/
671+
private static boolean match(String pattern, String str, boolean isCaseSensitive) {
672+
673+
char[] patArr = pattern.toCharArray();
674+
char[] strArr = str.toCharArray();
675+
int patIdxStart = 0;
676+
int patIdxEnd = patArr.length - 1;
677+
int strIdxStart = 0;
678+
int strIdxEnd = strArr.length - 1;
679+
char ch;
680+
boolean containsStar = false;
681+
682+
for (int i = 0; i < patArr.length; i++) {
683+
if (patArr[i] == '*') {
684+
containsStar = true;
685+
break;
686+
}
687+
}
688+
if (!containsStar) {
689+
690+
// No '*'s, so we make a shortcut
691+
if (patIdxEnd != strIdxEnd) {
692+
return false; // Pattern and string do not have the same size
693+
}
694+
for (int i = 0; i <= patIdxEnd; i++) {
695+
ch = patArr[i];
696+
if (isCaseSensitive && (ch != strArr[i])) {
697+
return false; // Character mismatch
698+
}
699+
if (!isCaseSensitive
700+
&& (Character.toUpperCase(ch)
701+
!= Character.toUpperCase(strArr[i]))) {
702+
return false; // Character mismatch
703+
}
704+
}
705+
return true; // String matches against pattern
706+
}
707+
if (patIdxEnd == 0) {
708+
return true; // Pattern contains only '*', which matches anything
709+
}
710+
711+
// Process characters before first star
712+
while ((ch = patArr[patIdxStart]) != '*' && (strIdxStart <= strIdxEnd)) {
713+
if (isCaseSensitive && (ch != strArr[strIdxStart])) {
714+
return false; // Character mismatch
715+
}
716+
if (!isCaseSensitive
717+
&& (Character.toUpperCase(ch)
718+
!= Character.toUpperCase(strArr[strIdxStart]))) {
719+
return false; // Character mismatch
720+
}
721+
patIdxStart++;
722+
strIdxStart++;
723+
}
724+
if (strIdxStart > strIdxEnd) {
725+
726+
// All characters in the string are used. Check if only '*'s are
727+
// left in the pattern. If so, we succeeded. Otherwise failure.
728+
for (int i = patIdxStart; i <= patIdxEnd; i++) {
729+
if (patArr[i] != '*') {
730+
return false;
731+
}
732+
}
733+
return true;
734+
}
735+
736+
// Process characters after last star
737+
while ((ch = patArr[patIdxEnd]) != '*' && (strIdxStart <= strIdxEnd)) {
738+
if (isCaseSensitive && (ch != strArr[strIdxEnd])) {
739+
return false; // Character mismatch
740+
}
741+
if (!isCaseSensitive
742+
&& (Character.toUpperCase(ch)
743+
!= Character.toUpperCase(strArr[strIdxEnd]))) {
744+
return false; // Character mismatch
745+
}
746+
patIdxEnd--;
747+
strIdxEnd--;
748+
}
749+
if (strIdxStart > strIdxEnd) {
750+
751+
// All characters in the string are used. Check if only '*'s are
752+
// left in the pattern. If so, we succeeded. Otherwise failure.
753+
for (int i = patIdxStart; i <= patIdxEnd; i++) {
754+
if (patArr[i] != '*') {
755+
return false;
756+
}
757+
}
758+
return true;
759+
}
760+
761+
// process pattern between stars. padIdxStart and patIdxEnd point
762+
// always to a '*'.
763+
while ((patIdxStart != patIdxEnd) && (strIdxStart <= strIdxEnd)) {
764+
int patIdxTmp = -1;
765+
766+
for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
767+
if (patArr[i] == '*') {
768+
patIdxTmp = i;
769+
break;
770+
}
771+
}
772+
if (patIdxTmp == patIdxStart + 1) {
773+
774+
// Two stars next to each other, skip the first one.
775+
patIdxStart++;
776+
continue;
777+
}
778+
779+
// Find the pattern between padIdxStart & padIdxTmp in str between
780+
// strIdxStart & strIdxEnd
781+
int patLength = (patIdxTmp - patIdxStart - 1);
782+
int strLength = (strIdxEnd - strIdxStart + 1);
783+
int foundIdx = -1;
784+
785+
strLoop:
786+
for (int i = 0; i <= strLength - patLength; i++) {
787+
for (int j = 0; j < patLength; j++) {
788+
ch = patArr[patIdxStart + j + 1];
789+
if (isCaseSensitive
790+
&& (ch != strArr[strIdxStart + i + j])) {
791+
continue strLoop;
792+
}
793+
if (!isCaseSensitive && (Character
794+
.toUpperCase(ch) != Character
795+
.toUpperCase(strArr[strIdxStart + i + j]))) {
796+
continue strLoop;
797+
}
798+
}
799+
foundIdx = strIdxStart + i;
800+
break;
801+
}
802+
if (foundIdx == -1) {
803+
return false;
804+
}
805+
patIdxStart = patIdxTmp;
806+
strIdxStart = foundIdx + patLength;
807+
}
808+
809+
// All characters in the string are used. Check if only '*'s are left
810+
// in the pattern. If so, we succeeded. Otherwise failure.
811+
for (int i = patIdxStart; i <= patIdxEnd; i++) {
812+
if (patArr[i] != '*') {
813+
return false;
814+
}
815+
}
816+
return true;
817+
}
818+
}

0 commit comments

Comments
 (0)