<commit_before>var EXPORTED_SYMBOLS = ['GM_xmlhttpRequester'];

Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
Components.utils.import("chrome://greasemonkey-modules/content/util.js");

var gStringBundle = Components
    .classes["@mozilla.org/intl/stringbundle;1"]
    .getService(Components.interfaces.nsIStringBundleService)
    .createBundle("chrome://greasemonkey/locale/greasemonkey.properties");


function GM_xmlhttpRequester(wrappedContentWin, originUrl, sandbox) {
  this.wrappedContentWin = wrappedContentWin;
  this.originUrl = originUrl;
  this.sandbox = sandbox;
  // Firefox < 29 (i.e. PaleMoon) does not support getObjectPrincipal in a
  // scriptable context.  Greasemonkey users on this platform otherwise would
  // use an older version without this check, so skipping is no worse.
  this.sandboxPrincipal = 'function' == typeof Components.utils.getObjectPrincipal
      ? Components.utils.getObjectPrincipal(sandbox) : null;
}

// this function gets called by user scripts in content security scope to
// start a cross-domain xmlhttp request.
//
// details should look like:
// {method,url,onload,onerror,onreadystatechange,headers,data}
// headers should be in the form {name:value,name:value,etc}
// can't support mimetype because i think it's only used for forcing
// text/xml and we can't support that
GM_xmlhttpRequester.prototype.contentStartRequest = function(details) {
  try {
    // Validate and parse the (possibly relative) given URL.
    var uri = GM_util.uriFromUrl(details.url, this.originUrl);
    var url = uri.spec;
  } catch (e) {
    // A malformed URL won't be parsed properly.
    throw new Error(
        gStringBundle.GetStringFromName('error.invalidUrl')
            .replace('%1', details.url)
        );
  }

  // This is important - without it, GM_xmlhttpRequest can be used to get
  // access to things like files and chrome. Careful.
  switch (uri.scheme) {
    case "http":
    case "https":
    case "ftp":
        var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
            .createInstance(Components.interfaces.nsIXMLHttpRequest);
        GM_util.hitch(this, "chromeStartRequest", url, details, req)();
      break;
    default:
      throw new Error(
          gStringBundle.GetStringFromName('error.disallowedScheme')
              .replace('%1', details.url)
          );
  }

  var rv = {
    abort: function () { return req.abort(); },
    finalUrl: null,
    readyState: null,
    responseHeaders: null,
    responseText: null,
    status: null,
    statusText: null
  };

  if (!!details.synchronous) {
    rv.finalUrl = req.finalUrl;
    rv.readyState = req.readyState;
    rv.responseHeaders = req.getAllResponseHeaders();
    try {
      rv.responseText = req.responseText;
    } catch (e) {
      // Some response types don't have .responseText (but do have e.g. blob
      // .response).  Ignore.
    }
    rv.status = req.status;
    rv.statusText = req.statusText;
  }

  rv = Components.utils.cloneInto({
    abort: rv.abort.bind(rv),
    finalUrl: rv.finalUrl,
    readyState: rv.readyState,
    responseHeaders: rv.responseHeaders,
    responseText: rv.responseText,
    status: rv.status,
    statusText: rv.statusText
  }, this.sandbox, {cloneFunctions: true});

  return rv;
};

// this function is intended to be called in chrome's security context, so
// that it can access other domains without security warning
GM_xmlhttpRequester.prototype.chromeStartRequest =
function(safeUrl, details, req) {
  this.setupReferer(details, req);

  var setupRequestEvent = GM_util.hitch(
      this, 'setupRequestEvent', this.wrappedContentWin, this.sandbox);

  setupRequestEvent(req, "abort", details);
  setupRequestEvent(req, "error", details);
  setupRequestEvent(req, "load", details);
  setupRequestEvent(req, "loadend", details);
  setupRequestEvent(req, "loadstart", details);
  setupRequestEvent(req, "progress", details);
  setupRequestEvent(req, "readystatechange", details);
  setupRequestEvent(req, "timeout", details);
  if (details.upload) {
    setupRequestEvent(req.upload, "abort", details.upload);
    setupRequestEvent(req.upload, "error", details.upload);
    setupRequestEvent(req.upload, "load", details.upload);
    setupRequestEvent(req.upload, "loadend", details.upload);
    setupRequestEvent(req.upload, "progress", details.upload);
    setupRequestEvent(req.upload, "timeout", details.upload);
  }

  req.mozBackgroundRequest = !!details.mozBackgroundRequest;

  req.open(details.method, safeUrl,
      !details.synchronous, details.user || "", details.password || "");

  var channel;

  var isPrivate = true;
  if (PrivateBrowsingUtils.isContentWindowPrivate) {
    // Firefox >= 35
    isPrivate = PrivateBrowsingUtils.isContentWindowPrivate(this.wrappedContentWin);
  } else {
    // Firefox <= 34; i.e. PaleMoon
    isPrivate = PrivateBrowsingUtils.isWindowPrivate(this.wrappedContentWin);
  }
  if (isPrivate) {
    channel = req.channel
        .QueryInterface(Components.interfaces.nsIPrivateBrowsingChannel);
    channel.setPrivate(true);
  }

  channel = req.channel
      .QueryInterface(Components.interfaces.nsIHttpChannelInternal);
  channel.forceAllowThirdPartyCookie = true;

  if (details.overrideMimeType) {
    req.overrideMimeType(details.overrideMimeType);
  }
  if (details.responseType) {
    req.responseType = details.responseType;
  }

  if (details.timeout) {
    req.timeout = details.timeout;
  }

  if ('redirectionLimit' in details) {
    try {
      var httpChannel = req.channel.QueryInterface(
          Components.interfaces.nsIHttpChannel);
      httpChannel.redirectionLimit = details.redirectionLimit;
    } catch (e) {
      // Ignore.
    }
  }

  if (details.headers) {
    var headers = details.headers;

    for (var prop in headers) {
      if (Object.prototype.hasOwnProperty.call(headers, prop)) {
        req.setRequestHeader(prop, headers[prop]);
      }
    }
  }

  var body = details.data ? details.data : null;
  if (details.binary) {
    req.sendAsBinary(body);
  } else {
    req.send(body);
  }
};

// sets the "Referer" HTTP header for this GM_XHR request.
// Firefox does not let chrome JS set the "Referer" HTTP header via XHR
// directly. However, we can still set it indirectly via an
// http-on-modify-request observer.
GM_xmlhttpRequester.prototype.setupReferer =
function(details, req) {
  if (!details.headers || !details.headers.Referer) return;

  var observerService = Components.classes["@mozilla.org/observer-service;1"]
      .getService(Components.interfaces.nsIObserverService);
  var requestObserver = {};
  requestObserver.observe = function(subject, topic, data) {
      observerService.removeObserver(requestObserver, "http-on-modify-request");
<commit_msg>Remove XMLHttpRequest sendAsBinary<commit_after>var EXPORTED_SYMBOLS = ['GM_xmlhttpRequester'];

Components.utils.importGlobalProperties(["Blob"]);
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
Components.utils.import("chrome://greasemonkey-modules/content/util.js");

var gStringBundle = Components
    .classes["@mozilla.org/intl/stringbundle;1"]
    .getService(Components.interfaces.nsIStringBundleService)
    .createBundle("chrome://greasemonkey/locale/greasemonkey.properties");


function GM_xmlhttpRequester(wrappedContentWin, originUrl, sandbox) {
  this.wrappedContentWin = wrappedContentWin;
  this.originUrl = originUrl;
  this.sandbox = sandbox;
  // Firefox < 29 (i.e. PaleMoon) does not support getObjectPrincipal in a
  // scriptable context.  Greasemonkey users on this platform otherwise would
  // use an older version without this check, so skipping is no worse.
  this.sandboxPrincipal = 'function' == typeof Components.utils.getObjectPrincipal
      ? Components.utils.getObjectPrincipal(sandbox) : null;
}

// this function gets called by user scripts in content security scope to
// start a cross-domain xmlhttp request.
//
// details should look like:
// {method,url,onload,onerror,onreadystatechange,headers,data}
// headers should be in the form {name:value,name:value,etc}
// can't support mimetype because i think it's only used for forcing
// text/xml and we can't support that
GM_xmlhttpRequester.prototype.contentStartRequest = function(details) {
  try {
    // Validate and parse the (possibly relative) given URL.
    var uri = GM_util.uriFromUrl(details.url, this.originUrl);
    var url = uri.spec;
  } catch (e) {
    // A malformed URL won't be parsed properly.
    throw new Error(
        gStringBundle.GetStringFromName('error.invalidUrl')
            .replace('%1', details.url)
        );
  }

  // This is important - without it, GM_xmlhttpRequest can be used to get
  // access to things like files and chrome. Careful.
  switch (uri.scheme) {
    case "http":
    case "https":
    case "ftp":
        var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
            .createInstance(Components.interfaces.nsIXMLHttpRequest);
        GM_util.hitch(this, "chromeStartRequest", url, details, req)();
      break;
    default:
      throw new Error(
          gStringBundle.GetStringFromName('error.disallowedScheme')
              .replace('%1', details.url)
          );
  }

  var rv = {
    abort: function () { return req.abort(); },
    finalUrl: null,
    readyState: null,
    responseHeaders: null,
    responseText: null,
    status: null,
    statusText: null
  };

  if (!!details.synchronous) {
    rv.finalUrl = req.finalUrl;
    rv.readyState = req.readyState;
    rv.responseHeaders = req.getAllResponseHeaders();
    try {
      rv.responseText = req.responseText;
    } catch (e) {
      // Some response types don't have .responseText (but do have e.g. blob
      // .response).  Ignore.
    }
    rv.status = req.status;
    rv.statusText = req.statusText;
  }

  rv = Components.utils.cloneInto({
    abort: rv.abort.bind(rv),
    finalUrl: rv.finalUrl,
    readyState: rv.readyState,
    responseHeaders: rv.responseHeaders,
    responseText: rv.responseText,
    status: rv.status,
    statusText: rv.statusText
  }, this.sandbox, {cloneFunctions: true});

  return rv;
};

// this function is intended to be called in chrome's security context, so
// that it can access other domains without security warning
GM_xmlhttpRequester.prototype.chromeStartRequest =
function(safeUrl, details, req) {
  this.setupReferer(details, req);

  var setupRequestEvent = GM_util.hitch(
      this, 'setupRequestEvent', this.wrappedContentWin, this.sandbox);

  setupRequestEvent(req, "abort", details);
  setupRequestEvent(req, "error", details);
  setupRequestEvent(req, "load", details);
  setupRequestEvent(req, "loadend", details);
  setupRequestEvent(req, "loadstart", details);
  setupRequestEvent(req, "progress", details);
  setupRequestEvent(req, "readystatechange", details);
  setupRequestEvent(req, "timeout", details);
  if (details.upload) {
    setupRequestEvent(req.upload, "abort", details.upload);
    setupRequestEvent(req.upload, "error", details.upload);
    setupRequestEvent(req.upload, "load", details.upload);
    setupRequestEvent(req.upload, "loadend", details.upload);
    setupRequestEvent(req.upload, "progress", details.upload);
    setupRequestEvent(req.upload, "timeout", details.upload);
  }

  req.mozBackgroundRequest = !!details.mozBackgroundRequest;

  req.open(details.method, safeUrl,
      !details.synchronous, details.user || "", details.password || "");

  var channel;

  var isPrivate = true;
  if (PrivateBrowsingUtils.isContentWindowPrivate) {
    // Firefox >= 35
    isPrivate = PrivateBrowsingUtils.isContentWindowPrivate(this.wrappedContentWin);
  } else {
    // Firefox <= 34; i.e. PaleMoon
    isPrivate = PrivateBrowsingUtils.isWindowPrivate(this.wrappedContentWin);
  }
  if (isPrivate) {
    channel = req.channel
        .QueryInterface(Components.interfaces.nsIPrivateBrowsingChannel);
    channel.setPrivate(true);
  }

  channel = req.channel
      .QueryInterface(Components.interfaces.nsIHttpChannelInternal);
  channel.forceAllowThirdPartyCookie = true;

  if (details.overrideMimeType) {
    req.overrideMimeType(details.overrideMimeType);
  }
  if (details.responseType) {
    req.responseType = details.responseType;
  }

  if (details.timeout) {
    req.timeout = details.timeout;
  }

  if ('redirectionLimit' in details) {
    try {
      var httpChannel = req.channel.QueryInterface(
          Components.interfaces.nsIHttpChannel);
      httpChannel.redirectionLimit = details.redirectionLimit;
    } catch (e) {
      // Ignore.
    }
  }

  if (details.headers) {
    var headers = details.headers;

    for (var prop in headers) {
      if (Object.prototype.hasOwnProperty.call(headers, prop)) {
        req.setRequestHeader(prop, headers[prop]);
      }
    }
  }

  var body = details.data ? details.data : null;
  if (details.binary && (body !== null)) {
    var bodyLength = body.length;
    var bodyData = new Uint8Array(bodyLength);
    for (var i = 0; i < bodyLength; i++) {
      bodyData[i] = body.charCodeAt(i) & 0xff;
    }
    req.send(new Blob([bodyData]));
  } else {
    req.send(body);
  }
};

// sets the "Referer" HTTP header for this GM_XHR request.
// Firefox does not let chrome JS set the "Referer" HTTP header via XHR
// directly. However, we can still set it indirectly via an
// http-on-modify-request observer.
GM_xmlhttpRequester.prototype.setupReferer =
function(details, req) {
  if (!details.headers || !details.headers.Referer) return;

  var observerService = Components.classes["@mozilla.org/observer-service;1"]
      .getService(Components.interfaces.nsIObserverService);
  var requestObserver = {};
  requestObserver.observe = function(subject, topic, data) {
      observerService.removeObserver(requestObserver, "http-on-modify-request");

{'fraction_non_alphanumeric': 0.11818707532167125, 'fraction_numerical': 0.001807141824490386, 'mean_word_length': 3.699388586956522, 'pattern_counts': {'":': 6, '<': 8, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 20}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3191804', 'n_tokens_mistral': 4249, 'n_tokens_neox': 4152, 'n_words': 957}