Skip to content
Snippets Groups Projects
Commit b2d53b08 authored by Peter Rotich's avatar Peter Rotich
Browse files

Merge pull request #437 from greezybacon/feature/packager


Reviewed-By: default avatarPeter Rotich <peter@osticket.com>
parents 51e2cef4 330ef8ac
No related branches found
No related tags found
No related merge requests found
......@@ -5,3 +5,6 @@ include/ost-config.php
.DS_Store
.vagrant
Vagrantfile
# Staging directory used for packaging script
stage
File moved
#!/usr/bin/env php
<?php
require_once "modules/class.module.php";
class Manager extends Module {
var $prologue =
"Manage one or more osTicket installations";
var $arguments = array(
'action' => "Action to be managed"
);
var $usage = '$script action [options] [arguments]';
var $autohelp = false;
function showHelp() {
foreach (glob(dirname(__file__).'/modules/*.php') as $script)
include_once $script;
global $registered_modules;
$this->epilog =
"Currently available modules follow. Use 'manage.php <module>
--help' for usage regarding each respective module:";
parent::showHelp();
echo "\n";
foreach ($registered_modules as $name=>$mod)
echo str_pad($name, 20) . $mod->prologue . "\n";
}
function run() {
if ($this->getOption('help') && !$this->getArgument('action'))
$this->showHelp();
else {
$action = $this->getArgument('action');
global $argv;
foreach ($argv as $idx=>$val)
if ($val == $action)
unset($argv[$idx]);
include_once dirname(__file__) . '/modules/' . $action . '.php';
$module = Module::getInstance($action);
$module->run();
}
}
}
if (php_sapi_name() != "cli")
die("Management only supported from command-line\n");
$manager = new Manager();
$manager->parseOptions();
$manager->run();
?>
<?php
class Option {
var $default = false;
function Option() {
call_user_func_array(array($this, "__construct"), func_get_args());
}
function __construct($options=false) {
list($this->short, $this->long) = array_slice($options, 0, 2);
$this->help = (isset($options['help'])) ? $options['help'] : "";
$this->action = (isset($options['action'])) ? $options['action']
: "store";
$this->dest = (isset($options['dest'])) ? $options['dest']
: substr($this->long, 2);
$this->type = (isset($options['type'])) ? $options['type']
: 'string';
$this->const = (isset($options['const'])) ? $options['const']
: null;
$this->default = (isset($options['default'])) ? $options['default']
: null;
$this->metavar = (isset($options['metavar'])) ? $options['metavar']
: 'var';
}
function hasArg() {
return $this->action != 'store_true'
&& $this->action != 'store_false';
}
function handleValue(&$destination, $args) {
$nargs = 0;
$value = array_shift($args);
if ($value[0] == '-')
$value = null;
elseif ($value)
$nargs = 1;
switch ($this->action) {
case 'store_true':
$value = true;
break;
case 'store_false':
$value = false;
break;
case 'store_const':
$value = $this->const;
break;
case 'store':
default:
if ($this->type == 'int')
$value = (int)$value;
break;
}
$destination[$this->dest] = $value;
return $nargs;
}
function toString() {
$short = explode(':', $this->short);
$long = explode(':', $this->long);
if ($this->nargs == '?')
$switches = sprintf(' %s [%3$s], %s[=%3$s]', $short[0],
$long[0], $this->metavar);
elseif ($this->hasArg())
$switches = sprintf(' %s %3$s, %s=%3$s', $short[0], $long[0],
$this->metavar);
else
$switches = sprintf(" %s, %s", $short[0], $long[0]);
$help = preg_replace('/\s+/', ' ', $this->help);
if (strlen($switches) > 24)
$help = "\n" . str_repeat(" ", 24) . $help;
else
$switches = str_pad($switches, 24);
$help = wordwrap($help, 54, "\n" . str_repeat(" ", 24));
return $switches . $help;
}
}
class Module {
var $options = array();
var $arguments = array();
var $prologue = "";
var $epilog = "";
var $usage = '$script [options] $args [arguments]';
var $autohelp = true;
function Module() {
call_user_func_array(array($this, '__construct'), func_get_args());
}
function __construct() {
$this->options['help'] = array("-h","--help",
'action'=>'store_true',
'help'=>"Display this help message");
foreach ($this->options as &$opt)
$opt = new Option($opt);
}
function showHelp() {
if ($this->prologue)
echo $this->prologue . "\n\n";
echo "Usage:\n";
global $argv;
echo " " . str_replace(
array('$script', '$args'),
array($argv[0], implode(' ', array_keys($this->arguments))),
$this->usage) . "\n";
ksort($this->options);
if ($this->options) {
echo "\nOptions:\n";
foreach ($this->options as $name=>$opt)
echo $opt->toString() . "\n";
}
if ($this->arguments) {
echo "\nArguments:\n";
foreach ($this->arguments as $name=>$help)
echo $name . "\n " . wordwrap(
preg_replace('/\s+/', ' ', $help), 76, "\n ");
}
if ($this->epilog) {
echo "\n\n";
$epilog = preg_replace('/\s+/', ' ', $this->epilog);
echo wordwrap($epilog, 76, "\n");
}
echo "\n";
}
function getOption($name, $default=false) {
$this->parseOptions();
if (isset($this->_options[$name]))
return $this->_options[$name];
else
return $default;
}
function getArgument($name, $default=false) {
$this->parseOptions();
foreach (array_keys($this->arguments) as $idx=>$arg)
if ($arg == $name && isset($this->_args[$idx]))
return $this->_args[$idx];
return $default;
}
function parseOptions() {
if (is_array($this->_options))
return;
global $argv;
list($this->_options, $this->_args) =
$this->parseArgs(array_slice($argv, 1));
foreach (array_keys($this->arguments) as $idx=>$name)
if (!isset($this->_args[$idx]))
$this->optionError($name . " is a required argument");
if ($this->autohelp && $this->getOption('help')) {
$this->showHelp();
die();
}
}
function optionError($error) {
echo "Error: " . $error . "\n\n";
$this->showHelp();
die();
}
/* abstract */ function run() {
}
/* static */ function register($action, $class) {
global $registered_modules;
$registered_modules[$action] = new $class();
}
/* static */ function getInstance($action) {
global $registered_modules;
return $registered_modules[$action];
}
function parseArgs($argv) {
$options = $args = array();
$argv = array_slice($argv, 0);
while ($arg = array_shift($argv)) {
if (strpos($arg, '=') !== false) {
list($arg, $value) = explode('=', $arg, 2);
array_unshift($argv, $value);
}
$found = false;
foreach ($this->options as $opt) {
if ($opt->short == $arg || $opt->long == $arg) {
if ($opt->handleValue($options, $argv))
array_shift($argv);
$found = true;
}
}
if (!$found && $arg[0] != '-')
$args[] = $arg;
}
return array($options, $args);
}
}
$registered_modules = array();
?>
<?php
require_once dirname(__file__) . "/class.module.php";
class Unpacker extends Module {
var $prologue = "Unpacks osTicket into target install path";
var $epilog =
"Copies an unpacked osticket tarball or zipfile into a production
location, optionally placing the include/ folder in a separate
location if requested";
var $options = array(
'include' => array('-i','--include', 'metavar'=>'path', 'help'=>
"The include/ folder, which contains the bulk of osTicket's source
code can be located outside of the install path. This is recommended
for better security. If you would like to install the include/
folder somewhere else, give the path here. Note that the full
path is assumed, so give path/to/include/ to unpack the source
code in that folder. The folder will be automatically created if
it doesn't already exist."
),
);
var $arguments = array(
'install-path' =>
"The destination for osTicket to reside. Use the --include
option to specify destination of the include/ folder, if the
administrator should chose to locate it separate from the
main installation path.",
);
function find_upload_folder() {
# Hop up to the root folder
$start = dirname(__file__);
for (;;) {
if (is_dir($start . '/upload')) break;
$start .= '/..';
}
return realpath($start.'/upload');
}
function change_include_dir($include_path) {
# Read the main.inc.php script
$main_inc_php = $this->destination . '/main.inc.php';
$lines = explode("\n", file_get_contents($main_inc_php));
# Try and use ROOT_PATH
if (strpos($include_path, $this->destination) === 0)
$include_path = "ROOT_PATH . '" .
str_replace($this->destination, '', $include_path) . "'";
else
$include_path = "'$include_path'";
# Find the line that defines INCLUDE_DIR
foreach ($lines as &$line) {
if (preg_match("/(\s*)define\s*\(\s*'INCLUDE_DIR'/", $line, $match)) {
# Replace the definition with the new locatin
$line = $match[1] . "define('INCLUDE_DIR', "
. $include_path
. "); // Set by installer";
break;
}
}
if (!file_put_contents($main_inc_php, implode("\n", $lines)))
die("Unable to configure location of INCLUDE_DIR in main.inc.php\n");
}
function exclude($pattern, $match) {
if (!$pattern) {
return false;
} elseif (is_array($pattern)) {
foreach ($pattern as $p)
if (fnmatch($p, $match))
return true;
} else {
return fnmatch($pattern, $match);
}
return false;
}
function unpackage($folder, $destination, $recurse=true, $exclude=false) {
foreach (glob($folder, GLOB_BRACE|GLOB_NOSORT) as $file) {
if ($this->exclude($exclude, $file))
continue;
if (is_file($file)) {
if (!is_dir($destination))
mkdir($destination, 0751, true);
copy($file, $destination . '/' . basename($file));
}
}
if ($recurse) {
foreach (glob(dirname($folder).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
if ($this->exclude($exclude, $dir))
continue;
$this->unpackage(
dirname($folder).'/'.basename($dir).'/'.basename($folder),
$destination.'/'.basename($dir),
$recurse - 1, $exclude);
}
}
}
function get_include_dir() {
$main_inc_php = $this->destination . '/main.inc.php';
$lines = preg_grep("/define\s*\(\s*'INCLUDE_DIR'/",
explode("\n", file_get_contents($main_inc_php)));
// NOTE: that this won't work for crafty folks who have a define or some
// variable in the value of their include path
if (!defined('ROOT_DIR')) define('ROOT_DIR', $this->destination . '/');
foreach ($lines as $line)
eval($line);
return INCLUDE_DIR;
}
function run() {
$this->destination = $this->getArgument('install-path');
if (!is_dir($this->destination))
if (!mkdir($this->destination, 0751, true))
$this->die("Destination path does not exist and cannot be created");
# Determine if this is an upgrade, and if so, where the include/
# folder is currently located
$upgrade = file_exists("{$this->destination}/main.inc.php");
# Locate the upload folder
$upload = $this->find_upload_folder();
# Unpack the upload folder to the destination, except the include folder
if ($upgrade)
# Get the current value of the INCLUDE_DIR before overwriting
# main.inc.php
$include = $this->get_include_dir();
$this->unpackage("$upload/*", $this->destination, -1, "*include");
if (!$upgrade) {
if ($this->getOption('include')) {
$location = $this->getOption('include');
if (!is_dir("$location/"))
if (!mkdir("$location/", 0751, true))
die("Unable to create folder for include/ files\n");
$this->unpackage("$upload/include/*", $location, -1);
$this->change_include_dir($location);
}
else
$this->unpackage("$upload/include/*", "{$this->destination}/include", -1);
}
else {
$this->unpackage("$upload/include/*", $include, -1);
# Change the new main.inc.php to reflect the location of the
# include/ directory
$this->change_include_dir($include);
}
}
}
Module::register('unpack', 'Unpacker');
#!/usr/bin/env php
<?php
if (php_sapi_name() != 'cli')
die("Only command-line packaging is supported");
$stage_folder = "stage";
$stage_path = dirname(__file__) . '/' . $stage_folder;
function get_osticket_root_path() {
# Hop up to the root folder
$start = dirname(__file__);
for (;;) {
if (file_exists($start . '/main.inc.php')) break;
$start .= '/..';
}
return realpath($start);
}
# Check PHP syntax across all php files
function glob_recursive($pattern, $flags = 0) {
$files = glob($pattern, $flags);
foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
$files = array_merge($files,
glob_recursive($dir.'/'.basename($pattern), $flags));
}
return $files;
}
$root = get_osticket_root_path();
function exclude($pattern, $match) {
if (is_array($pattern)) {
foreach ($pattern as $p)
if (fnmatch($p, $match))
return true;
}
else
return fnmatch($pattern, $match);
return false;
}
function package($pattern, $destination, $recurse=false, $exclude=false) {
global $root, $stage_path;
$search = $root . '/' . $pattern;
echo "Packaging " . $search . "\n";
foreach (glob($search, GLOB_BRACE|GLOB_NOSORT) as $file) {
if (is_file($file)) {
if ($exclude && exclude($exclude, $file))
continue;
if (!is_dir("$stage_path/$destination"))
mkdir("$stage_path/$destination", 0777, true);
copy($file, $stage_path . '/' . $destination . '/' . basename($file));
}
}
if ($recurse) {
foreach (glob(dirname($search).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
if ($exclude && exclude($exclude, $dir))
continue;
package(dirname($pattern).'/'.basename($dir).'/'.basename($pattern),
$destination.'/'.basename($dir),
$recurse-1, $exclude);
}
}
}
# Create the stage folder for the install files
if (!is_dir($stage_path))
mkdir($stage_path);
else {
$dirs = array();
foreach (glob_recursive($stage_path . '/*') as $file)
if (is_dir($file))
$dirs[] = $file;
else
unlink($file);
sort($dirs);
foreach (array_reverse($dirs) as $dir)
rmdir($dir);
}
# Source code goes into 'upload'
mkdir($stage_path . '/upload');
# Load the root directory files
package("*.php", 'upload/');
# Load the client interface
foreach (array('assets','css','images','js') as $dir)
package("$dir/*", "upload/$dir", -1, "*less");
# Load the knowledgebase
package("kb/*.php", "upload/kb");
# Load the staff interface
package("scp/*.php", "upload/scp/", -1);
foreach (array('css','images','js') as $dir)
package("$dir/*", "upload/scp/$dir", -1);
# Load in the scripts
mkdir("$stage_path/scripts/");
package("setup/scripts/*", "scripts/", -1, "*stage");
# Load the heart of the system
package("include/*.php", "upload/include", -1);
# And the sql patches
package("include/upgrader/*.sql", "upload/include/upgrader", -1);
# Include the installer
package("setup/*.{php,txt}", "upload/setup", -1, array("*scripts","*test","*stage"));
foreach (array('css','images','js') as $dir)
package("setup/$dir/*", "upload/setup/$dir", -1);
package("setup/inc/sql/*.{sql,md5}", "upload/setup/inc/sql", -1);
# Load the license and documentation
package("*.{txt,md}", "");
# Make an archive of the stage folder
$version_info = preg_grep('/THIS_VERSION/',
explode("\n", file_get_contents("$root/main.inc.php")));
foreach ($version_info as $line)
eval($line);
$pwd = getcwd();
chdir($stage_path);
shell_exec("tar cjf '$pwd/osticket-".THIS_VERSION.".tar.bz2' *");
shell_exec("zip -r '$pwd/osticket-".THIS_VERSION.".zip' *");
chdir($pwd);
?>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment