From 276bb99fc91ac09784e4a88c575fb441c0db8db2 Mon Sep 17 00:00:00 2001
From: Dan Stillman <dstillman@zotero.org>
Date: Thu, 9 Aug 2018 15:11:58 -0400
Subject: [PATCH] Don't percent-encode periods in usernames in WebDAV requests

For some reason nsIURL encodes periods in usernames, even though RFC3986
says not to [1]. (It also says servers should normalize them, and most
seem to, but apparently not all [2].)

[1] https://tools.ietf.org/html/rfc3986#section-2.3
[2] https://forums.zotero.org/discussion/73127/zotero-will-convert-the-into-2e-in-the-name-of-the-webdav
---
 chrome/content/zotero/xpcom/http.js | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/chrome/content/zotero/xpcom/http.js b/chrome/content/zotero/xpcom/http.js
index 68faaf4b2d..b1fabf790c 100644
--- a/chrome/content/zotero/xpcom/http.js
+++ b/chrome/content/zotero/xpcom/http.js
@@ -123,12 +123,23 @@ Zotero.HTTP = new function() {
 	 */
 	this.request = Zotero.Promise.coroutine(function* (method, url, options = {}) {
 		if (url instanceof Components.interfaces.nsIURI) {
-			// Don't display password in console
-			var dispURL = this.getDisplayURI(url).spec;
+			// Extract username and password from URI and undo Mozilla's excessive percent-encoding
+			options.username = url.username || null;
+			if (options.username) {
+				options.username = options.username.replace(/%2E/, '.');
+				options.password = url.password || null;
+				url = url.clone();
+				url.userPass = '';
+			}
+			
 			url = url.spec;
 		}
-		else {
-			var dispURL = url;
+		
+		var dispURL = url;
+		
+		// Add username:******** to display URL
+		if (options.username) {
+			dispURL = dispURL.replace(/^(https?:\/\/)/, `$1${options.username}:********@`);
 		}
 		
 		// Don't display API key in console
@@ -173,7 +184,7 @@ Zotero.HTTP = new function() {
 		if (!options.foreground) {
 			xmlhttp.mozBackgroundRequest = true;
 		}
-		xmlhttp.open(method, url, true);
+		xmlhttp.open(method, url, true, options.username, options.password);
 		
 		// Pass the request to a callback
 		if (options.requestObserver) {