3636import java .util .ArrayList ;
3737import java .util .List ;
3838import java .util .Map ;
39+ import java .util .StringTokenizer ;
3940import java .util .concurrent .Callable ;
4041import java .util .concurrent .ExecutorService ;
4142import 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