Partial fix for tickets #2194, #2393: Workaround for Meteor breaking AJAX error responses returned on posting new notices. Fixes things in Firefox 4, but Safari 5 and Chrome 8 still don't return data... either on success or failure! Sigh.

The Meteor realtime plugin sets document.domain to the common prefix between the main server and the Meteor server's hostnames, which overrides the same-origin controls on JavaScript DOM access so the two parts of the app can speak to each other.
This unfortunately causes "fun" side effects for XMLHTTPRequest access to the main domain... if the new domain doesn't match the actual host (eg 'status.net' instead of 'brion.status.net') then we can't access the XHR's responseXML attribute, which holds a DOM tree of the parsed XML return data.
As a workaround, if we can't get at the contents there, we'll parse a fresh DOM tree in the local context from the responseText property, which remains available.

In the longer term, recommend retooling the realtime stuff so it's not fiddling with document.domain. It could also be an issue as it could allow local JavaScript XSS attacks to migrate to subdomains in other open windows.
This commit is contained in:
Brion Vibber 2010-11-17 14:24:35 -08:00
parent 197b56778a
commit b73c162256
2 changed files with 14 additions and 3 deletions

View File

@ -236,8 +236,9 @@ var SN = { // StatusNet
form.append('<p class="form_response error">Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists.</p>'); form.append('<p class="form_response error">Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists.</p>');
} }
else { else {
if ($('.'+SN.C.S.Error, xhr.responseXML).length > 0) { var response = SN.U.GetResponseXML(xhr);
form.append(document._importNode($('.'+SN.C.S.Error, xhr.responseXML)[0], true)); if ($('.'+SN.C.S.Error, response).length > 0) {
form.append(document._importNode($('.'+SN.C.S.Error, response)[0], true));
} }
else { else {
if (parseInt(xhr.status) === 0 || jQuery.inArray(parseInt(xhr.status), SN.C.I.HTTP20x30x) >= 0) { if (parseInt(xhr.status) === 0 || jQuery.inArray(parseInt(xhr.status), SN.C.I.HTTP20x30x) >= 0) {
@ -326,6 +327,16 @@ var SN = { // StatusNet
}); });
}, },
GetResponseXML: function(xhr) {
// Work around unavailable responseXML when document.domain
// has been modified by Meteor or other tools.
try {
return xhr.responseXML;
} catch (e) {
return (new DOMParser()).parseFromString(xhr.responseText, "text/xml");
}
},
NoticeReply: function() { NoticeReply: function() {
if ($('#'+SN.C.S.NoticeDataText).length > 0 && $('#content .notice_reply').length > 0) { if ($('#'+SN.C.S.NoticeDataText).length > 0 && $('#content .notice_reply').length > 0) {
$('#content .notice').each(function() { SN.U.NoticeReplyTo($(this)); }); $('#content .notice').each(function() { SN.U.NoticeReplyTo($(this)); });

2
js/util.min.js vendored

File diff suppressed because one or more lines are too long