#!/usr/bin/env php copy_patch(trim($address))){ return; } } $this->remove_temporals(); if ($patch == '') { $patch = basename($address); } if (!$this->untar_patch($patch)) { return false; } // Backup files listed on changes.log file echo "Backup files\n"; $changeLog = fopen(PROCESSMAKER_PATH . 'shared/patches/processmaker/changes.log', 'r'); while (!feof($changeLog)) { $linea = trim(fgets($changeLog)); // Backup file and then replace $s1 = substr(PROCESSMAKER_PATH, 0, strpos(PROCESSMAKER_PATH, 'processmaker')) . $linea; // Location where must be the original $s2 = PROCESSMAKER_PATH . 'shared/patches/original/' . $linea; if (!is_file($s2)) { if (!is_dir(substr($s2, 0, strrpos($s2, "/")))) { mkdir(substr($s2, 0, strrpos($s2, "/")), 0777, true); } if (is_file($s1)) { echo $s1."\n"; copy($s1, $s2); } } } fclose($changeLog); echo "Apply changes ...\n"; $this->copy_directory(PROCESSMAKER_PATH . '/shared/patches/processmaker', PROCESSMAKER_PATH); $this->remove_temporals(); echo "Patch installed sucessfully\n"; } /** * Utar the hotfix file * @return boolean true or false */ public function untar_patch($patch) { echo "Untar patch file\n"; $p = new PharData(PROCESSMAKER_PATH . 'shared/patches/'.$patch); if ($p->extractTo(PROCESSMAKER_PATH . 'shared/patches')) { echo "Untar sucessfull\n"; return true; } else { echo "Error to untar patch file.\n"; return false; } } /** * This method list of origin version and patches */ public function list_patches() { echo "The available versions are:\n"; $original_version = ''; if (is_file(PROCESSMAKER_PATH . 'shared/patches/original/processmaker/workflow/engine/' . 'methods/login/version-pmos.php')) { $original_version = $this->get_version(PROCESSMAKER_PATH . 'shared/patches/original/processmaker/workflow/engine/' . 'methods/login/version-pmos.php'); } else { $original_version = $this->get_version(PROCESSMAKER_PATH . 'workflow/engine/methods/login/version-pmos.php'); } $current_installation = $this->get_version(PROCESSMAKER_PATH . 'workflow/engine/methods/login/version-pmos.php'); echo "Original version:\n"; echo $original_version . "\n"; echo "Patch installed:\n"; $directory = opendir(PROCESSMAKER_PATH . 'shared/patches'); while ($file = readdir($directory)) { if (!is_dir($file) && strpos($file,'.tar')) { if ( str_replace($file,'.tar','')==$current_installation) { echo $file . " *\n"; } else { echo $file . "\n"; } } } } /** * This method is used to obtain the current version or the original * @param type $address File location with version * @return type Returns the version of ProcessMaker requested */ private function get_version($address) { $result = ''; $file = fopen($address, 'r'); while (!feof($file)) { $linea = trim(fgets($file)); if (strpos($linea, 'PM_VERSION')) { $result = substr($linea, strpos($linea, ", ") + 3); $result = substr($result,0,strlen($result)-3); } } fclose($file); return $result; } /** * You change the version of a hotfix available * @param type $hotfix_version */ public function rollback_patch($patch_version) { echo "Rollback to ".$patch_version."\n"; $this->register('rollback_patch ' . $patch_version); $this->rollback_origin(); if (strpos($patch_version, '.tar')) { $this->add_patch('', $patch_version); } } /** * Installation returns to its original state. */ private function rollback_origin() { echo "Rollback to original state\n"; $this->copy_directory(PROCESSMAKER_PATH . '/shared/patches/original/processmaker', PROCESSMAKER_PATH); echo "Rollback to original state sucessfull\n"; } /** * Copy a entire directory * @param type $source Location of files to copy * @param type $target Destination to be copied */ private function copy_directory($source, $target) { if (is_dir($source)) { @mkdir($target); $d = dir($source); while (FALSE !== ( $entry = $d->read() )) { if ($entry == '.' || $entry == '..') { continue; } $Entry = $source . '/' . $entry; if (is_dir($Entry)) { $this->copy_directory($Entry, $target . '/' . $entry); continue; } copy($Entry, $target . '/' . $entry); } $d->close(); } else { copy($source, $target); } } /** * This function remove a folder complete * @param type $address Folder to remove * @return type true or false */ private function delete_directory($address) { $files = array_diff(scandir($address), array('.', '..')); foreach ($files as $file) { (is_dir("$address/$file")) ? $this->delete_directory("$address/$file") : unlink("$address/$file"); } return rmdir($address); } /** * Remove the temporal folder for install hotfix */ private function remove_temporals() { echo "Removing temporals files\n"; if (is_Dir(PROCESSMAKER_PATH . "shared/patches/processmaker")) { $this->delete_directory(PROCESSMAKER_PATH . "shared/patches/processmaker"); } } /** * Copy the hotfix and create shared/hotfixes * @param type $address Ubicación del hotfix * @return boolean falso en caso de q no exista el archivo hotfix */ private function copy_patch($address) { echo "Copy hotfix file to shared/hotfixes\n"; $this->verify_directory(); // Verify that the address is correct hotfix if (is_file($address)) { copy($address, PROCESSMAKER_PATH . "shared/patches/" . basename($address)); } else { echo 'The file route is incorrect, please check the route\n'; return false; } return true; } private function verify_directory(){ // Verify that there is a shared/hotfixes directory exist if (!is_Dir(PROCESSMAKER_PATH . "shared/patches")) { mkdir(PROCESSMAKER_PATH . "shared/patches", 0777); } } /** * Add a log message in the patches.log file * @param type $log */ private function register($log) { $this->verify_directory(); $file = fopen(PROCESSMAKER_PATH . 'shared/patches/patches.log', "a"); $message = date('l jS \of F Y h:i:s A') . ' ' . $log . PHP_EOL; fwrite($file, $message); fclose($file); } } define('PROCESSMAKER_PATH', $scriptDir); $p = new Patch(); switch (isset($argv[1]) ? $argv[1] : "-h") { case "-l": $p->list_patches(); break; case "-a": $p->add_patch($argv[2]); break; case "-r": $p->rollback_patch($argv[2]); break; case "-h": default: echo "-a /patch.tar _add/install a patch from a file parameter\n"; echo "-r patch_name _remove/uninstall a patch\n"; echo "-l _list all patches installed in processmaker\n"; echo "-h _help list the options in the patch tool\n"; }