@@ -49,6 +49,11 @@ public class SimplePipeRequest extends SimpleRPCRequest {
4949 */
5050 protected static final String PIPE_TYPE_QUERY = "q" ; // "query";
5151
52+ /**
53+ * Type of pipe request: subdomain-query
54+ */
55+ protected static final String PIPE_TYPE_SUBDOMAIN_QUERY = "u" ; // "subdomain-query";
56+
5257 /**
5358 * Type of pipe request: notify
5459 */
@@ -80,6 +85,11 @@ public class SimplePipeRequest extends SimpleRPCRequest {
8085 */
8186 protected static final String FORM_PIPE_TYPE = "t" ; // "pipetype";
8287
88+ /**
89+ * Query key for pipe: pipetype
90+ */
91+ protected static final String FORM_PIPE_DOMAIN = "d" ; // "pipedomain";
92+
8393 /**
8494 * Query key for pipe: pipernd
8595 */
@@ -464,6 +474,24 @@ static void pipeScript(SimplePipeRunnable runnable) { // xss
464474 // only for JavaScript
465475 }
466476
477+ /**
478+ * @param runnable
479+ * @param domain
480+ * @j2sNative
481+ var ifr = document.createElement ("IFRAME");
482+ ifr.style.display = "none";
483+ var pipeKey = runnable.pipeKey;
484+ var spr = net.sf.j2s.ajax.SimplePipeRequest;
485+ var url = runnable.getPipeURL();
486+ ifr.src = url + (url.indexOf('?') != -1 ? "&" : "?")
487+ + spr.constructRequest(pipeKey, spr.PIPE_TYPE_SUBDOMAIN_QUERY, true)
488+ + "&" + spr.FORM_PIPE_DOMAIN + "=" + domain;
489+ document.body.appendChild (ifr);
490+ */
491+ static void pipeSubdomainQuery (SimplePipeRunnable runnable , String domain ) {
492+ // only for JavaScript
493+ }
494+
467495 static void pipeNotify (SimplePipeRunnable runnable ) { // notifier
468496 String url = runnable .getPipeURL ();
469497 loadPipeScript (url + (url .indexOf ('?' ) != -1 ? "&" : "?" )
@@ -504,25 +532,7 @@ public void onLoaded() {
504532 * @j2sNative
505533 * if (window == null || window["net"] == null) return;
506534 */ {}
507- String responseText = pipeRequest .getResponseText ();
508- if (responseText != null ) {
509- String retStr = parseReceived (responseText );
510- if (retStr != null && retStr .length () > 0 ) {
511- String destroyedKey = PIPE_STATUS_DESTROYED ;
512- if (retStr .indexOf (destroyedKey ) == 0 ) {
513- int beginIndex = destroyedKey .length () + 1 ;
514- String pipeKeyStr = retStr .substring (beginIndex , beginIndex + PIPE_KEY_LENGTH );
515- SimplePipeRunnable pipe = SimplePipeHelper .getPipe (pipeKeyStr );
516- if (pipe != null ) {
517- pipe .pipeAlive = false ;
518- pipe .pipeClosed ();
519- SimplePipeHelper .removePipe (pipeKeyStr );
520- }
521- //SimplePipeHelper.removePipe(pipeKeyStr);
522- }
523- }
524- }
525-
535+ onPipeDataReceived (pipeRequest .getResponseText ());
526536 /**
527537 * @j2sNative
528538 * net.sf.j2s.ajax.SimplePipeRequest.lastQueryReceived = true;
@@ -541,6 +551,26 @@ public void onLoaded() {
541551 sendRequest (pipeRequest , pipeMethod , pipeURL , pipeRequestData , async );
542552 }
543553
554+ static void onPipeDataReceived (String responseText ) {
555+ if (responseText != null ) {
556+ String retStr = parseReceived (responseText );
557+ if (retStr != null && retStr .length () > 0 ) {
558+ String destroyedKey = PIPE_STATUS_DESTROYED ;
559+ if (retStr .indexOf (destroyedKey ) == 0 ) {
560+ int beginIndex = destroyedKey .length () + 1 ;
561+ String pipeKeyStr = retStr .substring (beginIndex , beginIndex + PIPE_KEY_LENGTH );
562+ SimplePipeRunnable pipe = SimplePipeHelper .getPipe (pipeKeyStr );
563+ if (pipe != null ) {
564+ pipe .pipeAlive = false ;
565+ pipe .pipeClosed ();
566+ SimplePipeHelper .removePipe (pipeKeyStr );
567+ }
568+ //SimplePipeHelper.removePipe(pipeKeyStr);
569+ }
570+ }
571+ }
572+ }
573+
544574 /**
545575 * Create pipe connection for the SimplePipeRunnable.
546576 * In Java, customized HttpRequest object is used to create Comet connection.
@@ -559,8 +589,11 @@ public void onLoaded() {
559589var pipeKey = runnable.pipeKey;
560590var spr = net.sf.j2s.ajax.SimplePipeRequest;
561591var url = runnable.getPipeURL();
592+ var subdomain = arguments[1];
562593ifr.src = url + (url.indexOf('?') != -1 ? "&" : "?")
563- + spr.constructRequest(pipeKey, spr.PIPE_TYPE_SCRIPT, true);
594+ + spr.constructRequest(pipeKey, spr.PIPE_TYPE_SCRIPT, true)
595+ + (subdomain == null ? ""
596+ : "&" + spr.FORM_PIPE_DOMAIN + "=" + subdomain);
564597document.body.appendChild (ifr);
565598var threadFun = function (pipeFun, key) {
566599 return function () {
@@ -762,12 +795,28 @@ static void ajaxPipe(final SimplePipeRunnable runnable) {
762795 * Here in JavaScript mode, try to detect whether it's in cross site
763796 * script mode or not. In XSS mode, <SCRIPT> is used to make requests.
764797 */
765- boolean isXSS = isXSSMode (runnable .getPipeURL ());
798+ String pipeURL = runnable .getPipeURL ();
799+ boolean isXSS = isXSSMode (pipeURL );
800+ boolean isSubdomain = false ;
801+ if (isXSS ) {
802+ isSubdomain = isSubdomain (pipeURL );
803+ }
766804
767- if (!isXSS && pipeMode == MODE_PIPE_CONTINUUM )
805+ if (( !isXSS || isSubdomain ) && pipeMode == MODE_PIPE_CONTINUUM )
768806 /**
769807 * @j2sNative
770- * net.sf.j2s.ajax.SimplePipeRequest.pipeContinuum (runnable);
808+ * var subdomain = null;
809+ * if (isSubdomain) {
810+ * subdomain = window.location.host;
811+ * if (subdomain != null) {
812+ * var idx = subdomain.indexOf (":");
813+ * if (idx != -1) {
814+ * subdomain = subdomain.substring (0, idx);
815+ * }
816+ * document.domain = subdomain; // set owner iframe's domain
817+ * }
818+ * }
819+ * net.sf.j2s.ajax.SimplePipeRequest.pipeContinuum (runnable, subdomain);
771820 */
772821 {
773822 //pipeQuery(runnable, "continuum");
@@ -779,6 +828,20 @@ public void run() {
779828 } else
780829 /**
781830 * @j2sNative
831+ if (isXSS && isSubdomain
832+ && net.sf.j2s.ajax.SimplePipeRequest.isSubdomainXSSSupported ()) {
833+ var subdomain = null;
834+ subdomain = window.location.host;
835+ if (subdomain != null) {
836+ var idx = subdomain.indexOf (":");
837+ if (idx != -1) {
838+ subdomain = subdomain.substring (0, idx);
839+ }
840+ document.domain = subdomain; // set owner iframe's domain
841+ }
842+ net.sf.j2s.ajax.SimplePipeRequest.pipeSubdomainQuery (runnable, subdomain);
843+ return;
844+ }
782845var spr = net.sf.j2s.ajax.SimplePipeRequest;
783846spr.lastQueryReceived = true;
784847if (spr.queryTimeoutHandle != null) {
@@ -817,4 +880,135 @@ public void run() {
817880 }
818881 }
819882
883+ /**
884+ * For early version of Firefox (<1.5) and Opera (<9.6), subdomain XSS
885+ * query may be unsupported.
886+ *
887+ * @return whether subdomain XSS is supported or not.
888+ *
889+ * @j2sNative
890+ var dua = navigator.userAgent;
891+ var dav = navigator.appVersion;
892+ if (dua.indexOf("Opera") != -1 && parseFloat (dav) < 9.6) {
893+ return false;
894+ }
895+ if (dua.indexOf("Firefox") != -1 && parseFloat (dav) < 1.5) {
896+ return false;
897+ }
898+ if (dua.indexOf("MSIE") != -1 && parseFloat (dav) < 6.0) {
899+ return false;
900+ }
901+ return true;
902+ */
903+ static boolean isSubdomainXSSSupported () {
904+ return true ;
905+ }
906+
907+ /**
908+ *
909+ * @param p
910+ * @j2sNative
911+ p.initParameters = function () {
912+ this.parentDomain = document.domain;
913+ this.pipeQueryInterval = 1000;
914+ this.lastQueryReceived = true;
915+ this.runnable = null;
916+ var oThis = this;
917+ with (window.parent) {
918+ var sph = net.sf.j2s.ajax.SimplePipeHelper;
919+ var spr = net.sf.j2s.ajax.SimplePipeRequest;
920+ this.runnable = sph.getPipe(this.key);
921+ this.pipeQueryInterval = spr.getQueryInterval ();
922+ }
923+ };
924+ p.initHttpRequest = function () {
925+ this.xhrHandle = null;
926+ if (window.XMLHttpRequest) {
927+ this.xhrHandle = new XMLHttpRequest();
928+ } else {
929+ try {
930+ this.xhrHandle = new ActiveXObject("Msxml2.XMLHTTP");
931+ } catch (e) {
932+ this.xhrHandle = new ActiveXObject("Microsoft.XMLHTTP");
933+ }
934+ }
935+ var oThis = this;
936+ this.xhrHandle.onreadystatechange = function () {
937+ var state = oThis.xhrHandle.readyState;
938+ if (state == 4) {
939+ var pipeData = oThis.xhrHandle.responseText;
940+ oThis.xhrHandle.onreadystatechange = function () {};
941+ oThis.xhrHandle = null;
942+ document.domain = oThis.parentDomain;
943+ oThis.lastQueryReceived = true;
944+ with (window.parent) {
945+ var sph = net.sf.j2s.ajax.SimplePipeHelper;
946+ var spr = net.sf.j2s.ajax.SimplePipeRequest;
947+ spr.onPipeDataReceived (pipeData);
948+ oThis.runnable = sph.getPipe (oThis.key);
949+ }
950+ }
951+ };
952+ };
953+ p.pipeXHRQuery = function (request, method, url, data) {
954+ if ("GET" == method.toUpperCase ()) {
955+ request.open (method, url + (url.indexOf ('?') != -1 ? "&" : "?") + data, true, null, null);
956+ data = null;
957+ } else {
958+ request.open (method, url, true, null, null);
959+ }
960+ request.setRequestHeader ("User-Agent",
961+ "Java2Script-Pacemaker/2.0.0 (+http://j2s.sourceforge.net)");
962+ if (method != null && method.toLowerCase () == "post") {
963+ request.setRequestHeader ("Content-type",
964+ "application/x-www-form-urlencoded");
965+ if (request.overrideMimeType) {
966+ request.setRequestHeader ("Connection", "close");
967+ }
968+ }
969+ request.send(data);
970+ };
971+ p.initParameters ();
972+ */
973+ static void subdomainInit (Object p ) {
974+ // for JavaScript only
975+ }
976+
977+ /**
978+ *
979+ * @param p
980+ * @j2sNative
981+ return function () {
982+ if (p.runnable != null) {
983+ if (p.lastQueryReceived) {
984+ p.lastQueryReceived = false;
985+ var method = null;
986+ var url = null;
987+ var data = null;
988+ with (window.parent) {
989+ method = p.runnable.getPipeMethod ();
990+ url = p.runnable.getPipeURL ();
991+ var spr = net.sf.j2s.ajax.SimplePipeRequest;
992+ data = spr.constructRequest(p.key, spr.PIPE_TYPE_QUERY, true);
993+ }
994+ try {
995+ document.domain = p.originalDomain;
996+ } catch (e) {};
997+ p.initHttpRequest ();
998+ try {
999+ p.pipeXHRQuery (p.xhrHandle, method, url, data);
1000+ } catch (e) {
1001+ p.xhrHandle.onreadystatechange = function () {};
1002+ p.xhrHandle = null;
1003+ document.domain = p.parentDomain;
1004+ p.lastQueryReceived = true;
1005+ }
1006+ }
1007+ window.setTimeout (arguments.callee, p.pipeQueryInterval);
1008+ }
1009+ };
1010+ */
1011+ static void subdomainLoopQuery (Object p ) {
1012+ // for JavaScript only
1013+ }
8201014}
0 commit comments