Index: /main/trunk/greenstone3/web/interfaces/default/js/document_scripts.js
===================================================================
--- /main/trunk/greenstone3/web/interfaces/default/js/document_scripts.js	(revision 32774)
+++ /main/trunk/greenstone3/web/interfaces/default/js/document_scripts.js	(revision 32775)
@@ -24,4 +24,21 @@
 * EXPANSION SCRIPTS *
 ********************/
+
+/* 
+   Given a string consisting of a single character, returns the %hex (%XX)
+   https://www.w3resource.com/javascript-exercises/javascript-string-exercise-27.php
+   https://stackoverflow.com/questions/40100096/what-is-equivalent-php-chr-and-ord-functions-in-javascript
+   https://www.w3resource.com/javascript-exercises/javascript-string-exercise-27.php
+*/
+function urlEncodeChar(single_char_string) {
+    /*var hex = Number(single_char_string.charCodeAt(0)).toString(16);
+    var str = "" + hex;
+    str = "%" + str.toUpperCase();
+    return str;
+    */
+
+    var hex = "%" + Number(single_char_string.charCodeAt(0)).toString(16).toUpperCase();
+    return hex;
+}
 
 /*
@@ -40,18 +57,40 @@
   Possibly more info: https://stackoverflow.com/questions/1547899/which-characters-make-a-url-invalid
 
+  Javascript already provides functions encodeURI() and encodeURIComponent(), see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI
+  However, the set of chars they deal with only partially overlap with the set of chars that need encoding as per the RFC3986 for URIs and RFC1738 for URLs discussed at
+  https://perishablepress.com/stop-using-unsafe-characters-in-urls/
+  We want to handle all the characters listed as unsafe and reserved at https://perishablepress.com/stop-using-unsafe-characters-in-urls/
+  so we define and use our own conceptually equivalent methods for both existing JavaScript methods: 
+  - makeSafeURL() for Javascript's encodeURI() to make sure all unsafe characters in URLs are escaped by being URL encoded
+  - and makeSafeURLComponent() for JavaScript's encodeURIComponent to additionally make sure all reserved characters in a URL portion are escaped by being URL encoded too
+
+  Function makeSafeURL() is passed a string that represents a URL and therefore only deals with characters that are unsafe in a URL and which therefore require escaping. 
+  Function makeSafeURLComponent() deals with portions of a URL that when decoded need not represent a URL at all, for example data like inline templates passed in as a
+  URL query string's parameter values. As such makeSafeURLComponent() should escape both unsafe URL characters and characters that are reserved in URLs since reserved
+  characters in the query string part (as query param values representing data) may take on a different meaning from their reserved meaning in a URL context.
 */
-/* URL encode RESERVED characters in a non-URL context of a URL, such as the inline template (ilt) parameter value of a URL */
-function makeSafeForURL(url_part, encode_percentages) {
+
+/* URL encodes both 
+   - UNSAFE characters to make URL safe, by calling makeSafeURL()
+   - and RESERVED characters (characters that have reserved meanings within a URL) to make URL valid, since the url component parameter could use reserved characters
+   in a non-URL sense. For example, the inline template (ilt) parameter value of a URL could use '=' and '&' signs where these would have XSLT rather than URL meanings.
+  
+   See end of https://www.w3schools.com/jsref/jsref_replace.asp to use a callback passing each captured element of a regex in str.replace()
+*/
+function makeURLComponentSafe(url_part, encode_percentages) {
     // https://stackoverflow.com/questions/12797118/how-can-i-declare-optional-function-parameters-in-javascript
     encode_percentages = encode_percentages || 1; // this method forces the URL-encoding of any % in url_part, e.g. do this for inline-templates that haven't ever been encoded
     
     var url_encoded = makeURLSafe(url_part, encode_percentages);
-    url_encoded = url_encoded.replace(/;/g, "%3B").replace(/\//g, "%2F").replace(/\?/g, "%3F").replace(/\:/g, "%3A").replace(/\@/g, "%40").replace(/=/g, "%3D").replace(/\&/g,"%26");
+    //return url_encoded.replace(/;/g, "%3B").replace(/\//g, "%2F").replace(/\?/g, "%3F").replace(/\:/g, "%3A").replace(/\@/g, "%40").replace(/=/g, "%3D").replace(/\&/g,"%26");
+    url_encoded = url_encoded.replace(/[\;\/\?\:\@\=\&]/g, function(s) { 
+	return urlEncodeChar(s);
+    }); 
     return url_encoded;
 }
 
 /* 
-   URL encode UNSAFE characters to make URL valid 
-   Set encode_percentages to 1 (true) if the url isn't already partly URL encoded
+   URL encode UNSAFE characters to make URL passed in safe.
+   Set encode_percentages to 1 (true) if you don't want % signs encoded: you'd do so if the url is already partly URL encoded.
 */
 function makeURLSafe(url, encode_percentages) {    
@@ -60,7 +99,11 @@
     var url_encoded = url;
     if(encode_percentages) { url_encoded = url_encoded.replace(/\%/g,"%25"); } // encode % first
-    url_encoded = url_encoded.replace(/ /g, "%20").replace(/\"/g,"%22").replace(/\</g,"%3C").replace(/\>/g,"%3E").replace(/\#/g,"%23").replace(/\{/g,"%7B").replace(/\}/g,"%7D");
-    url_encoded = url_encoded.replace(/\|/g,"%7C").replace(/\\/g,"%5C").replace(/\^/g,"%5E").replace(/\[/g,"%5B").replace(/\]/g,"%5D").replace(/\`/g,"%60");
+    //url_encoded = url_encoded.replace(/ /g, "%20").replace(/\"/g,"%22").replace(/\</g,"%3C").replace(/\>/g,"%3E").replace(/\#/g,"%23").replace(/\{/g,"%7B").replace(/\}/g,"%7D");
+    //url_encoded = url_encoded.replace(/\|/g,"%7C").replace(/\\/g,"%5C").replace(/\^/g,"%5E").replace(/\[/g,"%5B").replace(/\]/g,"%5D").replace(/\`/g,"%60");
     // Should we handle ~, but then what is its URL encoded value? Because https://meyerweb.com/eric/tools/dencoder/ URLencodes ~ to ~.
+    //return url_encoded;    
+    url_encoded = url_encoded.replace(/[\ \"\<\>\#\{\}\|\\^\~\[\]\`]/g, function(s) { 
+	return urlEncodeChar(s);
+    });
     return url_encoded;
 }
@@ -82,5 +125,5 @@
 	template += '</xsl:template>';
     
-    template = makeSafeForURL(template);
+    template = makeURLComponentSafe(template);
     
 	var hlCheckBox = document.getElementById("highlightOption");
@@ -152,5 +195,5 @@
 	template += '</xsl:template>';
 
-    template = makeSafeForURL(template);
+    template = makeURLComponentSafe(template);
 	var url = gs.xsltParams.library_name + "/collection/" + gs.cgiParams.c + "/document/" + sectionID + "?ilt=" + template;
 
@@ -721,5 +764,5 @@
 	ilt += '</xsl:template>';
 	
-    ilt = makeSafeForURL(ilt);
+    ilt = makeURLComponentSafe(ilt);
 
 
@@ -986,5 +1029,5 @@
 		template +=   '</html>';
 		template += '</xsl:template>';
-	template = makeSafeForURL(template);
+	template = makeURLComponentSafe(template);
 		var url = href + "?noText=1&ilt=" + template;
 
@@ -1390,5 +1433,5 @@
 	template +=   ']</images>';
 	template += '</xsl:template>';
-    template = makeSafeForURL(template);
+    template = makeURLComponentSafe(template);
 	var url = gs.xsltParams.library_name + "/collection/" + gs.cgiParams.c + "/document/" + gs.cgiParams.d + "?ed=1&ilt=" + template;
 
