*/ 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; } }