<commit_before>/* global Buffer */
var SP = require("node-spoauth"),
	folders = require('./folders'),
	urlparse = require('url').parse,
	util = require("util"),
	httpreq = require("httpreq"),
	httpntml = require("httpntlm"),
	LoggerFunc = require("./logger"),
	setAuth = require('./setAuth');

module.exports = function (options, callback) {
	var httprequest,
		onPrem,
		log,
		onreadyCallback,
		logger;

	if (!callback) {
		callback = function () { }
	}
	if (!options.isOnPrem) {
		options.isOnPrem = isOnPrem;
	}
	if (typeof options.log !== "boolean") {
		options.log = log = false;
	} else {
		log = options.log;
	}
	logger = new LoggerFunc(options.log);

	onreadyCallback = callback;

	onPrem = options.isOnPrem(options.siteUrl);

	if (onPrem) {
		httprequest = exhttpntlm;
	} else {
		httprequest = httpreq;
	}

	if (onPrem) {
		spSaveCore(options, {
			username: options.username,
			password: <PASSWORD>,
			workstation: options.workstation,
			domain: options.domain
		});
	} else {
		var service = new SP.RestService(options.siteUrl);
		service.signin(options.username, options.password, function (err, auth) {
			if (err) {
				logger.error(err);
				onreadyCallback(err);
				return;
			}

			spSaveCore(options, auth);
		});
	}

	function spSaveCore(options, auth) {
		var url = urlparse(options.siteUrl);
		getRequestDigest(url, options, auth, function (digestValue) {
			if (options.appWebUrl) {
				getAppWebUrl(options, auth, digestValue, function (appWebUrl) {
					getRequestDigest(appWebUrl, options, auth, function (newDigest) {
						uploadFile(appWebUrl, options, newDigest, auth);
					});
				});
			} else {
				uploadFile(url, options, digestValue, auth);
			}
		});
	}

	function getRequestDigest(url, options, auth, onDigest) {
		var opts = {
			headers: {
				"Accept": "application/json;odata=verbose",
				"content-length": "0"
			}
		};

		setAuth(options, auth, opts, onPrem);

		httprequest.post(url.href + "/_api/contextinfo", opts, function (err, res) {
			if (err) {
				logger.error(err);
				onreadyCallback(err);
				return;
			} else {
				var data = JSON.parse(res.body);

				if (data.error) {
					logger.error(data.error);
					onreadyCallback(new Error(JSON.stringify(data.error)));
					return;
				}

				onDigest(data.d.GetContextWebInformation.FormDigestValue);
			}
		});
	}

	function getAppWebUrl(options, auth, digestValue, onGetAppWeb) {

		writeToLog(util.format("Opening '%s' ...", options.appWebUrl));

		var openWebUrl = util.format("/_api/site/openWeb(@strUrl)?@strUrl='%s'", options.appWebUrl);

		var opts = {
			headers: {
				"Accept": "application/json;odata=verbose",
				"X-RequestDigest": digestValue
			}
		};

		setAuth(options, auth, opts, onPrem);
<commit_msg>Added error handler for status code 401 during retrieval of context information (makes debugging of deployment issues easier)<commit_after>/* global Buffer */
var SP = require("node-spoauth"),
	folders = require('./folders'),
	urlparse = require('url').parse,
	util = require("util"),
	httpreq = require("httpreq"),
	httpntml = require("httpntlm"),
	LoggerFunc = require("./logger"),
	setAuth = require('./setAuth');

module.exports = function (options, callback) {
	var httprequest,
		onPrem,
		log,
		onreadyCallback,
		logger;

	if (!callback) {
		callback = function () { }
	}
	if (!options.isOnPrem) {
		options.isOnPrem = isOnPrem;
	}
	if (typeof options.log !== "boolean") {
		options.log = log = false;
	} else {
		log = options.log;
	}
	logger = new LoggerFunc(options.log);

	onreadyCallback = callback;

	onPrem = options.isOnPrem(options.siteUrl);

	if (onPrem) {
		httprequest = exhttpntlm;
	} else {
		httprequest = httpreq;
	}

	if (onPrem) {
		spSaveCore(options, {
			username: options.username,
			password: <PASSWORD>,
			workstation: options.workstation,
			domain: options.domain
		});
	} else {
		var service = new SP.RestService(options.siteUrl);
		service.signin(options.username, options.password, function (err, auth) {
			if (err) {
				logger.error(err);
				onreadyCallback(err);
				return;
			}

			spSaveCore(options, auth);
		});
	}

	function spSaveCore(options, auth) {
		var url = urlparse(options.siteUrl);
		getRequestDigest(url, options, auth, function (digestValue) {
			if (options.appWebUrl) {
				getAppWebUrl(options, auth, digestValue, function (appWebUrl) {
					getRequestDigest(appWebUrl, options, auth, function (newDigest) {
						uploadFile(appWebUrl, options, newDigest, auth);
					});
				});
			} else {
				uploadFile(url, options, digestValue, auth);
			}
		});
	}

	function getRequestDigest(url, options, auth, onDigest) {
		var opts = {
			headers: {
				"Accept": "application/json;odata=verbose",
				"content-length": "0"
			}
		};

		setAuth(options, auth, opts, onPrem);

		httprequest.post(url.href + "/_api/contextinfo", opts, function (err, res) {
			if (err) {
				logger.error(err);
				onreadyCallback(err);
				return;
            } else if (res.statusCode === 401) {
                logger.error("Server returned status code 401. Cannot login to SharePoint.");
                onreadyCallback(new Error("Status Code 401"));
                return;
            }
            else {
				var data = JSON.parse(res.body);

				if (data.error) {
					logger.error(data.error);
					onreadyCallback(new Error(JSON.stringify(data.error)));
					return;
				}

				onDigest(data.d.GetContextWebInformation.FormDigestValue);
			}
		});
	}

	function getAppWebUrl(options, auth, digestValue, onGetAppWeb) {

		writeToLog(util.format("Opening '%s' ...", options.appWebUrl));

		var openWebUrl = util.format("/_api/site/openWeb(@strUrl)?@strUrl='%s'", options.appWebUrl);

		var opts = {
			headers: {
				"Accept": "application/json;odata=verbose",
				"X-RequestDigest": digestValue
			}
		};

		setAuth(options, auth, opts, onPrem);

{'fraction_non_alphanumeric': 0.14851654947693363, 'fraction_numerical': 0.0024009603841536613, 'mean_word_length': 3.5349922239502334, 'pattern_counts': {'":': 8, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '6132923', 'n_tokens_mistral': 2292, 'n_tokens_neox': 1939, 'n_words': 402}