You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
334 lines
14 KiB
334 lines
14 KiB
<?php
|
|
/*********************************************************************
|
|
class.installer.php
|
|
|
|
osTicket Intaller - installs the latest version.
|
|
|
|
Peter Rotich <peter@osticket.com>
|
|
Copyright (c) 2006-2013 osTicket
|
|
http://www.osticket.com
|
|
|
|
Released under the GNU General Public License WITHOUT ANY WARRANTY.
|
|
See LICENSE.TXT for details.
|
|
|
|
vim: expandtab sw=4 ts=4 sts=4:
|
|
**********************************************************************/
|
|
require_once INCLUDE_DIR.'class.migrater.php';
|
|
require_once INCLUDE_DIR.'class.setup.php';
|
|
require_once INCLUDE_DIR.'class.i18n.php';
|
|
|
|
class Installer extends SetupWizard {
|
|
|
|
var $config;
|
|
|
|
function __construct($configfile) {
|
|
$this->config =$configfile;
|
|
$this->errors=array();
|
|
}
|
|
|
|
function getConfigFile() {
|
|
return $this->config;
|
|
}
|
|
|
|
function config_exists() {
|
|
return ($this->getConfigFile() && file_exists($this->getConfigFile()));
|
|
}
|
|
|
|
function config_writable() {
|
|
return ($this->getConfigFile() && is_writable($this->getConfigFile()));
|
|
}
|
|
|
|
function check_config() {
|
|
return ($this->config_exists() && $this->config_writable());
|
|
}
|
|
|
|
//XXX: Latest version insall logic...no carry over.
|
|
function install($vars) {
|
|
|
|
$this->errors=$f=array();
|
|
|
|
$f['name'] = array('type'=>'string', 'required'=>1, 'error'=>__('Name required'));
|
|
$f['email'] = array('type'=>'email', 'required'=>1, 'error'=>__('Valid email required'));
|
|
$f['fname'] = array('type'=>'string', 'required'=>1, 'error'=>__('First name required'));
|
|
$f['lname'] = array('type'=>'string', 'required'=>1, 'error'=>__('Last name required'));
|
|
$f['admin_email'] = array('type'=>'email', 'required'=>1, 'error'=>__('Valid email required'));
|
|
$f['username'] = array('type'=>'username', 'required'=>1, 'error'=>__('Username required'));
|
|
$f['passwd'] = array('type'=>'string', 'required'=>1, 'error'=>__('Password required'));
|
|
$f['passwd2'] = array('type'=>'string', 'required'=>1, 'error'=>__('Confirm Password'));
|
|
$f['prefix'] = array('type'=>'string', 'required'=>1, 'error'=>__('Table prefix required'));
|
|
$f['dbhost'] = array('type'=>'string', 'required'=>1, 'error'=>__('Host name required'));
|
|
$f['dbname'] = array('type'=>'string', 'required'=>1, 'error'=>__('Database name required'));
|
|
$f['dbuser'] = array('type'=>'string', 'required'=>1, 'error'=>__('Username required'));
|
|
$f['dbpass'] = array('type'=>'string', 'required'=>1, 'error'=>__('Password required'));
|
|
|
|
$vars = array_map('trim', $vars);
|
|
|
|
if(!Validator::process($f,$vars,$this->errors) && !$this->errors['err'])
|
|
$this->errors['err'] = sprintf('%s — %s',
|
|
__('Missing or invalid data'),
|
|
__('Correct any errors below and try again'));
|
|
|
|
|
|
//Staff's email can't be same as system emails.
|
|
if($vars['admin_email'] && $vars['email'] && !strcasecmp($vars['admin_email'],$vars['email']))
|
|
$this->errors['admin_email']=__('Conflicts with system email above');
|
|
//Admin's pass confirmation.
|
|
if(!$this->errors && strcasecmp($vars['passwd'],$vars['passwd2']))
|
|
$this->errors['passwd2']=__('Passwords do not match');
|
|
|
|
//Check table prefix underscore required at the end!
|
|
if($vars['prefix'] && substr($vars['prefix'], -1)!='_')
|
|
$this->errors['prefix']=__('Bad prefix. Must have underscore (_) at the end. e.g \'ost_\'');
|
|
|
|
//Make sure admin username is not very predictable. XXX: feels dirty but necessary
|
|
if(!$this->errors['username'] && in_array(strtolower($vars['username']),array('admin','admins','username','osticket')))
|
|
$this->errors['username']=__('Bad username');
|
|
|
|
// Support port number specified in the hostname with a colon (:)
|
|
list($host, $port) = explode(':', $vars['dbhost']);
|
|
if ($port && is_numeric($port) && ($port < 1 || $port > 65535))
|
|
$this->errors['db'] = __('Invalid database port number');
|
|
|
|
//MYSQL: Connect to the DB and check the version & database (create database if it doesn't exist!)
|
|
if(!$this->errors) {
|
|
if(!db_connect($vars['dbhost'],$vars['dbuser'],$vars['dbpass']))
|
|
$this->errors['db']=sprintf(__('Unable to connect to MySQL server: %s'), db_connect_error());
|
|
elseif(explode('.', db_version()) < explode('.', SetupWizard::getMySQLVersion()))
|
|
$this->errors['db']=sprintf(__('osTicket requires MySQL %s or later!'),SetupWizard::getMySQLVersion());
|
|
elseif(!db_select_database($vars['dbname']) && !db_create_database($vars['dbname'])) {
|
|
$this->errors['dbname']=__("Database doesn't exist");
|
|
$this->errors['db']=__('Unable to create the database.');
|
|
} elseif(!db_select_database($vars['dbname'])) {
|
|
$this->errors['dbname']=__('Unable to select the database');
|
|
} else {
|
|
//Abort if we have another installation (or table) with same prefix.
|
|
$sql = 'SELECT * FROM `'.$vars['prefix'].'config` LIMIT 1';
|
|
if(db_query($sql, false)) {
|
|
$this->errors['err'] = __('We have a problem - another installation with same table prefix exists!');
|
|
$this->errors['prefix'] = __('Prefix already in-use');
|
|
} else {
|
|
//Try changing charset and collation of the DB - no bigie if we fail.
|
|
db_query('ALTER DATABASE '.$vars['dbname'].' DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci', false);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************** We're ready to install ************************/
|
|
define('ADMIN_EMAIL',$vars['admin_email']); //Needed to report SQL errors during install.
|
|
define('TABLE_PREFIX',$vars['prefix']); //Table prefix
|
|
if (!defined('SECRET_SALT'))
|
|
define('SECRET_SALT',md5(TABLE_PREFIX.ADMIN_EMAIL));
|
|
Bootstrap::defineTables(TABLE_PREFIX);
|
|
Bootstrap::loadCode();
|
|
|
|
// Check password against password policy (after loading code)
|
|
try {
|
|
PasswordPolicy::checkPassword($vars['passwd'], null);
|
|
}
|
|
catch (BadPassword $e) {
|
|
$this->errors['passwd'] = $e->getMessage();
|
|
}
|
|
|
|
// bailout on errors.
|
|
if ($this->errors)
|
|
return false;
|
|
|
|
|
|
$debug = true; // Change it to false to squelch SQL errors.
|
|
|
|
//Last minute checks.
|
|
if(!file_exists($this->getConfigFile()) || !($configFile=file_get_contents($this->getConfigFile())))
|
|
$this->errors['err']=__('Unable to read config file. Permission denied! (#2)');
|
|
elseif(!($fp = @fopen($this->getConfigFile(),'r+')))
|
|
$this->errors['err']=__('Unable to open config file for writing. Permission denied! (#3)');
|
|
|
|
else {
|
|
$streams = DatabaseMigrater::getUpgradeStreams(INCLUDE_DIR.'upgrader/streams/');
|
|
foreach ($streams as $stream=>$signature) {
|
|
$schemaFile = INC_DIR."streams/$stream/install-mysql.sql";
|
|
if (!file_exists($schemaFile) || !($fp2 = fopen($schemaFile, 'rb')))
|
|
$this->errors['err'] = sprintf(
|
|
__('%s: Internal error occurred - please make sure your download is the latest (#1)'),
|
|
$stream);
|
|
elseif (
|
|
// TODO: Make the hash algo configurable in the streams
|
|
// configuration ( core : md5 )
|
|
!($hash = md5(fread($fp2, filesize($schemaFile))))
|
|
|| strcasecmp($signature, $hash))
|
|
$this->errors['err'] = sprintf(
|
|
__('%s: Unknown or invalid schema signature (%s .. %s)'),
|
|
$stream,
|
|
$signature, $hash);
|
|
elseif (!$this->load_sql_file($schemaFile, $vars['prefix'], true, $debug))
|
|
$this->errors['err'] = sprintf(
|
|
__('%s: Error parsing SQL schema! Get help from developers (#4)'),
|
|
$stream);
|
|
}
|
|
}
|
|
|
|
if ($this->errors)
|
|
return false;
|
|
|
|
// TODO: Use language selected from install worksheet
|
|
$i18n = new Internationalization($vars['lang_id']);
|
|
$i18n->loadDefaultData();
|
|
|
|
Signal::send('system.install', $this);
|
|
|
|
list($sla_id) = Sla::objects()->order_by('id')->values_flat('id')->first();
|
|
list($dept_id) = Dept::objects()->order_by('id')->values_flat('id')->first();
|
|
list($role_id) = Role::objects()->order_by('id')->values_flat('id')->first();
|
|
list($schedule_id) = Schedule::objects()->order_by('id')->values_flat('id')->first();
|
|
|
|
$sql='SELECT `tpl_id` FROM `'.TABLE_PREFIX.'email_template_group` ORDER BY `tpl_id` LIMIT 1';
|
|
$template_id_1 = db_result(db_query($sql, false));
|
|
|
|
// Create admin user.
|
|
$staff = Staff::create(array(
|
|
'isactive' => 1,
|
|
'isadmin' => 1,
|
|
'max_page_size' => 25,
|
|
'dept_id' => $dept_id,
|
|
'role_id' => $role_id,
|
|
'email' => $vars['admin_email'],
|
|
'firstname' => Format::htmlchars($vars['fname']),
|
|
'lastname' => Format::htmlchars($vars['lname']),
|
|
'username' => $vars['username'],
|
|
));
|
|
$staff->updatePerms(array(
|
|
User::PERM_CREATE,
|
|
User::PERM_EDIT,
|
|
User::PERM_DELETE,
|
|
User::PERM_MANAGE,
|
|
User::PERM_DIRECTORY,
|
|
Organization::PERM_CREATE,
|
|
Organization::PERM_EDIT,
|
|
Organization::PERM_DELETE,
|
|
FAQ::PERM_MANAGE,
|
|
Email::PERM_BANLIST,
|
|
Dept::PERM_DEPT,
|
|
Staff::PERM_STAFF,
|
|
));
|
|
$staff->setPassword($vars['passwd']);
|
|
if (!$staff->save()) {
|
|
$this->errors['err'] = __('Unable to create admin user (#6)');
|
|
return false;
|
|
}
|
|
|
|
// Extended Access
|
|
foreach (Dept::objects()
|
|
->filter(Q::not(array('id' => $dept_id)))
|
|
->values_flat('id') as $row) {
|
|
$da = new StaffDeptAccess(array(
|
|
'dept_id' => $row[0],
|
|
'role_id' => $role_id
|
|
));
|
|
$staff->dept_access->add($da);
|
|
}
|
|
$staff->dept_access->saveAll();
|
|
|
|
// Create default emails!
|
|
$email = $vars['email'];
|
|
list(,$domain) = explode('@', $vars['email']);
|
|
foreach (array(
|
|
"Support" => $email,
|
|
"osTicket Alerts" => "alerts@$domain",
|
|
'' => "noreply@$domain",
|
|
) as $name => $mailbox) {
|
|
$mb = Email::create(array(
|
|
'name' => $name,
|
|
'email' => $mailbox,
|
|
'dept_id' => $dept_id,
|
|
));
|
|
$mb->save();
|
|
if ($mailbox == $email)
|
|
$support_email_id = $mb->email_id;
|
|
if ($mailbox == "alerts@$domain")
|
|
$alert_email_id = $mb->email_id;
|
|
}
|
|
|
|
//Create config settings---default settings!
|
|
$defaults = array(
|
|
'default_email_id'=>$support_email_id,
|
|
'alert_email_id'=>$alert_email_id,
|
|
'default_dept_id'=>$dept_id,
|
|
'default_sla_id'=>$sla_id,
|
|
'schedule_id'=>$schedule_id,
|
|
'default_template_id'=>$template_id_1,
|
|
'default_timezone' => $vars['timezone'] ?: date_default_timezone_get(),
|
|
'admin_email'=>$vars['admin_email'],
|
|
'schema_signature'=>$streams['core'],
|
|
'helpdesk_url'=>URL,
|
|
'helpdesk_title'=>Format::htmlchars($vars['name'], true)
|
|
);
|
|
|
|
$config = new Config('core');
|
|
if (!$config->updateAll($defaults))
|
|
$this->errors['err']=__('Unable to create config settings').' (#7)';
|
|
|
|
// Set company name
|
|
require_once(INCLUDE_DIR.'class.company.php');
|
|
$company = new Company();
|
|
$company->getForm()->setAnswer('name', $vars['name']);
|
|
$company->getForm()->save();
|
|
|
|
foreach ($streams as $stream => $signature) {
|
|
if ($stream != 'core') {
|
|
$config = new Config($stream);
|
|
if (!$config->update('schema_signature', $signature))
|
|
$this->errors['err'] = __('Unable to create config settings').' (#8)';
|
|
}
|
|
}
|
|
|
|
if ($this->errors)
|
|
return false; //Abort on internal errors.
|
|
|
|
|
|
//Rewrite the config file - MUST be done last to allow for installer recovery.
|
|
$configFile = strtr($configFile, array(
|
|
"define('OSTINSTALLED',FALSE);" => "define('OSTINSTALLED',TRUE);",
|
|
'%ADMIN-EMAIL' => $vars['admin_email'],
|
|
'%CONFIG-DBHOST' => $vars['dbhost'],
|
|
'%CONFIG-DBNAME' => $vars['dbname'],
|
|
'%CONFIG-DBUSER' => $vars['dbuser'],
|
|
'%CONFIG-DBPASS' => $vars['dbpass'],
|
|
'%CONFIG-PREFIX' => $vars['prefix'],
|
|
'%CONFIG-SIRI' => Misc::randCode(32),
|
|
));
|
|
if (!$fp || !ftruncate($fp,0) || !fwrite($fp,$configFile)) {
|
|
$this->errors['err']=__('Unable to write to config file. Permission denied! (#5)');
|
|
return false;
|
|
}
|
|
@fclose($fp);
|
|
|
|
/************* Make the system happy ***********************/
|
|
global $cfg;
|
|
$cfg = new OsticketConfig();
|
|
|
|
//Create a ticket to make the system warm and happy.
|
|
$errors = array();
|
|
$ticket_vars = $i18n->getTemplate('templates/ticket/installed.yaml')
|
|
->getData();
|
|
$ticket = Ticket::create($ticket_vars, $errors, 'api', false, false);
|
|
|
|
if ($ticket
|
|
&& ($org = Organization::objects()->order_by('id')->one())
|
|
) {
|
|
$user = User::lookup($ticket->getOwnerId());
|
|
$user->setOrganization($org);
|
|
}
|
|
|
|
//TODO: create another personalized ticket and assign to admin??
|
|
|
|
//Log a message.
|
|
$msg=__("Congratulations osTicket basic installation completed!\n\nThank you for choosing osTicket!");
|
|
$sql='INSERT INTO '.TABLE_PREFIX.'syslog SET created=NOW(), updated=NOW(), log_type="Debug" '
|
|
.', title="osTicket installed!"'
|
|
.', log='.db_input($msg)
|
|
.', ip_address='.db_input($_SERVER['REMOTE_ADDR']);
|
|
db_query($sql, false);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
?>
|