*/
class Installer extends Controller
{
public $path_config;
public $path_languages;
public $path_plugins;
public $path_xmlforms;
public $path_shared;
public $path_sep;
public $link; #resource for database connection
public function __construct()
{
$this->path_config = PATH_CORE.'config/';
$this->path_languages = PATH_CORE.'content/languages/';
$this->path_plugins = PATH_CORE.'plugins/';
$this->path_xmlforms = PATH_CORE.'xmlform/';
$this->path_public = PATH_HOME.'public_html/index.html';
$this->path_shared = PATH_TRUNK.'shared/';
$this->path_sep = PATH_SEP;
}
public function index($httpData)
{
$step1_txt = 'If any of these items is not supported (marked as No) then please take actions to correct them.
' .
'Failure to do so could lead to your ProcessMaker installation not functioning correctly!
' .
//'(*) MSSQL Support is optional.
' .
'(*) OpenSSL is optional.
' .
'(*) LDAP is optional.';
$step2_txt = 'These settings are recommended for PHP in order to ensure full compatibility with ProcessMaker. <> ' .
'However, ProcessMaker still operate if your settings do not quite match the recommended';
$step3_txt = 'In order for ProcessMaker to work correctly, it needs to be able read and write to certain directories and their files.
' .
'Make sure to give read and write access to the directories listed below and all their subdirectories and files.';
$step4_txt = 'ProcessMaker stores all of its data in a database. Enter the address and port number used by the database. Also enter' .
'the username and password of the database user who will set up the databases used by ProcessMaker
';
$step5_txt = 'ProcessMaker uses workspaces to store data in the database. Please enter a valid workspace name and a username and password to login'.
' as the administrator.';
$step6_txt = 'xxx';
$licenseContent = file_get_contents(PATH_TRUNK . 'LICENSE.txt');
$this->includeExtJS('installer/CardLayout', false);
$this->includeExtJS('installer/Wizard', false);
$this->includeExtJS('installer/Header', false);
$this->includeExtJS('installer/Card', false);
$this->includeExtJS('installer/installer_cards');
$this->includeExtJS('installer/main', false);
$this->setJSVar('licenseTxt', $licenseContent);
$this->setJSVar('step1_txt', $step1_txt);
$this->setJSVar('step2_txt', $step2_txt);
$this->setJSVar('step3_txt', $step3_txt);
$this->setJSVar('step4_txt', $step4_txt);
$this->setJSVar('step5_txt', $step5_txt);
$this->setJSVar('step6_txt', $step6_txt);
$this->setJSVar('path_config', $this->path_config );
$this->setJSVar('path_languages', $this->path_languages );
$this->setJSVar('path_plugins', $this->path_plugins );
$this->setJSVar('path_xmlforms', $this->path_xmlforms );
$this->setJSVar('path_public', $this->path_public );
$this->setJSVar('path_shared', $this->path_shared );
$this->setJSVar('path_sep', $this->path_sep );
$this->setView('installer/main');
G::RenderPage('publish', 'extJs');
}
public function newSite()
{
$textStep1 = 'ProcessMaker stores all of its data in a database. This screen gives the installation program the information needed to create this database.
' .
'If you are installing ProcessMaker on a remote web server, you will need to get this information from your Database Server.';
$textStep2 = 'ProcessMaker uses a workspaces to store data. Please select a valid workspace name and credentials to log in it.';
$this->includeExtJS('installer/CardLayout', false);
$this->includeExtJS('installer/Wizard', false);
$this->includeExtJS('installer/Header', false);
$this->includeExtJS('installer/Card', false);
$this->includeExtJS('installer/newSite', false);
$this->setJSVar('textStep1', $textStep1);
$this->setJSVar('textStep2', $textStep2);
$this->setJSVar('DB_ADAPTER', DB_ADAPTER);
$aux = explode(':', DB_HOST);
$this->setJSVar('DB_HOST', $aux[0]);
$this->setJSVar('DB_PORT', isset($aux[1]) ? $aux[1] : (DB_ADAPTER == 'mssql' ? '1433' : '3306'));
$this->setJSVar('DB_NAME', 'workflow');
$this->setJSVar('DB_USER', '');
$this->setJSVar('DB_PASS', '');
$this->setJSVar('pathConfig', PATH_CORE . 'config' . PATH_SEP);
$this->setJSVar('pathLanguages', PATH_LANGUAGECONT);
$this->setJSVar('pathPlugins', PATH_PLUGINS);
$this->setJSVar('pathXmlforms', PATH_XMLFORM);
$this->setJSVar('pathShared', PATH_DATA);
$this->setView('installer/newSite');
G::RenderPage('publish', 'extJs');
}
public function getSystemInfo()
{
$this->setResponseType('json');
// PHP info and verification
$phpVer = phpversion();
preg_match('/[0-9\.]+/', $phpVer, $match);
$phpVerNum = (float) $match[0];
$info = new stdclass();
$info->php = new stdclass();
$info->mysql = new stdclass();
$info->mssql = new stdclass();
$info->openssl = new stdclass();
$info->curl = new stdclass();
$info->dom = new stdclass();
$info->gd = new stdclass();
$info->multibyte = new stdclass();
$info->soap = new stdclass();
$info->ldap = new stdclass();
$info->memory = new stdclass();
$info->php->version = phpversion();
$info->php->result = $phpVerNum >= 5.1 ? true : false;
// MYSQL info and verification
$info->mysql->result = false;
if ( function_exists ( 'mysql_query' ) ) {
$mysqlVer = mysql_get_client_info();
preg_match('/[0-9\.]+/', $mysqlVer, $match);
$mysqlNum = (float) $match[0];
$info->mysql->version = 'Client API version ' . $mysqlVer;
$info->mysql->result = $mysqlNum >= 5.0 ? true : false;
}
// MSSQL info and verification
$info->mssql->result = false;
$info->mssql->version = 'not enabled';
if ( function_exists ( 'mssql_query' ) ) {
$info->mssql->result = true;
$info->mssql->version = 'enabled';
}
// OpenSSL info
$info->openssl->result = false;
$info->openssl->version = 'not enabled';
if ( function_exists ( 'openssl_open' ) ) {
$info->openssl->result = true;
$info->openssl->version = 'enabled';
}
// Curl info
$info->curl->result = false;
$info->curl->version = 'not enabled';
if ( function_exists ( 'curl_version' ) ) {
$info->curl->result = true;
$version = curl_version();
$info->curl->version = 'cURL ' . $version['version'];
$info->openssl->version = $version['ssl_version'];
}
// DOMDocument info
$info->dom->result = false;
$info->dom->version = 'not enabled';
if ( class_exists ( 'DOMDocument' ) ) {
$info->dom->result = true;
$info->dom->version = 'enabled';
}
// GD info
$info->gd->result = false;
$info->gd->version = 'not enabled';
if ( function_exists ( 'gd_info' ) ) {
$info->gd->result = true;
$gdinfo = gd_info();
$info->gd->version = $gdinfo['GD Version'] ;
}
// Multibyte info
$info->multibyte->result = false;
$info->multibyte->version = 'not enabled';
if ( function_exists ( 'mb_check_encoding' ) ) {
$info->multibyte->result = true;
$info->multibyte->version = 'enabled';
}
// soap info
$info->soap->result = false;
$info->soap->version = 'not enabled';
if ( class_exists ( 'SoapClient' ) ) {
$info->soap->result = true;
$info->soap->version = 'enabled';
}
// ldap info
$info->ldap->result = false;
$info->ldap->version = 'not enabled';
if ( function_exists ( 'ldap_connect' ) ) {
$info->ldap->result = true;
$info->ldap->version = 'enabled';
}
// memory limit verification
$memory = (int)ini_get("memory_limit");
$info->memory->version = $memory . 'M';
if ( $memory > 80 ) {
$info->memory->result = true;
}
else {
$info->memory->result = false;
}
return $info;
}
public function is_dir_writable($path)
{
return G::is_writable_r($path);
}
public function getPermissionInfo()
{
$this->setResponseType('json');
$info = new StdClass();
$info->success = true;
$noWritableFiles = array();
// pathConfig
$info->pathConfig->message = 'unwriteable';
$info->pathConfig->result = G::is_writable_r($_REQUEST['pathConfig'], $noWritableFiles);
if ( $info->pathConfig->result ) {
$info->pathConfig->message = 'writeable';
}
else {
$info->success = false;
}
$info->pathLanguages->message = 'unwriteable';
$info->pathLanguages->result = G::is_writable_r($_REQUEST['pathLanguages'], $noWritableFiles);
if ( $info->pathLanguages->result ) {
$info->pathLanguages->message = 'writeable';
}
else {
$info->success = false;
}
$info->pathPlugins->message = 'unwriteable';
$info->pathPlugins->result = G::is_writable_r($_REQUEST['pathPlugins'], $noWritableFiles);
if ( $info->pathPlugins->result ) {
$info->pathPlugins->message = 'writeable';
}
else {
$info->success = false;
}
$info->pathXmlforms->message = 'unwriteable';
$info->pathXmlforms->result = G::is_writable_r($_REQUEST['pathXmlforms'], $noWritableFiles);
if ( $info->pathXmlforms->result ) {
$info->pathXmlforms->message = 'writeable';
}
else {
$info->success = false;
}
$info->pathPublic->message = 'unwriteable';
$info->pathPublic->result = G::is_writable_r($_REQUEST['pathPublic'], $noWritableFiles);
if ( $info->pathPublic->result ) {
$info->pathShared->message = 'writeable';
}
else {
$info->success = false;
}
$info->pathShared->message = 'unwriteable';
$info->pathShared->result = G::is_writable_r($_REQUEST['pathShared'], $noWritableFiles);
if ( $info->pathShared->result ) {
$info->pathShared->message = 'writeable';
}
else {
G::verifyPath($_REQUEST['pathShared'], true);
$info->pathShared->result = G::is_writable_r($_REQUEST['pathShared'], $noWritableFiles);
if ( $info->pathShared->result )
$info->pathShared->message = 'writeable';
else
$info->success = false;
}
if ($info->pathShared->result) {
$aux = pathinfo($_REQUEST['pathLogFile']);
G::verifyPath($aux['dirname'], true);
if (is_dir($aux['dirname'])) {
if (!file_exists($_REQUEST['pathLogFile'])) {
@file_put_contents($_REQUEST['pathLogFile'], '');
}
}
}
$info->pathLogFile->message = 'Could not create the installation log';
$info->pathLogFile->result = file_exists($_REQUEST['pathLogFile']);
if ($info->pathLogFile->result) {
$info->pathLogFile->message = 'Installation log created';
}
if ($info->success) {
$info->notify = 'Success, all required directories are writable.';
}
else {
$info->notify = 'Some directories and/or files inside it are not writable.';
}
$info->noWritableFiles = $noWritableFiles;
return $info;
}
public function testConnection ()
{
$this->setResponseType('json');
if ($_REQUEST['db_engine'] == 'mysql') {
return $this->testMySQLconnection();
}
else {
return $this->testMSSQLconnection();
}
}
/**
* log the queries and other information to install.log,
* the install.log files should be placed in shared/logs
* for that reason we are using the $_REQUEST of pathShared
*/
public function installLog( $text )
{
$serverAddr = $_SERVER['SERVER_ADDR'];
//if this function is called outside the createWorkspace, just returns and do nothing
if ( !isset( $_REQUEST['pathShared']) )
return;
//log file is in shared/logs
$pathShared = trim($_REQUEST['pathShared']);
if ( substr($pathShared,-1) != '/' ) $pathShared .= '/';
$logFile = $pathShared . 'log/install.log';
if ( !is_file($logFile) ) {
G::mk_dir(dirname($pathShared));
$fpt = fopen ( $logFile, 'w' );
if ( $fpt !== NULL ) {
fwrite( $fpt, sprintf ( "%s %s\n", date('Y:m:d H:i:s'), '----- starting log file ------' ));
fclose( $fpt);
}
else {
throw ( new Exception ( sprintf ( "File '%s' is not writeable. Please check permission before continue", $logFile ) ) );
return $false;
}
}
$fpt = fopen ( $logFile, 'a' );
fwrite( $fpt, sprintf ( "%s %s\n", date('Y:m:d H:i:s'), trim($text) ));
fclose( $fpt);
return true;
}
/**
* function to create a workspace
* in fact this function is calling appropiate functions for mysql and mssql
*/
public function createWorkspace()
{
$this->setResponseType('json');
if ($_REQUEST['db_engine'] == 'mysql') {
$info = $this->createMySQLWorkspace();
}
else {
$info = $this->createMSSQLWorkspace();
}
return $info;
}
public function forceTogenerateTranslationsFiles($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, (isset($_SERVER['HTTPS']) ? ($_SERVER['HTTPS'] != '' ? 'https://' : 'http://') : 'http://') . $_SERVER['HTTP_HOST'] . '/js/ext/translation.en.js?r=' . rand(1, 10000));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
curl_exec($ch);
curl_close($ch);
}
/**
* send a query to MySQL and log the query
*/
public function mysqlQuery($sql)
{
$this->installLog($sql);
$query = @mysql_query($sql, $this->link);
if (!$query) {
$errorMessage = mysql_error($this->link);
$this->installLog('MySQL error: ' . $errorMessage);
throw new Exception($errorMessage);
return false;
}
@mysql_free_result($query);
return true;
}
/**
* send a query to MSSQL and log the query
*/
public function mssqlQuery($sql)
{
$this->installLog( $sql );
$query = @mssql_query($sql, $this->link);
if (!$query) {
$errorMessage = mssql_get_last_message();
$this->installLog ( 'MSSQL error: ' . $errorMessage );
throw ( new Exception ( $errorMessage ) );
return false;
}
@mssql_free_result($query);
return true;
}
/**
* query_sql_file send many statements to server
*
* @param string $file
* @param string $connection
* @return array $report
*/
public function mysqlFileQuery($file)
{
if ( !is_file($file) ) {
throw ( new Exception ( sprintf ( "File $file is not a valid sql file", $file ) ) );
return $false;
}
$this->installLog ( 'Procesing: ' . $file );
$startTime = microtime(true);
// $content = file_get_contents($file);
// $queries = explode(';', $content);
// foreach( $queries as $sql) {
// if (trim($sql) != '') {
// $query = @mysql_query($sql, $this->link);
// if (!$query) {
// $errorMessage = mysql_error($this->link);
// $this->installLog ( sprintf ( 'MySQL error: %s Query: %s ', $errorMessage, $sql ) );
// throw ( new Exception ( $errorMessage ) );
// return false;
// }
// }
// }
//erik: New Update, to support more complex queries
$lines = file($file);
$previous = NULL;
$errors = '';
@mysql_query("SET NAMES 'utf8';");
foreach ($lines as $j => $line) {
$line = trim($line); // Remove comments from the script
if (strpos($line, "--") === 0) {
$line = substr($line, 0, strpos($line, "--"));
}
if (empty($line)) {
continue;
}
if (strpos($line, "#") === 0) {
$line = substr($line, 0, strpos($line, "#"));
}
if (empty($line)) {
continue;
}
// Concatenate the previous line, if any, with the current
if ($previous) {
$line = $previous . " " . $line;
}
$previous = NULL;
// If the current line doesnt end with ; then put this line together
// with the next one, thus supporting multi-line statements.
if (strrpos($line, ";") != strlen($line) - 1) {
$previous = $line;
continue;
}
$line = substr($line, 0, strrpos($line, ";"));
@mysql_query($line, $this->link);
}
$endTime = microtime(true);
$this->installLog ( sprintf ('File: %s processed in %3.2f seconds', basename($file) , $endTime - $startTime ) );
return true;
}
/**
* query_sql_file send many statements to server
*
* @param string $file
* @param string $connection
* @return array $report
*/
public function mssqlFileQuery($file)
{
if ( !is_file($file) ) {
throw ( new Exception ( sprintf ( "File $file is not a valid sql file", $file ) ) );
return $false;
}
$this->installLog ( 'Procesing: ' . $file );
$startTime = microtime(true);
$content = file_get_contents($file);
$queries = explode(';', $content);
foreach( $queries as $sql) {
$query = @mssql_query($sql, $this->link);
if (!$query) {
$errorMessage = mssql_get_last_message();
$this->installLog ( sprintf ( 'MSSQL error: %s Query: %s ', $errorMessage, $sql ) );
throw ( new Exception ( $errorMessage ) );
return false;
}
}
$endTime = microtime(true);
$this->installLog ( sprintf ('File: %s processed in %3.2f seconds', basename($file) , $endTime - $startTime ) );
return true;
}
/**
* set Grant Privileges for MySQL
*
* @param string $psUser
* @param string $psPassword
* @param string $psDatabase
* @return void
*/
public function setGrantPrivilegesMySQL($psUser, $psPassword, $psDatabase, $host)
{
$host = ($host == 'localhost' || $host == '127.0.0.1' ? 'localhost' : '%');
$query = sprintf("GRANT ALL PRIVILEGES ON `%s`.* TO %s@'%s' IDENTIFIED BY '%s' WITH GRANT OPTION", $psDatabase, $psUser, $host, $psPassword);
$this->mysqlQuery($query);
}
/**
* set Grant Privileges for SQLServer
*
* @param string $psUser
* @param string $psPassword
* @param string $psDatabase
* @return void
*/
public function setGrantPrivilegesMSSQL($psUser, $psPassword, $psDatabase)
{
$query = sprintf ( "IF EXISTS (SELECT * FROM sys.server_principals WHERE name = N'%s') DROP LOGIN [%s]", $psUser, $psUser );
$this->mssqlQuery( $query );
$query = sprintf ( "CREATE LOGIN [%s] WITH PASSWORD=N'%s', DEFAULT_DATABASE=[%s], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF ", $psUser, $psPassword, $psDatabase );
$this->mssqlQuery( $query );
$query = sprintf ( "USE %s;", $psDatabase );
$this->mssqlQuery( $query );
$query = sprintf ( "IF EXISTS (SELECT * FROM sys.database_principals WHERE name = N'%s') DROP USER [%s]", $psUser, $psUser );
$this->mssqlQuery( $query );
$query = sprintf ( "CREATE USER %s FOR LOGIN %s;", $psUser, $psUser );
$this->mssqlQuery( $query );
$query = sprintf ( "sp_addrolemember 'db_owner', '%s' ", $psUser );
$this->mssqlQuery( $query );
$query = sprintf ( "sp_addrolemember 'db_ddladmin', '%s' ", $psUser );
$this->mssqlQuery( $query );
$query = sprintf ( "sp_addrolemember 'db_accessadmin', '%s' ", $psUser );
$this->mssqlQuery( $query );
$query = sprintf ( "use master " );
$this->mssqlQuery( $query );
return true;
}
public function createMySQLWorkspace()
{
ini_set('max_execution_time', '0');
$info->result = false;
$info->message = '';
$info->canRedirect = true;
$db_hostname = trim($_REQUEST['db_hostname']);
$db_port = trim($_REQUEST['db_port']);
$db_username = trim($_REQUEST['db_username']);
$db_password = trim($_REQUEST['db_password']);
$wf = trim($_REQUEST['wfDatabase']);
$rb = trim($_REQUEST['rbDatabase']);
$rp = trim($_REQUEST['rpDatabase']);
$workspace = trim($_REQUEST['workspace']);
$pathConfig = trim($_REQUEST['pathConfig']);
$pathLanguages = trim($_REQUEST['pathLanguages']);
$pathPlugins = trim($_REQUEST['pathPlugins']);
$pathShared = trim($_REQUEST['pathShared']);
$pathXmlforms = trim($_REQUEST['pathXmlforms']);
$adminPassword = trim($_REQUEST['adminPassword']);
$adminUsername = trim($_REQUEST['adminUsername']);
$deleteDB = ($_REQUEST['deleteDB'] == 'true');
if ( substr($pathShared,-1) != '/' ) $pathShared .= '/';
$this->installLog ( '-------------------------------------------' );
$this->installLog ( sprintf ( "Creating workspace '%s' ", $workspace) );
try {
$db_host = ($db_port != '' && $db_port != 3306) ? $db_hostname . ':' . $db_port : $db_hostname ;
$this->link = @mysql_connect($db_host, $db_username, $db_password);
$this->installLog (sprintf ( "Connected to server %s:%d using user: '%s' ", $db_hostname, $db_port, $db_username ) );
if ($deleteDB) {
$q = sprintf('DROP DATABASE IF EXISTS %s;' , $wf, $wf);
$this->mysqlQuery($q);
$q = sprintf('DROP DATABASE IF EXISTS %s;' , $rb, $rb);
$this->mysqlQuery($q);
$q = sprintf('DROP DATABASE IF EXISTS %s;' , $rp, $rp);
$this->mysqlQuery($q);
}
// CREATE databases wf_workflow, rb_workflow and rp_workflow
$q = sprintf('CREATE DATABASE IF NOT EXISTS %s;' , $wf, $wf);
$this->mysqlQuery($q);
$q = sprintf('CREATE DATABASE IF NOT EXISTS %s;' , $rb, $rb);
$this->mysqlQuery($q);
$q = sprintf('CREATE DATABASE IF NOT EXISTS %s;' , $rp, $rp);
$this->mysqlQuery($q);
// CREATE users and GRANT Privileges
$wfPass = G::generate_password(12);
$rbPass = G::generate_password(12);
$rpPass = G::generate_password(12);
$this->setGrantPrivilegesMySQL($wf, $wfPass, $wf, $db_hostname);
$this->setGrantPrivilegesMySQL($rb, $rbPass, $rb, $db_hostname);
$this->setGrantPrivilegesMySQL($rp, $rpPass, $rp, $db_hostname);
// Generate the db.php file and folders
$path_site = $pathShared . "/sites/" . $workspace ."/";
$db_file = $path_site. "db.php";
@mkdir($path_site, 0777, true);
@mkdir($path_site . "files/", 0777, true);
@mkdir($path_site . "mailTemplates/", 0777, true);
@mkdir($path_site . "public/", 0777, true);
@mkdir($path_site . "reports/", 0777, true);
@mkdir($path_site . "xmlForms", 0777, true);
$dbText = "installLog("Creating: " . $db_file );
file_put_contents ( $db_file, $dbText);
// Generate the databases.php file
$databases_file = $path_site . 'databases.php';
$dbData = sprintf("\$dbAdapter = '%s';\n", 'mysql');
$dbData .= sprintf("\$dbHost = '%s';\n", $db_host);
$dbData .= sprintf("\$dbName = '%s';\n", $wf);
$dbData .= sprintf("\$dbUser = '%s';\n", $wf);
$dbData .= sprintf("\$dbPass = '%s';\n", $wfPass);
$dbData .= sprintf("\$dbRbacHost = '%s';\n", $db_host);
$dbData .= sprintf("\$dbRbacName = '%s';\n", $rb);
$dbData .= sprintf("\$dbRbacUser = '%s';\n", $rb);
$dbData .= sprintf("\$dbRbacPass = '%s';\n", $rbPass);
$dbData .= sprintf("\$dbReportHost = '%s';\n", $db_host);
$dbData .= sprintf("\$dbReportName = '%s';\n", $rp);
$dbData .= sprintf("\$dbReportUser = '%s';\n", $rp);
$dbData .= sprintf("\$dbReportPass = '%s';\n", $rpPass);
$databasesText = str_replace('{dbData}', $dbData, @file_get_contents(PATH_HOME . 'engine/templates/installer/databases.tpl'));
$this->installLog('Creating: ' . $databases_file);
file_put_contents($databases_file, $databasesText);
// Execute scripts to create and populates databases
$query = sprintf ( "USE %s;", $rb );
$this->mysqlQuery( $query );
$this->mysqlFileQuery ( PATH_RBAC_HOME . 'engine/data/mysql/schema.sql' );
$this->mysqlFileQuery ( PATH_RBAC_HOME . 'engine/data/mysql/insert.sql' );
$query = sprintf ( "USE %s;", $wf );
$this->mysqlQuery( $query );
$this->mysqlFileQuery ( PATH_HOME . 'engine/data/mysql/schema.sql' );
$this->mysqlFileQuery ( PATH_HOME . 'engine/data/mysql/insert.sql' );
// Create the triggers
if (file_exists(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerAppDelegationInsert.sql') &&
file_exists(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerAppDelegationUpdate.sql') &&
file_exists(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerApplicationUpdate.sql') &&
file_exists(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerApplicationDelete.sql') &&
file_exists(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerContentUpdate.sql')) {
$this->mysqlQuery(@file_get_contents(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerAppDelegationInsert.sql'));
$this->mysqlQuery(@file_get_contents(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerAppDelegationUpdate.sql'));
$this->mysqlQuery(@file_get_contents(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerApplicationUpdate.sql'));
$this->mysqlQuery(@file_get_contents(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerApplicationDelete.sql'));
$this->mysqlQuery(@file_get_contents(PATH_HOME . 'engine/methods/setup/setupSchemas/triggerContentUpdate.sql'));
$this->mysqlQuery("INSERT INTO `CONFIGURATION` (
`CFG_UID`,
`CFG_VALUE`
)
VALUES (
'APP_CACHE_VIEW_ENGINE',
'" . mysql_real_escape_string(serialize(array('LANG' => 'en', 'STATUS' => 'active'))) . "'
)");
}
// Change admin user
$query = sprintf ( "USE %s;", $wf );
$this->mysqlQuery( $query );
$query = sprintf ( "UPDATE USERS SET USR_USERNAME = '%s', USR_PASSWORD = '%s' WHERE USR_UID = '00000000000000000000000000000001' ", $adminUsername, md5($adminPassword) );
$this->mysqlQuery( $query );
$query = sprintf ( "USE %s;", $rb );
$this->mysqlQuery( $query );
$query = sprintf ( "UPDATE USERS SET USR_USERNAME = '%s', USR_PASSWORD = '%s' WHERE USR_UID = '00000000000000000000000000000001' ", $adminUsername, md5($adminPassword) );
$this->mysqlQuery( $query );
// Write the paths_installed.php file (contains all the information configured so far)
if ( !file_exists(FILE_PATHS_INSTALLED) ) {
$sh = md5( filemtime( PATH_GULLIVER . '/class.g.php' ) );
$h = G::encrypt($db_hostname.$sh.$db_username.$sh.$db_password, $sh);
$dbText = "installLog("Creating: " . FILE_PATHS_INSTALLED );
file_put_contents ( FILE_PATHS_INSTALLED, $dbText);
}
/**
* AppCacheView Build
*/
define('HASH_INSTALLATION', $h );
define('SYSTEM_HASH', $sh );
define('PATH_DB', $pathShared . 'sites' . PATH_SEP );
define('SYS_SYS', 'workflow');
require_once("propel/Propel.php");
Propel::init( PATH_CORE . "config/databases.php" );
$con = Propel::getConnection('workflow');
require_once('classes/model/AppCacheView.php');
$lang='en';
//setup the appcacheview object, and the path for the sql files
$appCache = new AppCacheView();
$appCache->setPathToAppCacheFiles ( PATH_METHODS . 'setup' . PATH_SEP .'setupSchemas'. PATH_SEP );
//APP_DELEGATION INSERT
$res = $appCache->triggerAppDelegationInsert($lang, true);
//APP_DELEGATION Update
$res = $appCache->triggerAppDelegationUpdate($lang, true);
//APPLICATION UPDATE
$res = $appCache->triggerApplicationUpdate($lang, true);
//APPLICATION DELETE
$res = $appCache->triggerApplicationDelete($lang, true);
//CONTENT UPDATE
$res = $appCache->triggerContentUpdate($lang, true);
//build using the method in AppCacheView Class
$res = $appCache->fillAppCacheView($lang);
//end AppCacheView Build
//erik: for new env conf handling
G::loadClass('system');
$envFile = PATH_CONFIG . 'env.ini';
//writting for new installtions to use the classic skin
$updatedConf['default_skin'] = 'classic';
$info->uri = '/sys' . $_REQUEST['workspace'] . '/en/classic/login/login';
try {
G::update_php_ini($envFile, $updatedConf);
}
catch (Exception $e) {
$info->result = false;
$info->message = "ProcessMaker couldn't write on configuration file: $envFile.
";
$info->message .= "The new ProcessMaker UI couldn't be applied on installation, you can enable it after from Admin->System settings.";
$this->installLog("Installed but with error, couldn't update env.ini" );
return $info;
}
// getting configuration from env.ini
$sysConf = System::getSystemConfiguration($envFile);
try {
// update the main index file
$indexFileUpdated = System::updateIndexFile(array(
'lang' => 'en',
'skin' => $updatedConf['default_skin']
));
}
catch (Exception $e) {
$info->result = false;
$info->message = "ProcessMaker couldn't write on configuration file: ".PATH_HTML."index.html.
";
$info->message .= "The new ProcessMaker UI couldn't be applied on installation, you can enable it after from Admin->System settings.";
$this->installLog("Installed but with error, couldn't update index.html" );
return $info;
}
$this->installLog("Index File updated $indexFileUpdated with lang: {$sysConf['default_lang']}, skin: {$sysConf['default_skin']} " );
$this->installLog("Install completed Succesfully" );
$info->result = true;
$info->message = 'Succesfully OK';
}
catch (Exception $e) {
$info->canRedirect = false;
$info->result = false;
$info->message = $e->getMessage();
}
return $info;
}
public function createMSSQLWorkspace()
{
ini_set('max_execution_time', '0');
$info->result = false;
$info->message = '';
$db_hostname = trim($_REQUEST['db_hostname']);
$db_port = trim($_REQUEST['db_port']);
$db_username = trim($_REQUEST['db_username']);
$db_password = trim($_REQUEST['db_password']);
$wf = trim($_REQUEST['wfDatabase']);
$rb = trim($_REQUEST['rbDatabase']);
$rp = trim($_REQUEST['rpDatabase']);
$workspace = trim($_REQUEST['workspace']);
$pathConfig = trim($_REQUEST['pathConfig']);
$pathLanguages = trim($_REQUEST['pathLanguages']);
$pathPlugins = trim($_REQUEST['pathPlugins']);
$pathShared = trim($_REQUEST['pathShared']);
$pathXmlforms = trim($_REQUEST['pathXmlforms']);
$adminPassword = trim($_REQUEST['adminPassword']);
$adminUsername = trim($_REQUEST['adminUsername']);
$deleteDB = ($_REQUEST['deleteDB'] == 'true');
if ( substr($pathShared,-1) != '/' ) $pathShared .= '/';
$this->installLog ( '-------------------------------------------' );
$this->installLog ( sprintf ( "Creating workspace '%s' ", $workspace) );
try {
$db_host = ($db_port != '' && $db_port != 1433) ? $db_hostname . ':' . $db_port : $db_hostname ;
$this->link = @mssql_connect($db_host, $db_username, $db_password);
$this->installLog (sprintf ( "Connected to server %s:%d using user: '%s' ", $db_hostname, $db_port, $db_username ) );
$this->mssqlQuery( 'USE [master]' );
// DROP databases wf_workflow, rb_workflow and rp_workflow
if ($deleteDB) {
$q = sprintf ("IF EXISTS (SELECT name FROM sys.databases WHERE name='%s' ) DROP DATABASE %s" , $wf, $wf );
$this->mssqlQuery( $q);
$q = sprintf ("IF EXISTS (SELECT name FROM sys.databases WHERE name='%s' ) DROP DATABASE %s" , $rb, $rb );
$this->mssqlQuery( $q);
$q = sprintf ("IF EXISTS (SELECT name FROM sys.databases WHERE name='%s' ) DROP DATABASE %s" , $rp, $rp );
$this->mssqlQuery( $q);
}
// CREATE databases wf_workflow, rb_workflow and rp_workflow
$q = sprintf ("IF NOT EXISTS (SELECT * FROM sys.databases WHERE name='%s' ) CREATE DATABASE %s" , $wf, $wf );
$this->mssqlQuery( $q);
$q = sprintf ("IF NOT EXISTS (SELECT * FROM sys.databases WHERE name='%s' ) CREATE DATABASE %s" , $rb, $rb );
$this->mssqlQuery( $q);
$q = sprintf ("IF NOT EXISTS (SELECT * FROM sys.databases WHERE name='%s' ) CREATE DATABASE %s" , $rp, $rp );
$this->mssqlQuery( $q);
//CREATE users and GRANT Privileges
$wfPass = G::generate_password(12);
$rbPass = G::generate_password(12);
$rpPass = G::generate_password(12);
$this->setGrantPrivilegesMSSQL($wf, $wfPass, $wf );
$this->setGrantPrivilegesMSSQL($rb, $rbPass, $rb );
$this->setGrantPrivilegesMSSQL($rp, $rpPass, $rp );
//Generate the db.php file and folders
$path_site = $pathShared . "/sites/" . $workspace ."/";
$db_file = $path_site. "db.php";
mkdir($path_site, 0777, true);
@mkdir($path_site . "files/", 0777, true);
@mkdir($path_site . "mailTemplates/", 0777, true);
@mkdir($path_site . "public/", 0777, true);
@mkdir($path_site . "reports/", 0777, true);
@mkdir($path_site . "xmlForms", 0777, true);
$dbText = "installLog("Creating: " . $db_file );
file_put_contents ( $db_file, $dbText);
// Generate the databases.php file
$databases_file = $path_site . 'databases.php';
$dbData = sprintf("\$dbAdapter = '%s';\n", 'mssql');
$dbData .= sprintf("\$dbHost = '%s';\n", $db_host);
$dbData .= sprintf("\$dbName = '%s';\n", $wf);
$dbData .= sprintf("\$dbUser = '%s';\n", $wf);
$dbData .= sprintf("\$dbPass = '%s';\n", $wfPass);
$dbData .= sprintf("\$dbRbacHost = '%s';\n", $db_host);
$dbData .= sprintf("\$dbRbacName = '%s';\n", $rb);
$dbData .= sprintf("\$dbRbacUser = '%s';\n", $rb);
$dbData .= sprintf("\$dbRbacPass = '%s';\n", $rbPass);
$dbData .= sprintf("\$dbReportHost = '%s';\n", $db_host);
$dbData .= sprintf("\$dbReportName = '%s';\n", $rp);
$dbData .= sprintf("\$dbReportUser = '%s';\n", $rp);
$dbData .= sprintf("\$dbReportPass = '%s';\n", $rpPass);
$databasesText = str_replace('{dbData}', $dbData, @file_get_contents(PATH_HOME . 'engine/templates/installer/databases.tpl'));
$this->installLog('Creating: ' . $databases_file);
file_put_contents($databases_file, $databasesText);
//execute scripts to create and populates databases
$query = sprintf ( "USE %s;", $rb );
$this->mssqlQuery( $query );
$this->mssqlFileQuery ( PATH_RBAC_HOME . 'engine/data/mssql/schema.sql' );
$this->mssqlFileQuery ( PATH_RBAC_HOME . 'engine/data/mssql/insert.sql' );
$query = sprintf ( "USE %s;", $wf );
$this->mssqlQuery( $query );
$this->mssqlFileQuery ( PATH_HOME . 'engine/data/mssql/schema.sql' );
$this->mssqlFileQuery ( PATH_HOME . 'engine/data/mssql/insert.sql' );
// Create the triggers
if (file_exists(PATH_HOME . 'engine/plugins/enterprise/data/triggerAppDelegationInsert.sql') &&
file_exists(PATH_HOME . 'engine/plugins/enterprise/data/triggerAppDelegationUpdate.sql') &&
file_exists(PATH_HOME . 'engine/plugins/enterprise/data/triggerApplicationUpdate.sql') &&
file_exists(PATH_HOME . 'engine/plugins/enterprise/data/triggerApplicationDelete.sql') &&
file_exists(PATH_HOME . 'engine/plugins/enterprise/data/triggerContentUpdate.sql')) {
$this->mssqlQuery(@file_get_contents(PATH_HOME . 'engine/plugins/enterprise/data/triggerAppDelegationInsert.sql'));
$this->mssqlQuery(@file_get_contents(PATH_HOME . 'engine/plugins/enterprise/data/triggerAppDelegationUpdate.sql'));
$this->mssqlQuery(@file_get_contents(PATH_HOME . 'engine/plugins/enterprise/data/triggerApplicationUpdate.sql'));
$this->mssqlQuery(@file_get_contents(PATH_HOME . 'engine/plugins/enterprise/data/triggerApplicationDelete.sql'));
$this->mssqlQuery(@file_get_contents(PATH_HOME . 'engine/plugins/enterprise/data/triggerContentUpdate.sql'));
$this->mssqlQuery("INSERT INTO CONFIGURATION (
CFG_UID,
CFG_VALUE
)
VALUES (
'APP_CACHE_VIEW_ENGINE',
'" . addslashes(serialize(array('LANG' => 'en', 'STATUS' => 'active'))) . "'
)");
}
//change admin user
$query = sprintf ( "USE %s;", $wf );
$this->mssqlQuery( $query );
$query = sprintf ( "UPDATE USERS SET USR_USERNAME = '%s', USR_PASSWORD = '%s' WHERE USR_UID = '00000000000000000000000000000001' ", $adminUsername, md5($adminPassword) );
$this->mssqlQuery( $query );
$query = sprintf ( "USE %s;", $rb );
$this->mssqlQuery( $query );
$query = sprintf ( "UPDATE USERS SET USR_USERNAME = '%s', USR_PASSWORD = '%s' WHERE USR_UID = '00000000000000000000000000000001' ", $adminUsername, md5($adminPassword) );
$this->mssqlQuery( $query );
// Write the paths_installed.php file (contains all the information configured so far)
if ( !file_exists(FILE_PATHS_INSTALLED) ) {
$sh = md5( filemtime( PATH_GULLIVER . '/class.g.php' ) );
$h = G::encrypt($db_hostname.$sh.$db_username.$sh.$db_password.'1' , $sh);
$dbText = "installLog("Creating: " . FILE_PATHS_INSTALLED );
file_put_contents ( FILE_PATHS_INSTALLED, $dbText);
}
$this->installLog("Install completed Succesfully" );
$info->result = true;
$info->message = 'Succesfully';
$info->url = '/sys' . $_REQUEST['workspace'] . '/en/classic/main/login';
}
catch (Exception $e) {
$info->result = false;
$info->message = $e->getMessage();
}
return $info;
}
public function getEngines()
{
$this->setResponseType('json');
$engines = array();
if (function_exists('mysql_query')) {
$engine = new stdclass();
$engine->id = 'mysql';
$engine->label = 'MySQL';
$engines[] = $engine;
}
/** DISABLED TEMPORARELY
if (function_exists('mssql_query')) {
$engine = new stdclass();
$engine->id = 'mssql';
$engine->label = 'Microsoft SQL Server';
$engines[] = $engine;
}*/
return $engines;
}
public function checkDatabases()
{
$this->setResponseType('json');
$info = new stdclass();
if ($_REQUEST['db_engine'] == 'mysql') {
$link = @mysql_connect($_REQUEST['db_hostname'], $_REQUEST['db_username'], $_REQUEST['db_password']);
$dataset = @mysql_query("show databases like '" . $_REQUEST['wfDatabase'] . "'", $link);
$info->wfDatabaseExists = (@mysql_num_rows($dataset) > 0);
$dataset = @mysql_query("show databases like '" . $_REQUEST['rbDatabase'] . "'", $link);
$info->rbDatabaseExists = (@mysql_num_rows($dataset) > 0);
$dataset = @mysql_query("show databases like '" . $_REQUEST['rpDatabase'] . "'", $link);
$info->rpDatabaseExists = (@mysql_num_rows($dataset) > 0);
}
else {
$link = @mssql_connect($_REQUEST['db_hostname'], $_REQUEST['db_username'], $_REQUEST['db_password']);
$dataset = @mssql_query("select * from sys.databases where name = '" . $_REQUEST['wfDatabase'] . "'", $link);
$info->wfDatabaseExists = (@mssql_num_rows($dataset) > 0);
$dataset = @mssql_query("select * from sys.databases where name = '" . $_REQUEST['rbDatabase'] . "'", $link);
$info->rbDatabaseExists = (@mssql_num_rows($dataset) > 0);
$dataset = @mssql_query("select * from sys.databases where name = '" . $_REQUEST['rpDatabase'] . "'", $link);
$info->rpDatabaseExists = (@mssql_num_rows($dataset) > 0);
}
$info->errMessage = 'Database already exists, check "Delete Databases if exists" to overwrite the exiting databases.';
return $info;
}
/**
* Privates functions section, non callable by http request
*/
private function testMySQLconnection()
{
$info->result = false;
$info->message = '';
if ( !function_exists("mysql_connect") ) {
$info->message = 'php-mysql is Not Installed';
return $info;
}
$db_hostname = $_REQUEST['db_hostname'];
$db_port = $_REQUEST['db_port'];
$db_username = $_REQUEST['db_username'];
$db_password = $_REQUEST['db_password'];
$fp = @fsockopen($db_hostname, $db_port, $errno, $errstr, 30);
if ( !$fp ) {
$info->message .= "Connection Error: $errstr ($errno)";
return $info;
}
$db_host = ($db_port != '' && $db_port != 1433) ? $db_hostname . ':' . $db_port : $db_hostname ;
$link = @mysql_connect($db_host, $db_username, $db_password);
if (!$link) {
$info->message .= "Connection Error: unable to connect to MySQL using provided credentials.";
return $info;
}
$res = @mysql_query("SELECT * FROM `information_schema`.`USER_PRIVILEGES` where (GRANTEE = \"'$db_username'@'$db_hostname'\" OR GRANTEE = \"'$db_username'@'%'\") and PRIVILEGE_TYPE = 'SUPER' ", $link);
$row = @mysql_fetch_array($res);
$hasSuper = is_array($row);
@mysql_free_result($res);
@mysql_close($link);
if (!$hasSuper) {
$info->message .= "Connection Error: User '$db_username' can't create databases and Users
Please provide an user with SUPER privilege.";
return $info;
}
$info->message .= "Succesfully connected to MySQL Server";
$info->result = true;
return $info;
}
private function testMSSQLconnection()
{
$info->result = false;
$info->message = '';
if ( !function_exists("mssql_connect") ) {
$info->message = 'php-mssql is Not Installed';
return $info;
}
$db_hostname = $_REQUEST['db_hostname'];
$db_port = $_REQUEST['db_port'];
$db_username = $_REQUEST['db_username'];
$db_password = $_REQUEST['db_password'];
$fp = @fsockopen($db_hostname, $db_port, $errno, $errstr, 30);
if ( !$fp ) {
$info->message .= "Connection Error: $errstr ($errno)";
return $info;
}
$db_host = ($db_port != '' && $db_port != 1433) ? $db_hostname . ':' . $db_port : $db_hostname ;
$link = @mssql_connect($db_host, $db_username, $db_password);
if (!$link) {
$info->message .= "Connection Error: unable to connect to MSSQL using provided credentials.";
return $info;
}
//checking if user has the dbcreator role
$hasDbCreator = false;
$hasSecurityAdmin = false;
$hasSysAdmin = false;
$res = @mssql_query( "EXEC sp_helpsrvrolemember 'dbcreator' ", $link );
$row = mssql_fetch_array($res);
while ( is_array( $row ) ) {
if ( $row['MemberName'] == $db_username ) $hasDbCreator = true;
$row = mssql_fetch_array($res);
}
mssql_free_result($res);
$res = @mssql_query( "EXEC sp_helpsrvrolemember 'sysadmin' ", $link );
$row = mssql_fetch_array($res);
while ( is_array( $row ) ) {
if ( $row['MemberName'] == $db_username ) $hasSysAdmin = true;
$row = mssql_fetch_array($res);
}
mssql_free_result($res);
$res = @mssql_query( "EXEC sp_helpsrvrolemember 'SecurityAdmin' ", $link );
$row = mssql_fetch_array($res);
while ( is_array( $row ) ) {
if ( $row['MemberName'] == $db_username ) $hasSecurityAdmin = true;
$row = mssql_fetch_array($res);
}
mssql_free_result($res);
if ( ! ( $hasSysAdmin || ( $hasSecurityAdmin && $hasDbCreator) ) ) {
$info->message .= "Connection Error: User '$db_username' can't create databases and Users
Please provide an user with sysadmin role or dbcreator and securityadmin roles.";
return $info;
}
$info->message .= "Succesfully connected to MSSQL Server";
$info->result = true;
return $info;
}
}