Index: /main/trunk/greenstone3/build.xml
===================================================================
--- /main/trunk/greenstone3/build.xml	(revision 32481)
+++ /main/trunk/greenstone3/build.xml	(revision 32482)
@@ -68,4 +68,5 @@
   -->
   <property name="https.test.mode" value="false"/>
+  <property name="sudo.or.not" value="/bin/bash"/><!-- by default, we don't run even special commands with sudo -->
 
   <property name="os.linux" value="Linux"/> 
@@ -263,6 +264,5 @@
 
 	<!-- On linux, if testing https certification, pass in minus-minus-staging. If not testing on linux, nothing extra to pass in.
-		On windows, if testing https certification, nothing extra to pass in. If not testing on windows, pass in minus-minus-live.
-		No https certification automation (yet) for macs.
+	     On windows or mac, if testing https certification, nothing extra to pass in. If not testing on windows or mac, pass in minus-minus-live.
 	-->
 	<if><bool><istrue value="${current.os.isunixnotmac}"/></bool>	
@@ -271,5 +271,5 @@
 		</condition>
 	</if>
-	<if><bool><istrue value="${current.os.iswindows}"/></bool>
+	<if><bool><or><istrue value="${current.os.iswindows}"/><istrue value="${current.os.ismac}"/></or></bool>
 		<condition property="https.testing" value="--live" else="">
 			<isfalse value="${https.test.mode}"/>
@@ -1633,8 +1633,8 @@
   <target name="check-os-for-https-cert-support">
 	<if><bool><isset property="current.os.ismac"/></bool>
-		<fail>
+		<echo>
 			Features that automate generating, removing and renewing HTTPS certificates
-			are currently not supported on Macs, only on other Unix systems and on Windows.
-		</fail>
+			are currently still being implemented on Macs.
+		</echo>
 	</if>	
   </target>
@@ -1661,9 +1661,9 @@
       To run this target, ensure you have:
       * (if on unix) sudo permissions. Enter the sudo password if prompted.
-	  * (if on windows) sufficient privileges to run the included tomcat on port 80.
+      * (if on windows) sufficient privileges to run the included tomcat on port 80.
       * nothing running on port 80 when you run this target
       * edited the build.properties file with
         - tomcat.server set to the/a domain name of your server
-        - server.protocols list set to contain at least 'https' if not also http (the first in this comma-separated list will be the default protocol)
+        - server.protocols comma-separated list set to contain at least 'https' if not also http (the first in this list will be the default protocol)
         - tomcat.port.https set to a valid port number not yet in use
         - keystore.pass set to a password for the certification process
@@ -1713,4 +1713,7 @@
 		<if><bool><istrue value="${current.os.isunixnotmac}"/></bool>
 			<antcall target="setup-https-cert-linux"/>
+		</if>
+		<if><bool><istrue value="${current.os.ismac}"/></bool>
+			<antcall target="setup-https-cert-mac"/>
 		</if>
 	 </else>
@@ -1798,7 +1801,7 @@
 	  <!--<arg value="==export-pfx" /><arg value="${keystore.pass}" />
 	  <arg value="==tag-pfx" /><arg value="greenstone3-tomcat" />--><!--Convert the certificate (that contains the full chain AND private key) to pfx format hereafter using OpenSSL instead-->
-	  <arg line="${https.cert.renewal}" /><!-- rewew command on windows appends min-min-renew XX, where if the day the renewal is run is XX days within expiry, the certificate will get renewed. -->
-    </exec>
-	
+	  <arg line="${https.cert.renewal}" /><!-- renew command on windows/mac appends min-min-renew XX, where if the day the renewal is run is XX days within expiry, the certificate will get renewed. -->
+    </exec>
+
 	<!-- stop the tomcat running on port 80 -->
 	<antcall target="stop">
@@ -1810,5 +1813,5 @@
 		<param name="https.comment.out.end" value="${comment.end}"/>
 	</antcall>
-	
+
 	<!-- Use OpenSSL instead of ZeroSSL to convert the certificate to the .pfx format that tomcat likes, using this cmd:
 			GS3/bin/windows/openssl/bin/openssl.exe pkcs12 -inkey domain.key -in domain.crt -passin pass:pwd -passout pass:pwd -export -out ${keystore.file}
@@ -1830,4 +1833,106 @@
   </target>
   
+  <target name="setup-https-cert-mac">
+	
+	<echo>********** The included tomcat will be stopped, then restarted on port 80 and stopped again</echo>
+	
+	<!-- create folder packages\tomcat\webapps\ROOT\.well-known\acme-challenge -->
+	<mkdir dir="${packages.home}/tomcat/webapps/ROOT/.well-known/acme-challenge"/>
+	<mkdir dir="${packages.home}/tomcat/conf/https_cert"/>
+  
+	<!--
+	    See comments under setup-https-cert-WINDOWS
+	-->
+	<!-- We generate the account key named "privkey.key" in ${packages.home}\tomcat\conf\https_cert -->
+	<if><bool><not><available file="${packages.home}/tomcat/conf/https_cert/privkey.key"/></not></bool>
+	  <exec executable="openssl" osfamily="mac" dir="${basedir}/bin/${os.bin.dir}/openssl/bin" spawn="false">    
+	    <arg value="genrsa" />
+	    <arg value="-out" /><arg value="${packages.home}/tomcat/conf/https_cert/privkey.key" /><arg value="4096" />
+	  </exec>
+	</if>
+  
+	<!-- Also generate the domain key (for csr-key parameter to zeroSSL's le.pl)
+		${packages.home}\tomcat\conf\https_cert\${tomcat.server}.key
+		Using 2048 instead of 4096 bits for this. See https://zerossl.com/usage.html#First_time_run_and_regular_use
+	-->
+	<if><bool><not><available file="${packages.home}/tomcat/conf/https_cert/${tomcat.server}.key"/></not></bool>
+	  <exec executable="openssl" osfamily="mac" dir="${basedir}/bin/${os.bin.dir}/openssl/bin" spawn="false">
+	    <arg value="genrsa" />
+	    <arg value="-out" /><arg value="${packages.home}/tomcat/conf/https_cert/${tomcat.server}.key" /><arg value="2048" />
+	  </exec>
+	</if>
+  
+	<!-- stop the included tomcat (also stopping derby and solr) -->
+	<antcall target="stop" />
+	
+	<!-- rerun tomcat on port 80
+		See https://ant.apache.org/manual/Tasks/antcall.html -->
+	<antcall target="start">
+	  <param name="sudo.or.not" value="/usr/bin/sudo" />
+		<param name="localhost.port.http" value="80"/>
+		<param name="default.tomcat.port" value="80"/>
+		<param name="local.http.url" value="http://${localhost.server.http}"/><!-- For port 80 over http, leave out port number in URL -->
+		<param name="http.address.restriction" value=""/><!-- don't prevent public access over http of port 80 -->
+		<param name="https.comment.out.start" value="${comment.start}"/>
+		<param name="https.comment.out.end" value="${comment.end}"/>
+	</antcall>
+ 
+	<!-- get the certificate: use zerossl's le.pl compiled up for Mac.
+	   For further notes, see under setup-https-cert-WINDOWS
+	-->
+
+    <exec executable="perl" osfamily="mac" dir="${gs2build.home}/perllib/cpan/Crypt/LE/bin" spawn="false">
+      <env key="PERL5LIB" value="${gs2build.home}/perllib/cpan${path.separator}${gs2build.home}/perllib/cpan/perl-5.18"/>
+      <arg value="-S" />
+	  <arg value="${gs2build.home}/perllib/cpan/Crypt/LE/bin/le.pl" />
+	  <arg value="--key" /><arg value="${packages.home}/tomcat/conf/https_cert/privkey.key" />
+	  <arg value="--csr" /><arg value="${packages.home}/tomcat/conf/https_cert/${tomcat.server}.csr" />
+	  <arg value="--csr-key" /><arg value="${packages.home}/tomcat/conf/https_cert/${tomcat.server}.key" />
+	  <!--<arg value="==crt" /><arg value="${packages.home}/tomcat/conf/https_cert/${tomcat.server}.crt" />-->
+	  <arg value="--crt" /><arg value="${packages.home}/tomcat/conf/https_cert/fullchain_and_prvtkey.crt" />
+	  <arg value="--domains" /><arg value="${https.cert.domains}" />
+	  <arg value="--path" /><arg value="${packages.home}/tomcat/webapps/ROOT/.well-known/acme-challenge" />
+	  <arg value="--generate-missing" />
+	  <arg value="--unlink" />
+	  <arg line="${https.testing}" /><!-- minus-minus-live if not testing, empty if testing. https://stackoverflow.com/questions/11840284/pass-arguments-to-apache-ant-exec-task-based-on-the-variables-value -->
+	  <!--<arg value="==export-pfx" /><arg value="${keystore.pass}" />
+	      <arg value="==tag-pfx" /><arg value="greenstone3-tomcat" />--><!-- not sure if this generates a keystore filename with ext .p12 or .pfx for Macs -->
+	  <arg line="${https.cert.renewal}" /><!-- renew command on windows/mac appends min-min-renew XX, where if the day the renewal is run is XX days within expiry, the certificate will get renewed. -->
+    </exec>
+
+    <!-- need regular user permissions on both the Certificate Signing Request file and the certicate,
+	 so as user, we copy the files from /tmp where they were generated as root to user location -->
+    <!--<copy file="/tmp/${tomcat.server}.csr" tofile="${packages.home}/tomcat/conf/https_cert/${tomcat.server}.csr"/>
+    <copy file="/tmp/fullchain_and_prvtkey.crt" tofile="${packages.home}/tomcat/conf/https_cert/fullchain_and_prvtkey.crt"/>-->
+
+	<!-- stop the tomcat running on port 80 -->
+	<antcall target="stop">
+	  <param name="sudo.or.not" value="/usr/bin/sudo" />
+		<param name="localhost.port.http" value="80"/>
+		<param name="default.tomcat.port" value="80"/>
+		<param name="local.http.url" value="http://${localhost.server.http}"/>
+		<param name="http.address.restriction" value=""/>
+		<param name="https.comment.out.start" value="${comment.start}"/>
+		<param name="https.comment.out.end" value="${comment.end}"/>
+	</antcall>
+
+	<!-- Use OpenSSL instead of ZeroSSL to convert the certificate to the .pfx format that tomcat likes, using this cmd:
+			GS3/bin/windows/openssl/bin/openssl.exe pkcs12 -inkey domain.key -in domain.crt -passin pass:pwd -passout pass:pwd -export -out ${keystore.file}
+			GS3/bin/windows/openssl/bin/openssl.exe pkcs12 -inkey domain.key -in domain.crt -password pass:pwd -export -out ${keystore.file}
+		where on windows, keystore.file = fullchain_and_prvtkey.pfx
+	-->
+	<exec executable="openssl" osfamily="mac" dir="${basedir}/bin/${os.bin.dir}/openssl/bin" spawn="false">
+	  <arg value="pkcs12" />
+	  <arg value="-inkey" /><arg value="${packages.home}/tomcat/conf/https_cert/${tomcat.server}.key" />
+	  <arg value="-in" /><arg value="${packages.home}/tomcat/conf/https_cert/fullchain_and_prvtkey.crt" />
+	  <arg value="-export" />
+	  <arg value="-out" /><arg value="${packages.home}/tomcat/conf/https_cert/${keystore.file}" />
+	  <arg value="-name"/><arg value="greenstone3-tomcat"/><!-- See https://stackoverflow.com/questions/808669/convert-a-cert-pem-certificate-to-a-pfx-certificate -->
+	  <arg value="-password"/><arg value="pass:${keystore.pass}"/>
+	</exec>
+	
+  </target>
+  
+
   
   <target name="setup-https-cert-linux">
@@ -1914,5 +2019,5 @@
 	Note osfamily="unix" is separate from osfamily="mac", which comes out handy here as we haven't set up certbot-auto for mac (yet).
     -->
-    <exec executable="./certbot-auto" osfamily="unix" dir="${basedir}/bin/${os.bin.dir}" failonerror="true" inputstring="Y">
+    <exec executable="./certbot-auto" os="${os.linux},${os.solaris}" dir="${basedir}/bin/${os.bin.dir}" failonerror="true" inputstring="Y">
      <arg value="revoke"/>
      <arg line="${https.testing}"/>
@@ -1926,14 +2031,25 @@
     -->
 	
-	<!-- On Windows, we use zeroSSl. For the revoke command, see https://zerossl.com/usage.html#Certificate_revocation -->
-	<exec executable="cmd" osfamily="windows" dir="${basedir}/bin/${os.bin.dir}" spawn="false">
+    <!-- On Windows and Mac, we use zeroSSl. For the revoke command, see https://zerossl.com/usage.html#Certificate_revocation -->
+    <exec executable="cmd" osfamily="windows" dir="${basedir}/bin/${os.bin.dir}" spawn="false">
       <arg value="/c" />
-	  <arg value="le${os.bitness}" />	  
-	  <arg value="--key" /><arg value="${packages.home}\tomcat\conf\https_cert\privkey.key" />
+      <arg value="le${os.bitness}" />	  
+      <arg value="--key" /><arg value="${packages.home}\tomcat\conf\https_cert\privkey.key" />
       <arg value="--crt" /><arg value="${packages.home}\tomcat\conf\https_cert\fullchain_and_prvtkey.crt"/>
-	  <arg value="--revoke"/>
-	  <arg line="${https.testing}"/>
-	</exec>
+      <arg value="--revoke"/>
+      <arg line="${https.testing}"/>
+    </exec>
 	
+    <!-- On Mac, we use the le.pl we compiled up (Crypt::LE) and which needs to have PERL5LIB set correctly to run -->	
+    <exec executable="perl" osfamily="mac" dir="${gs2build.home}/perllib/cpan/Crypt/LE/bin" spawn="false">
+      <env key="PERL5LIB" value="${gs2build.home}/perllib/cpan${path.separator}${gs2build.home}/perllib/cpan/perl-5.18"/>
+      <arg value="-S" />
+      <arg value="${gs2build.home}/perllib/cpan/Crypt/LE/bin/le.pl" />
+      <arg value="--key" /><arg value="${packages.home}/tomcat/conf/https_cert/privkey.key" />
+      <arg value="--crt" /><arg value="${packages.home}/tomcat/conf/https_cert/fullchain_and_prvtkey.crt"/>
+      <arg value="--revoke"/>
+      <arg line="${https.testing}"/>
+    </exec>
+
     <!-- And remove the https_cert folder -->
     <delete dir="${packages.home}/tomcat/conf/https_cert"/>
@@ -1951,6 +2067,6 @@
     <echo>
       NOTE: To run this target,
-	  * ensure nothing is running on port 80.
-      * if you're on Linux, you need to have sudo permissions. Enter the sudo password if prompted.      
+          * ensure nothing is running on port 80
+          * if you're on Linux or Mac, you need to have sudo permissions. Enter the sudo password if prompted.      
 
       If you want your cronjob to renew a certificate, you can add pre and post hooks
@@ -1959,5 +2075,5 @@
          ./path/to/GS3/bin/linux/certbot-auto --help renew
     </echo>
-    <exec executable="./certbot-auto" osfamily="unix" dir="${basedir}/bin/${os.bin.dir}" failonerror="true">
+    <exec executable="./certbot-auto" os="${os.linux},${os.solaris}" dir="${basedir}/bin/${os.bin.dir}" failonerror="true">
      <arg value="renew"/>
      <arg value="--quiet"/>
@@ -1965,20 +2081,31 @@
     </exec>
 	
-	<!-- For rewewal on Windows, need to re-run the original (issuance) command and append "min-min-renew XX" to it,
-		where if it's within XX days of expiry, the certificate will get renewed.
-		See https://zerossl.com/usage.html#Certificate_renewal -->
-	<if><bool><istrue value="${current.os.iswindows}"/></bool>
-			
-		<input addproperty="https.other.domains">Enter a comma separated list of additional domains besides tomcat.server=${tomcat.server} that you registered on issuance, if any</input>
-		<condition property="https.cert.domains" value="${tomcat.server},${https.other.domains}" else="${tomcat.server}">
-			<and>
-			  <isset property="https.other.domains" />
-			  <not><matches string="${https.other.domains}" pattern="^\s*$"/></not>
-			</and>
-		</condition>
-		<antcall target="setup-https-cert-windows">
-			<param name="https.cert.renewal" value="--renew 10"/>			
-		</antcall>
-	</if>
+    <!-- For renewal on Windows or Mac, we use ZeroSSL as intermediary between GS3 and Let's Encrypt.
+	 And when using ZeroSSL we need to re-run the original (issuance) command and append "min-min-renew XX" to it,
+	 where if it's within XX days of expiry, the certificate will get renewed.
+	 See https://zerossl.com/usage.html#Certificate_renewal -->
+    <if><bool><or>
+	  <istrue value="${current.os.iswindows}"/>
+	  <istrue value="${current.os.ismac}"/>
+      </or></bool>
+      
+      <input addproperty="https.other.domains">Enter a comma separated list of additional domains besides tomcat.server=${tomcat.server} that you registered on issuance, if any</input>
+      <condition property="https.cert.domains" value="${tomcat.server},${https.other.domains}" else="${tomcat.server}">
+	<and>
+	  <isset property="https.other.domains" />
+	  <not><matches string="${https.other.domains}" pattern="^\s*$"/></not>
+	</and>
+	  </condition>
+      <if><bool><istrue value="${current.os.iswindows}"/></bool>
+	<antcall target="setup-https-cert-windows">
+	  <param name="https.cert.renewal" value="--renew 10"/>			
+	</antcall>
+	<else>
+	  <antcall target="setup-https-cert-mac">
+	    <param name="https.cert.renewal" value="--renew 10"/>			
+	  </antcall>
+	</else>
+      </if>
+    </if>
   </target>
 
@@ -2252,5 +2379,6 @@
 	see http://ant-contrib.sourceforge.net/tasks/tasks/osfamily.html -->
 
-    <exec executable="${catalina.home}/bin/startup.sh" os="${os.unix}" dir="${catalina.home}/bin" spawn="false">
+    <!--<exec executable="${catalina.home}/bin/startup.sh" os="${os.unix}" dir="${catalina.home}/bin" spawn="false">-->
+    <exec executable="${sudo.or.not}" os="${os.unix}" dir="${catalina.home}/bin" spawn="false">
       <!--<env key="GSDLOS" value="linux"/> do we need this?? -->
       <env key="GSDL3HOME" value="${basedir}"/>
@@ -2263,4 +2391,5 @@
       <env key="WNHOME" path="${wn.home}"/>
       <env key="FEDORA_HOME" path="${fedora.home}"/>
+      <arg value="${catalina.home}/bin/startup.sh"/>
     </exec>
     <exec executable="${catalina.home}/bin/startup.bat" osfamily="windows" dir="${catalina.home}/bin" spawn="true">
@@ -2309,7 +2438,9 @@
        stopped as happens when stop-tomcat is called consecutively. -->
   <target name="force-stop-tomcat" description="Shutdown only Tomcat" depends="init" if="tomcat.islocal">
-    <exec executable="${catalina.home}/bin/shutdown.sh" os="${os.unix}" dir="${catalina.home}/bin" spawn="false">
+    <!--<exec executable="${catalina.home}/bin/shutdown.sh" os="${os.unix}" dir="${catalina.home}/bin" spawn="false">-->
+    <exec executable="${sudo.or.not}" os="${os.unix}" dir="${catalina.home}/bin" spawn="false">
       <env key="FEDORA_HOME" path="${fedora.home}"/>
       <env key="CATALINA_HOME" value="${catalina.home}"/>
+      <arg value="${catalina.home}/bin/shutdown.sh"/>
       <arg line=">/dev/null 2>&amp;1"/>
     </exec>
