#!/usr/bin/php
<?php
	chdir(__DIR__);
	error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);

	define("DAY", 86400);

	function __autoload($class_name) {
		$library = __DIR__."/libraries/".strtolower($class_name).".php";

		if (file_exists($library) == false) {
			printf("Error including library for class %s.\n", $class_name);
			exit;
		}

		include($library);
	}

	/* Configuration
	 */
	$config = new config("letsencrypt.conf");
	foreach ($config->content as $key => $value) {
		define($key, $value);
	}

	/* Show help information
	 */
	function show_help($executable) {
		printf("Usage: %s <command>\n", $executable);
		printf("Commands: register: Register your account key at the Let's Encrypt CA.\n");
		printf("          request <hostname> [<cert.pem>]: Request new certificate for website.\n");
		printf("          expire: show number of days left before certificate expires.\n");
		printf("          renew [restart]: Renew the almost expired Let's Encrypt certificates\n");
		printf("                           in Hiawatha's certificate directory.\n");
		printf("          revoke <cert.pem>: Revoke the certificate.\n");
		printf("\n");
	}

	/* Check configuration
	 */
	if (ACCOUNT_EMAIL_ADDRESS == "info@example.org") {
		exit("Read README.txt before using this tool.\n");
	}

	/* Account key
	 */
	if (file_exists("account.key") == false) {
		printf("Generating account key.\n");
		$account_key = new RSA(ACCOUNT_RSA_KEY_SIZE);
		if (($fp = fopen("account.key", "w")) === false) {
			exit(" - Error writing account.key.\n");
		}
		fputs($fp, $account_key->private_key);
		fclose($fp);
		chmod("account.key", 0400);
	} else {
		$account_key = new RSA("account.key");
	}

	/* Let's Encrypt
	 */
	$lets_encrypt = new LetsEncrypt($account_key);

	/* Execute commands
	 */
	$command = $argv[1];

	switch ($command) {
		case "register":
			/* Account registration
			 */
			printf("Registering account.\n");
			$lets_encrypt->register_account(ACCOUNT_EMAIL_ADDRESS, LE_CA_TERMS);
			break;
		case "request":
			/* Request certificate
			 */
			if (count($argv) < 3) {
				show_help($argv[0]);
				break;
			}

			$lets_encrypt->request_certificate($argv[2], $argv[3]);
			break;
		case "renew":
		case "expire":
			/* Renew certificates
			 */
			$lets_encrypt_issuers = explode("|", LE_ISSUERS);

			$now = time();
			$restart = false;

			$cert_files = $lets_encrypt->get_certificate_files();

			foreach ($cert_files as $cert_file) {
				/* Read certificate
				 */
				if (($cert = file_get_contents($cert_file)) == false) {
					printf(" - Error reading %s.\n", $cert_file);
					continue;
				}
				if (($x509 = openssl_x509_parse($cert)) == false) {
					continue;
				}

				/* Check if issuer is Let's Encrypt
				 */
				if (in_array($x509["issuer"]["CN"], $lets_encrypt_issuers) == false) {
					continue;
				}

				if ($command == "expire") {
					$days_left = ($x509["validTo_time_t"] - $now) / DAY;
					printf("%-35s %2d\n", $x509["subject"]["CN"], $days_left);
				} else {
					/* Check if certificate is ready to be renewed
					 */
					if ($x509["validTo_time_t"] - RENEWAL_EXPIRE_THRESHOLD * DAY > $now) {
						continue;
					}

					/* Renew certificate
					 */
					printf("Renewing certificate for %s.\n", $x509["subject"]["CN"]);
					$reuse_key = in_array(strtolower(RENEWAL_REUSE_KEY), array("yes", "true"));
					if ($lets_encrypt->request_certificate($x509["subject"]["CN"], $cert_file, $reuse_key) == false) {
						continue;
					}

					/* Renewal script
					 */
					$info = pathinfo($cert_file);
					$renewal_script = RENEWAL_SCRIPT_DIR."/".$info["filename"];
					if (file_exists($renewal_script)) {
						printf("Running script %s.\n", $renewal_script);
						system($renewal_script);
					}

					$restart = true;
				}
			}

			if ($restart) {
				if ($argv[2] == "restart") {
					system(HIAWATHA_RESTART_COMMAND);
				}

				exit(1);
			}
			break;
		case "revoke":
			/* Revoke certificate
			 */
			if (count($argv) < 3) {
				show_help($argv[0]);
				break;
			}

			printf("Revoking certificate.\n");
			$lets_encrypt->revoke_certificate($argv[2]);
			break;
		default:
			/* Show help
			 */
			show_help($argv[0]);
			break;
	}
?>
