<commit_before>// digest auth request
// by <NAME>

// dependent upon CryptoJS MD5 hashing:
// http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/md5.js

function digestAuthRequest(method, url, username, password) {

	var self = this;

	this.scheme = null; // we just echo the scheme, to allow for 'Digest', 'X-Digest', 'JDigest' etc
	this.nonce = null; // server issued nonce
	this.realm = null; // server issued realm
	this.qop = null; // "quality of protection" - '' or 'auth' or 'auth-int'
	this.response = null; // hashed response to server challenge
	this.opaque = null; // hashed response to server challenge
	this.nc = 1; // nonce count - increments with each request used with the same nonce
	this.cnonce = null; // client nonce

	// settings
	this.timeout = 10000; // timeout
	this.loggingOn = true; // toggle console logging

	// determine if a post, so that request will send data 
	this.post = false;
	if (method.toLowerCase() === 'post' || method.toLowerCase() === 'put') {
		this.post = true;
	}

	// start here
	// successFn - will be passed JSON data
	// errorFn - will be passed error status code
	// data - optional, for POSTS
	this.request = function(successFn, errorFn, data) {
		// posts data as JSON if there is any
		if (data) {
			self.data = JSON.stringify(data);
		}
		self.successFn = successFn;
		self.errorFn = errorFn;

		if (!self.nonce) {
			self.makeUnauthenticatedRequest(self.data);
		} else {
			self.makeAuthenticatedRequest();
		}		
	}
	this.makeUnauthenticatedRequest = function(data) {		
		self.firstRequest = new XMLHttpRequest();
		self.firstRequest.open(method, url, true);
		self.firstRequest.timeout = self.timeout;
		// if we are posting, add appropriate headers
		if (self.post) {
			self.firstRequest.setRequestHeader('Content-type', 'application/json');
		}

		self.firstRequest.onreadystatechange = function() {

			// 2: received headers,  3: loading, 4: done
			if (self.firstRequest.readyState === 2) { 

				var responseHeaders = self.firstRequest.getAllResponseHeaders();
				responseHeaders = responseHeaders.split('\n');
				// get authenticate header
				var digestHeaders;
				for(var i = 0; i < responseHeaders.length; i++) {
					if (responseHeaders[i].match(/www-authenticate/i) != null) {
						digestHeaders = responseHeaders[i];
					}
				}
				
				if (digestHeaders != null) {
					// parse auth header and get digest auth keys
					digestHeaders = digestHeaders.split(':')[1];
					digestHeaders = digestHeaders.split(',');
					self.scheme = digestHeaders[0].split(/\s/)[1];
					for (var i = 0; i < digestHeaders.length; i++) {
						var equalIndex = digestHeaders[i].indexOf('='),
							key = digestHeaders[i].substring(0, equalIndex),
							val = digestHeaders[i].substring(equalIndex + 1);
						val = val.replace(/['"]+/g, '');
						// find realm
						if (key.match(/realm/i) != null) {
							self.realm = val;
						}
						// find nonce
						if (key.match(/nonce/i) != null) {
							self.nonce = val;
						}
						// find opaque
						if (key.match(/opaque/i) != null) {
							self.opaque = val;
						}
						// find QOP
						if (key.match(/qop/i) != null) {
							self.qop = val;
						}
					}
					// client generated keys
					self.cnonce = self.generateCnonce();
					self.nc++;
					// if logging, show headers received:
					self.log('received headers:');
					self.log('	realm: '+self.realm);
					self.log('	nonce: '+self.nonce);
					self.log('	opaque: '+self.opaque);
					self.log('	qop: '+self.qop);
					// now we can make an authenticated request
					
					self.makeAuthenticatedRequest();
				}
			}
			if (self.firstRequest.readyState === 4) {
				if (self.firstRequest.status === 200) {
					self.log('Authentication not required for '+url);
					if (self.firstRequest.responseText !== 'undefined') {
						if (self.firstRequest.responseText.length > 0) {
							// If JSON, parse and return object
							if (self.isJson(self.firstRequest.responseText)) {
								self.successFn(JSON.parse(self.firstRequest.responseText));
							} else {
								self.successFn(self.firstRequest.responseText);
							}
						}
					} else {
						self.successFn();
					}
				}
			}
		}
		// send
		if (self.post) {
			// in case digest auth not required
			self.firstRequest.send(self.data);
		} else {
			self.firstRequest.send();
		}
		self.log('Unauthenticated request to '+url);

		// handle error
		self.firstRequest.onerror = function() {
			if (self.firstRequest.status !== 401) {
				self.log('Error ('+self.authenticatedRequest.status+') on unauthenticated request to '+url);
				self.errorFn(self.firstRequest.status);
			}
		}

	}
	this.makeAuthenticatedRequest= function() {

		self.response = self.formulateResponse();

		self.authenticatedRequest = new XMLHttpRequest();
		self.authenticatedRequest.open(method, url, true);
		self.authenticatedRequest.timeout = self.timeout;
		var digestAuthHeader = self.scheme+' '+
			'username="'+username+'", '+
			'realm="'+self.realm+'", '+
			'nonce="'+self.nonce+'", '+
			'uri="'+url+'", '+
			'response="'+self.response+'", '+
			'opaque="'+self.opaque+'", '+
			'qop='+self.qop+', '+
			'nc='+('00000000' + self.nc).slice(-8)+', '+
			'cnonce="'+self.cnonce+'"';
		self.authenticatedRequest.setRequestHeader('Authorization', digestAuthHeader);<commit_msg>log status code for the first (unauthenticated) request on request error. Fix a bug where trying to get status code from the wrong request object.<commit_after>// digest auth request
// by <NAME>

// dependent upon CryptoJS MD5 hashing:
// http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/md5.js

function digestAuthRequest(method, url, username, password) {

	var self = this;

	this.scheme = null; // we just echo the scheme, to allow for 'Digest', 'X-Digest', 'JDigest' etc
	this.nonce = null; // server issued nonce
	this.realm = null; // server issued realm
	this.qop = null; // "quality of protection" - '' or 'auth' or 'auth-int'
	this.response = null; // hashed response to server challenge
	this.opaque = null; // hashed response to server challenge
	this.nc = 1; // nonce count - increments with each request used with the same nonce
	this.cnonce = null; // client nonce

	// settings
	this.timeout = 10000; // timeout
	this.loggingOn = true; // toggle console logging

	// determine if a post, so that request will send data 
	this.post = false;
	if (method.toLowerCase() === 'post' || method.toLowerCase() === 'put') {
		this.post = true;
	}

	// start here
	// successFn - will be passed JSON data
	// errorFn - will be passed error status code
	// data - optional, for POSTS
	this.request = function(successFn, errorFn, data) {
		// posts data as JSON if there is any
		if (data) {
			self.data = JSON.stringify(data);
		}
		self.successFn = successFn;
		self.errorFn = errorFn;

		if (!self.nonce) {
			self.makeUnauthenticatedRequest(self.data);
		} else {
			self.makeAuthenticatedRequest();
		}		
	}
	this.makeUnauthenticatedRequest = function(data) {		
		self.firstRequest = new XMLHttpRequest();
		self.firstRequest.open(method, url, true);
		self.firstRequest.timeout = self.timeout;
		// if we are posting, add appropriate headers
		if (self.post) {
			self.firstRequest.setRequestHeader('Content-type', 'application/json');
		}

		self.firstRequest.onreadystatechange = function() {

			// 2: received headers,  3: loading, 4: done
			if (self.firstRequest.readyState === 2) { 

				var responseHeaders = self.firstRequest.getAllResponseHeaders();
				responseHeaders = responseHeaders.split('\n');
				// get authenticate header
				var digestHeaders;
				for(var i = 0; i < responseHeaders.length; i++) {
					if (responseHeaders[i].match(/www-authenticate/i) != null) {
						digestHeaders = responseHeaders[i];
					}
				}
				
				if (digestHeaders != null) {
					// parse auth header and get digest auth keys
					digestHeaders = digestHeaders.split(':')[1];
					digestHeaders = digestHeaders.split(',');
					self.scheme = digestHeaders[0].split(/\s/)[1];
					for (var i = 0; i < digestHeaders.length; i++) {
						var equalIndex = digestHeaders[i].indexOf('='),
							key = digestHeaders[i].substring(0, equalIndex),
							val = digestHeaders[i].substring(equalIndex + 1);
						val = val.replace(/['"]+/g, '');
						// find realm
						if (key.match(/realm/i) != null) {
							self.realm = val;
						}
						// find nonce
						if (key.match(/nonce/i) != null) {
							self.nonce = val;
						}
						// find opaque
						if (key.match(/opaque/i) != null) {
							self.opaque = val;
						}
						// find QOP
						if (key.match(/qop/i) != null) {
							self.qop = val;
						}
					}
					// client generated keys
					self.cnonce = self.generateCnonce();
					self.nc++;
					// if logging, show headers received:
					self.log('received headers:');
					self.log('	realm: '+self.realm);
					self.log('	nonce: '+self.nonce);
					self.log('	opaque: '+self.opaque);
					self.log('	qop: '+self.qop);
					// now we can make an authenticated request
					
					self.makeAuthenticatedRequest();
				}
			}
			if (self.firstRequest.readyState === 4) {
				if (self.firstRequest.status === 200) {
					self.log('Authentication not required for '+url);
					if (self.firstRequest.responseText !== 'undefined') {
						if (self.firstRequest.responseText.length > 0) {
							// If JSON, parse and return object
							if (self.isJson(self.firstRequest.responseText)) {
								self.successFn(JSON.parse(self.firstRequest.responseText));
							} else {
								self.successFn(self.firstRequest.responseText);
							}
						}
					} else {
						self.successFn();
					}
				}
			}
		}
		// send
		if (self.post) {
			// in case digest auth not required
			self.firstRequest.send(self.data);
		} else {
			self.firstRequest.send();
		}
		self.log('Unauthenticated request to '+url);

		// handle error
		self.firstRequest.onerror = function() {
			if (self.firstRequest.status !== 401) {
				self.log('Error ('+self.firstRequest.status+') on unauthenticated request to '+url);
				self.errorFn(self.firstRequest.status);
			}
		}

	}
	this.makeAuthenticatedRequest= function() {

		self.response = self.formulateResponse();

		self.authenticatedRequest = new XMLHttpRequest();
		self.authenticatedRequest.open(method, url, true);
		self.authenticatedRequest.timeout = self.timeout;
		var digestAuthHeader = self.scheme+' '+
			'username="'+username+'", '+
			'realm="'+self.realm+'", '+
			'nonce="'+self.nonce+'", '+
			'uri="'+url+'", '+
			'response="'+self.response+'", '+
			'opaque="'+self.opaque+'", '+
			'qop='+self.qop+', '+
			'nc='+('00000000' + self.nc).slice(-8)+', '+
			'cnonce="'+self.cnonce+'"';
		self.authenticatedRequest.setRequestHeader('Authorization', digestAuthHeader);
{'fraction_non_alphanumeric': 0.15398904058697874, 'fraction_numerical': 0.007244357759821678, 'mean_word_length': 2.9399926820343945, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, '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': '2930151', 'n_tokens_mistral': 4335, 'n_tokens_neox': 3442, 'n_words': 811}