Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Fri, Feb 21, 11:59 PM

in-portal

Index: branches/5.2.x/core/install/step_templates/db_config.tpl
===================================================================
--- branches/5.2.x/core/install/step_templates/db_config.tpl (revision 16818)
+++ branches/5.2.x/core/install/step_templates/db_config.tpl (revision 16819)
@@ -1,77 +1,81 @@
<tr class="table-color2">
<td class="text"><b>Database Server Type<span class="error">*</span>:</b></td>
<td align="left">
<select name="DBType">
<?php
$options = Array ('mysqli' => 'MySQL', /*'mssql' => 'MS-SQL Server', 'pgsql' => 'pgSQL'*/);
$option_tpl = '<option value="%1$s"%2$s>%3$s</option>'."\n";
foreach ($options as $option_key => $option_title) {
$selected = $option_key == $this->toolkit->systemConfig->get('DBType', 'Database') ? ' selected' : '';
echo sprintf($option_tpl, $option_key, $selected, $option_title);
}
?>
</select>
</td>
</tr>
<tr class="table-color2">
<td class="text"><b>Database Hostname <span class="error">*</span>:</b></td>
<td align="left">
<input type="text" name="DBHost" class="text" value="<?php echo $this->toolkit->systemConfig->get('DBHost', 'Database'); ?>" />
</td>
</tr>
<tr class="table-color2">
<td class="text"><b>Database Name <span class="error">*</span>:</b></td>
<td align="left">
<input type="text" name="DBName" class="text" value="<?php echo $this->toolkit->systemConfig->get('DBName', 'Database'); ?>" />
</td>
</tr>
<tr class="table-color2">
<td class="text"><b>Database User Name <span class="error">*</span>:</b></td>
<td align="left">
<input type="text" name="DBUser" class="text" value="<?php echo $this->toolkit->systemConfig->get('DBUser', 'Database'); ?>" />
</td>
</tr>
<tr class="table-color2">
<td class="text"><b>Database User Password:</b></td>
<td align="left">
<input type="password" name="DBUserPassword" class="text" value="<?php echo $this->toolkit->systemConfig->get('DBUserPassword', 'Database'); ?>" />
</td>
</tr>
<tr class="table-color2">
<td class="text"><b>Database Collation <span class="error">*</span>:</b></td>
<td align="left">
<select name="DBCollation" class="text">
<?php
- $option_tpl = '<option value="%1$s"%2$s>%1$s</option>'."\n";
- $collations = Array ('utf8_general_ci', 'latin1_swedish_ci');
- foreach ($collations as $collation) {
- $selected = ($collation == $this->toolkit->systemConfig->get('DBCollation', 'Database')) ? ' selected="selected"' : '';
- echo sprintf($option_tpl, $collation, $selected);
+ $option_tpl = '<option value="%1$s"%3$s>%2$s</option>'."\n";
+ $collations = Array (
+ 'utf8_general_ci' => 'utf8_general_ci (MySQL 5.x)',
+ 'utf8mb3_general_ci' => 'utf8mb3_general_ci (MySQL 8.x+)',
+ 'latin1_swedish_ci' => 'latin1_swedish_ci (MySQL 5.x & MySQL 8.x+)',
+ );
+ foreach ($collations as $collation_key => $collation_title) {
+ $selected = ($collation_key == $this->toolkit->systemConfig->get('DBCollation', 'Database')) ? ' selected="selected"' : '';
+ echo sprintf($option_tpl, $collation_key, $collation_title, $selected);
}
?>
</select>
</td>
</tr>
<tr class="table-color2">
<td class="text"><b>Prefix for Table Names:</b></td>
<td align="left">
<input type="text" name="TablePrefix" class="text" maxlength="7" value="<?php echo $this->toolkit->systemConfig->get('TablePrefix', 'Database'); ?>" />
</td>
</tr>
<?php if ($this->GetVar('preset') != 'already_installed') { ?>
<!--show this option ONLY when config.php is empty or cant connect to In-Portal installation using current DB settings -->
<tr class="table-color2">
<td class="text" width="55%"><b>Use existing In-Portal installation in this Database:</b></td>
<td align="left">
<input type="radio" name="UseExistingSetup" id="UseExistingSetup_1" value="1"/> <label for="UseExistingSetup_1">Yes</label> <input type="radio" name="UseExistingSetup" id="UseExistingSetup_0" value="0" checked/> <label for="UseExistingSetup_0">No</label>
</td>
</tr>
-<?php } ?>
\ No newline at end of file
+<?php } ?>
Index: branches/5.2.x/core/install/step_templates/db_reconfig.tpl
===================================================================
--- branches/5.2.x/core/install/step_templates/db_reconfig.tpl (revision 16818)
+++ branches/5.2.x/core/install/step_templates/db_reconfig.tpl (revision 16819)
@@ -1,67 +1,71 @@
<tr class="table-color2">
<td class="text"><b>Database Server Type<span class="error">*</span>:</b></td>
<td align="left">
<select name="DBType">
<?php
$options = Array ('mysqli' => 'MySQL', /*'mssql' => 'MS-SQL Server', 'pgsql' => 'pgSQL'*/);
$option_tpl = '<option value="%1$s"%2$s>%3$s</option>'."\n";
foreach ($options as $option_key => $option_title) {
$selected = $option_key == $this->toolkit->systemConfig->get('DBType', 'Database') ? ' selected' : '';
echo sprintf($option_tpl, $option_key, $selected, $option_title);
}
?>
</select>
</td>
</tr>
<tr class="table-color2">
<td class="text"><b>Database Hostname <span class="error">*</span>:</b></td>
<td align="left">
<input type="text" name="DBHost" class="text" value="<?php echo $this->toolkit->systemConfig->get('DBHost', 'Database'); ?>" />
</td>
</tr>
<tr class="table-color2">
<td class="text"><b>Database Name <span class="error">*</span>:</b></td>
<td align="left">
<input type="text" name="DBName" class="text" value="<?php echo $this->toolkit->systemConfig->get('DBName', 'Database'); ?>" />
</td>
</tr>
<tr class="table-color2">
<td class="text"><b>Database User Name <span class="error">*</span>:</b></td>
<td align="left">
<input type="text" name="DBUser" class="text" value="<?php echo $this->toolkit->systemConfig->get('DBUser', 'Database'); ?>" />
</td>
</tr>
<tr class="table-color2">
<td class="text"><b>Database User Password:</b></td>
<td align="left">
<input type="password" name="DBUserPassword" class="text" value="<?php echo $this->toolkit->systemConfig->get('DBUserPassword', 'Database'); ?>" />
</td>
</tr>
<tr class="table-color2">
<td class="text"><b>Database Collation <span class="error">*</span>:</b></td>
<td align="left">
<select name="DBCollation" class="text">
<?php
- $option_tpl = '<option value="%1$s"%2$s>%1$s</option>'."\n";
- $collations = Array ('utf8_general_ci', 'latin1_swedish_ci');
- foreach ($collations as $collation) {
- $selected = ($collation == $this->toolkit->systemConfig->get('DBCollation', 'Database')) ? ' selected="selected"' : '';
- echo sprintf($option_tpl, $collation, $selected);
+ $option_tpl = '<option value="%1$s"%3$s>%2$s</option>'."\n";
+ $collations = Array (
+ 'utf8_general_ci' => 'utf8_general_ci (MySQL 5.x)',
+ 'utf8mb3_general_ci' => 'utf8mb3_general_ci (MySQL 8.x+)',
+ 'latin1_swedish_ci' => 'latin1_swedish_ci (MySQL 5.x/8.x+)',
+ );
+ foreach ($collations as $collation_key => $collation_title) {
+ $selected = ($collation_key == $this->toolkit->systemConfig->get('DBCollation', 'Database')) ? ' selected="selected"' : '';
+ echo sprintf($option_tpl, $collation_key, $collation_title, $selected);
}
?>
</select>
</td>
</tr>
<tr class="table-color2">
<td class="text"><b>Prefix for Table Names:</b></td>
<td align="left">
<input type="text" name="TablePrefix" class="text" maxlength="7" value="<?php echo $this->toolkit->systemConfig->get('TablePrefix', 'Database'); ?>" />
</td>
-</tr>
\ No newline at end of file
+</tr>
Index: branches/5.2.x/core/install/steps_db.xml
===================================================================
--- branches/5.2.x/core/install/steps_db.xml (revision 16818)
+++ branches/5.2.x/core/install/steps_db.xml (revision 16819)
@@ -1,339 +1,339 @@
<steps>
<step name="clean_db" title="Clean Database">
<![CDATA[missing step description]]>
</step>
<step name="db_config" title="Database Configuration">
<![CDATA[<p><b><i>Database Hostname</i></b> - IP or hostname of your database server (normally <i>"localhost"</i>).</p>
<p><b><i>Database Name</i></b> - name of the database where In-Portal will be installed.</p>
<p><b><i>Database User Name</i></b> - name of the user for selected database.</p>
<p><b><i>Database User Password</i></b> - password for selected username.</p>
- <p><b><i>Database Collation</i></b> - character set used to store data in text fields (normally <i>"utf8_general_ci"</i>).</p>
+ <p><b><i>Database Collation</i></b> - character set used to store data in text fields (normally <i>"utf8_general_ci"</i> for MySQL 5.x and <i>"utf8mb3_general_ci"</i> for MySQL 8.x+).</p>
<p><b><i>Prefix for Table Names</i></b> - specified when multiple scripts will be run in the same database.
Prefix can be any text string allowed in table naming by your database engine (normally <i>"inp_"</i>).</p>
<p><b><i>Use existing In-Portal installation setup in this Database</i></b> - select <i>"Yes"</i>
if you already have In-Portal installed in this database and want to use it. Select <i>"No"</i> in all other cases.</p>
]]>
</step>
<step name="select_license" title="Select License" help_title="License Configuration">
<![CDATA[<p><b>In-Portal is an Open Source</b> object-oriented framework that is developed in PHP
and provides a quick and easy way to build websites and web applications.</p>
<p>In-Portal is copyrighted and distributed under <a href="http://www.in-portal.org/license" target="_blank">GPLv2 license</a>.</p>
<p><b><i>GPL / Open Source License</i></b> - by downloading and installing In-Portal
under GPLv2 license you understand and agree to all terms of the
<a href="http://www.in-portal.org/license" target="_blank">GPLv2 license</a>.</p>
<p><b><i>Upload License File</i></b> - if you have obtained Commercial
<a href="http://www.in-portal.com/features-modules.html" target="_blank">Modules</a>
or <a href="http://www.in-portal.com/support-downloads/customer-support.html" target="_blank">Support</a>
from Intechnic you will be provided with a license file, upload it here.</p>
<!--
<p><b><i>Download from Intechnic Servers</i></b> - .</p>
-->
<p><b><i>Use Existing License</i></b> - if a valid license has been detected on your server,
you can choose this option and continue the installation process.</p>]]>
</step>
<step name="download_license" title="Download License" help_title="Download License from Intechnic">
<![CDATA[<p><b>In-Portal is an Open Source</b> object-oriented framework that is developed in PHP
and provides a quick and easy way to build websites and web applications.</p>
<p>In-Portal is copyrighted and distributed under <a href="http://www.in-portal.org/license" target="_blank">GPLv2 license</a>.</p>
<p><b><i>GPL / Open Source License</i></b> - by downloading and installing In-Portal
under GPLv2 license you understand and agree to all terms of
<a href="http://www.in-portal.org/license" target="_blank">GPLv2 license</a>.</p>
<p><b><i>Download from Intechnic Servers</i></b> - if you have obtained Commercial
<a href="http://www.in-portal.com/features-modules.html" target="_blank">Modules</a>
or <a href="http://www.in-portal.com/support-downloads/customer-support.html" target="_blank">Support</a>
from Intechnic you will be provided with a license, specify your Username and Password in order to download the license.</p>]]>
</step>
<step name="select_domain" title="Select Domain" help_title="Select Licensed Domain">
<![CDATA[<p>Select the domain you wish to install In-Portal on.</p>
<p>The <i>Other</i> option can be used to install In-Portal other custom domains. Note that your web server should match entered domain name.</p>]]>
</step>
<step name="root_password" title="Set Root Password" help_title="Set Admin Root Password">
<![CDATA[<p>The <b>Root Password</b> is initially required to access the Admin Console of In-Portal.
The root user can <b>NOT</b> be used to access the Front-end of your In-Portal website.</p>
<p>Once installation is completed it's highly recommented to create additional users with admin privlidges.</p>]]>
</step>
<step name="choose_modules" title="Modules to Install">
<![CDATA[<p>Current step lists all <b>In-Portal Modules</b> that were found on your server and can be installed now.</p>
<p>Additional <a href="http://www.in-portal.com/features-modules.html" target="_blank">In-Portal Modules</a> can be found and downloaded <a href="http://www.in-portal.com/features-modules.html" target="_blank">here</a>.</p>
<p>While <a href="http://www.in-portal.com/features-modules.html" target="_blank">In-Portal Community</a> constantly works on improving In-Portal by creating new functionality and releasing new modules we are always looking for new ideas and Your help so we can make In-Portal even better software!</p>]]>
</step>
<step name="check_paths" title="Filesystem Check">
<![CDATA[<p><b>In-Portal Installer checks through the system folders and files</b> that require write permissions (777) to be set in order to run successfully In-Portal on your website.</p>
<p>In case if you see a <strong>Failure notice</strong> saying that In-Portal Installation cannot continue until all permissions are set correctly please continue reading below.</p>
<p><strong>Permissions can be set</strong> by using <a href="http://www.google.com/search?q=free+ftp+program" target="_blank">FTP program</a> or directly in <i>shell</i> running "chmod" command. Please refer to the following <a href="http://www.stadtaus.com/en/tutorials/chmod-ftp-file-permissions.php" target="_blank">guide</a> to learn how to set permissions using your FTP program. In case if you have access to <i>shell</i> in your account you can simply run fix_perms.sh files located in /tools folder or do <br/><br/>
&nbsp;&nbsp;&nbsp;# chmod -R 777 ../system ../themes ../system/config.php</p>
<p><strong>Security reasons</strong> you will be asked to change permissions back to 755 on /system/config.php file and root / folder of In-Portal on the last step of this installation process!</p>
]]>
</step>
<step name="post_config" title="Basic Configuration">
<![CDATA[<p>Adjust <b>Basic Configuration</b> settings on this step.</p>
<p>Once your In-Portal is installed you can login into <b>Admin Console</b> to change these and other settings. The Configuration section is located in main navigation menu.</p>
<br/>
<p><b>Additional Recommendations:</b></p>
<p><b><i>1. Use Cron</i></b> (<a href="http://en.wikipedia.org/wiki/Cron" target="_blank">UNIX/BSD/Linux</a>) or <b>Task Scheduler</b> (<a href="http://en.wikipedia.org/wiki/Task_Scheduler" target="_blank">Windows</a>) to run Regular Events in your In-Portal.<br />
It's highly recommended to setup your cron to run <b>every minute</b> so all system events that are enabled will run in the background based on their schedule. These events can be managed in Admin Console via <b><i>Configuration -> Website -> Scheduled Tasks</i></b> section.
<p>In-Portal <b>cron</b> file is located in <b>/tools/cron.php</b> folder and can be setup using hosting Control Panel or <a href="http://en.wikipedia.org/wiki/Cron" target="_blank">manually</a>. In Plesk or CPanel interfaces use dialog to add a new cron job and specify the following (use correct paths)<br />
&nbsp;&nbsp;&nbsp;<b>/absolute/path/to/bin/php -f /absolute/path/to/in-portal/tools/cron.php</b></p>
<p><b><i>2. Adjust Scheduled Tasks</i></b><br />
As was explained in the previous recommendation there is a <b><i>Configuration -> Website -> Scheduled Tasks</i></b> section where you can control Events triggered by the system. These events do their job to cleanup the data, old image files, check the data integrity, RSS feeds and other processes required for your In-Portal to run efficiently. We do recommend to review and enable/disable these events based on your website needs.</p>
<p><b><i>3. Set Mail Server</i></b><br />
It's recommended to review and adjust your mail server settings once your In-Portal is up and running. This can be done in Admin Console under <b><i>Configuration -> Website -> Advanced</i></b> section.</p>
<p><b>We strongly recommend carefully reviewing and adjusting all settings under Configuration -> Website section!</b></p>
]]>
</step>
<step name="sys_config" title="System Configuration">
<![CDATA[<p>These are system advanced settings and must be changed with caution. It's <strong><i>not recommended</i></strong> to
change these settings unless you exactly know what you are doing. These settings will be stored in <strong>system/config.php</strong>
file and can be changed manually if needed.</p>
<br/>
<p><b><i>Web Path to Installation</i></b> - web path to the root of your In-Portal installation. For example,
if your In-Portal will be running at http://www.your-website.com, then Web Path to Installation should be left empty
since In-Portal is setup in the root of the domain. In case if your In-Portal will be running under
http://www.your-website.com/in-portal/, then it should be set to <b>/in-portal</b> (no trailing slash). This setting is auto-detected during the
initial installation step, but can be adjusted at Installation Maintenance step.</p>
<p><b><i>Path to Writable folder</i></b> - path to a folder inside your In-Portal installation which can be accessed from the Web
and has writable permissions for the web server. This folder will be used to store dynamic content such as
uploaded and resized images, cached templates and other types of user files. The default value is <b>/system</b>.</p>
<p><b><i>Path to Restricted folder</i></b> - path to a folder inside or outside your In-Portal installation which will
used to store debug files, system logs and other non-public information. This folder must be writable by the web-server
and can be located outside of your In-Portal installation if needed. The default value is <b>/system/.restricted</b> .</p>
<p><b><i>Path to Admin folder</i></b> - web path to your In-Portal Admin Console folder. The default value is set to
<b>/admin</b> and your Admin Console will be accessible at http://www.your-website.com/admin.
In case if you want your Admin Console to be under http://www.your-website.com/secure-admin (or anything else)
you'll need to rename original <b>admin</b> folder to <b>secure-admin</b> on your filesystem and then set this path to <b>/secure-admin</b> .</p>
<p><b><i>Path to Admin Interface Presets folder</i></b> - path to a folder inside your In-Portal installation
contains Admin Interface Presets. The default value is <b>/admin</b> .</p>
<p><b><i>Name of Base Application Class</i></b> - default value is <b>kApplication</b> and can change very rarely. </p>
<p><b><i>Path to Base Application Class file</i></b> - default value is <b>/core/kernel/application.php</b> and can change very rarely.</p>
<p><b><i>Output Caching Engine</i></b> - provides ability to cache HTML output or other data using various caching engines to
lower the database load. The default value is set to <b>None</b> if no available engines detected. Available options are:
None (Fake), Memcached (Memcache), XCache (XCache) and Alternative PHP Cache (Apc).
Note that only auto-detected caching engines will be available for selection.</p>
<p><b><i>Location of Memcache Servers</i></b> - host or IP address with port where Memcached Server is running.
Multiple locations of can be listed separated by semi-colon (;). For example, 192.168.1.1:1121;192.168.1.2:1121;192.168.1.3:1121 .</p>
<p><b><i>CSS/JS Compression Engine</i></b> - provides <a href="http://en.wikipedia.org/wiki/Minification_(programming)">minification</a>
functionality for CSS / Javascript files. The default value is set to <b>PHP-based</b> if no Java is auto-detected on server-side.
Available options are: None (empty), YUICompressor (Java) (yui) and PHP-based (php) .</p>
<p><b><i>Website Charset</i></b> - character encoding that will be used across the website. By default this should be set to UTF-8,
but can set to other encoding also (see <a href="http://en.wikipedia.org/wiki/Character_encoding">wikipedia.org</a> options).
It's highly recommended to have Website Encoding match the Database Encoding (specified on DB step).</p>
<p><b><i>Enable "System Log"</i></b> - "System Log" has capability to record PHP Exceptions, Errors, Warnings, Notices, Database/SQL
Errors and Warnings, and User defined messages that happened on your website. It has 3 modes - Enabled (logs everything, including user
defined messages), User-only (user defined messages only), and Disabled (don't log anything at all - default setting).</p>
<p><b><i>Trust Proxy</i></b> - whatever to trust information provided by provided by proxy server (if any) located between web server
and client browser.</p>
<br/>
]]>
</step>
<step name="select_theme" title="Select Default Theme">
<![CDATA[<p>Selected theme will be used as a default in your In-Portal website.</p>
<p>You can manage your themes in Admin Console under Configuration -> Website -> Themes section.</p>
<p>Additional themes are available on <a href="http://www.in-portal.com/support-downloads.html" target="_blank">Support & Downloads</a> section on <a href="http://www.in-portal.com" target="_blank">In-Portal.com</a> website</p>]]>
</step>
<step name="security" title="Security Check">
<![CDATA[<p><strong>In-Portal Installer</strong> performs final security checks on this step.</p>
<p><b>1. Write Permissions Check</b> - checks whether critical In-Portal files are open for the outside world and can be used by hackers to attack your websites. <b>You won't be able to continue until you correctly set these permissions!</b></p>
<p><b>2. Ability to Execute PHP in Writable Folders</b> - checks if hackers can save and execute PHP files in your /system
folder used for the uploads.While it's recommended to adjust these settings you can continue In-Portal Installation without changing them.</p>
<p><b>3. Webserver PHP Configuration</b> - additional suggestions how to make your website even more secure. While it's recommended to adjust these settings you can continue In-Portal Installation without changing them.</p>
]]>
</step>
<step name="finish" title="Installation Complete" help_title="Thank You!">
<![CDATA[<p>Thank you for downloading and installing In-Portal Content Management System!</p>
<p>Feel free to visit <a target="_new" href="http://www.in-portal.com">www.in-portal.com</a> for support, latest news and module updates.</p>
<p><strong>Please make sure to clean your Browser's Cache if you were performing the upgrade.</strong></p>]]>
</step>
<step name="install_setup" title="Installation Maintenance">
<![CDATA[<p>A Configuration file has been detected on your system and it appears In-Portal is correctly installed.
In order to work with the maintenance functions provided to the left you must enter your admin Root password.
<b><i>(Use Username 'root' if using your root password)</i></b></p>
<p><b><i>Upgrade In-Portal</i></b> - available when you upload files from new In-Portal release into
your current installation. Upgrade scripts will run and upgrade your current In-Portal database to the uploaded version.</p>
<p><b><i>Reinstall In-Portal</i></b> - cleans out your existing In-Portal database and starts with a fresh installation.
<i>Note</i> that this operation cannot be undone and no backups are made! Use at your own risk.</p>
<p><b><i>Install In-Portal to a New Database</i></b> - keeps the existing installation and installs In-Portal to a new database.
If this option is selected you will be prompted for new database configuration information.</p>
<p><b><i>Update License Information</i></b> - used to update your In-Portal license data. Select this option if you have
modified your licensing status with Intechnic (obtained commercial support or module), or you have received new license data via email.</p>
<p><b><i>Update Database Configuration</i></b> - allows you to update your current database configuration variables such as
database server host, username, password and others.</p>
<p><b><i>Update Installation Paths</i></b> - should be used when the location of your In-Portal files has changed.
For example, if you moved them from one folder to another. It will update all settings and ensure In-Portal
is operational at the new location.</p>]]>
</step>
<step name="upgrade_modules" title="Select Modules to Upgrade">
<![CDATA[<p>Select modules from the list, you need to update to the last downloaded version of In-Portal</p>]]>
</step>
<step name="skin_upgrade" title="Admin Skin Upgrade">
<![CDATA[<p>Review Administrative Console skin upgrade log.</p>]]>
</step>
<step name="db_reconfig" title="Update Database Configuration">
<![CDATA[<p>In-Portal needs to connect to your Database Server. Please provide the database server type*,
host name (<i>normally "localhost"</i>), Database user name, and database Password. These fields are required
to connect to the database.</p><p>If you would like In-Portal to use a table prefix, enter it in the field
provided. This prefix can be any text which can be used in the names of tables on your system.
The characters entered in this field are placed <i>before</i> the names of the tables used by In-Portal.
For example, if you enter "inp_" into the prefix field, the table named Categories will be named inp_Categories.</p>]]>
</step>
<step name="sys_requirements" title="System Requirements Check">
<![CDATA[
<p>The <i>System Requirements Check</i> option should be used to ensure proper system behavior in the current environment.</p>
<p>
<b>PHP version 5.6 or above<span class="error">*</span></b><br/>
Use this PHP version or better to ensure normal website operation on every day basis.
</p>
<p>
<b>URL rewriting support</b><br/>
Allows to build nice looking SEO urls without specifying "/index.php" in each of them.
</p>
<p>
<b>Java template compression</b><br/>
When Java is installed on web server, then it's possible to use <a href="http://developer.yahoo.com/yui/compressor/" target="_blank">YUI Compressor</a>
to minify HTML, CSS and JavaScript output of website. This allows to make websites, which opens even faster, then before.
</p>
<p>
<b>Dependencies via Composer</b><br/>
In-Portal uses <a href="https://getcomposer.org/" target="_blank">Composer</a> to install required 3rd-party libraries.
Please ensure, that:<br/>
<ol>
<li>Composer is installed (<a href="https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx" target="_blank">instructions</a>)</li>
<li>Dependencies are installed (<a href="https://getcomposer.org/doc/00-intro.md#using-composer" target="_blank">instructions</a>)</li>
</ol>
</p>
<p>
<b>Memory caching support</b><br/>
When available use <a href="http://memcached.org/" target="_blank">Memcached</a> memory object caching system for data caching.
Will severely improve website performance under heavy load and page loading speed in general.
</p>
<p>
<b>Accessing remote resources (via cURL)</b><br/>
Allows to perform data retrieval from other websites (e.g. rss feeds) in background. Data retrieval internally is done
using <a href="http://curl.haxx.se/" target="_blank">cURL</a> library, that must be installed on web server.
</p>
<p>
<b>XML document processing (via SimpleXML)<span class="error">*</span></b><br/>
In-Portal uses XML files to store module/theme meta data. This
<a href="http://www.php.net/manual/en/book.simplexml.php" target="_blank">library</a> is used keep In-Portal
code clean as fast even, when processing XML files.
</p>
<p>
<b>Standard PHP Library (SPL)<span class="error">*</span></b><br/>
Usage of <a href="http://www.php.net/manual/en/book.spl.php" target="_blank">this library</a> guarantees memory
efficient way to manage files and data structures across In-Portal.
</p>
<p>
<b>TrueType font support (via Freetype)<span class="error">*</span></b><br/>
This library allows to use TrueType fonts inside produced images. In particular it's used for Captcha code generation.
</p>
<p>
<b>GD Graphics Library 1.8 or above<span class="error">*</span></b><br/>
<a href="http://www.boutell.com/gd/" target="_blank">This library</a> is used to perform various manipulations (e.g. resize, crop, etc.)
on user-uploaded images.
</p>
<p>
<b>JPEG images support<span class="error">*</span></b><br/>
Support image manipulations on user-uploaded images *.jpg and *.jpeg file extensions.
</p>
<p>
<b>Database connectivity (via MySQL)<span class="error">*</span></b><br/>
In-Portal uses MySQL database as it's persistent data storage.
</p>
<p>
<b>JSON processing support<span class="error">*</span></b><br/>
<a href="http://en.wikipedia.org/wiki/JSON" target="_blank">JSON</a> data format is used to implement AJAX
approach and perform complete page reload only, when necessary.
</p>
<p>
<b>Memory requirements changing on the fly</b><br/>
In-Portal requires at least 16 megabytes of memory to operate normally. However some resource consuming
operations (like link validation) might consume more memory, then usual. To ensure, that such operations
never fail In-Portal changes maximally allowed memory limit on the fly. See
<a href="http://www.php.net/manual/en/ini.core.php#ini.memory-limit" target="_blank">memory_limit</a> setting
for more info.
</p>
<p>
<b>Prevent script errors in production environment</b><br/>
Prevents any errors to be shown on website, that might happen due incorrect web server configuration. See
<a href="http://www.php.net/manual/ru/errorfunc.configuration.php#ini.display-errors" target="_blank">display_errors</a> setting
for more info.
</p>
<p>
<b>Change error detalization level</b><br/>
Ensures, that all error types are shown in development environment and none in production environment. See
<a href="http://www.php.net/manual/ru/function.error-reporting.php" target="_blank">error_reporting</a> setting
for more info.
</p>
<p>
<b>Web server timezone is explicitly set<span class="error">*</span></b><br/>
Web server timezone must be set explicitly to ensure correct date/time calculations and display across the website.
See <a href="http://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone" target="_blank">date.timezone</a>
setting for more info.
</p>
<p>
<b>Needed super-global arrays registered</b><br/>
Internally In-Portal relies on super-global array (e.g. $_SERVER, $_POST, etc.) presense inside a script. To make that happen
<a href="http://www.php.net/manual/en/ini.core.php#ini.variables-order" target="_blank">variables_order</a> setting must contain
following letters: "G", "P", "C", "S".
</p>
<p>
<b>Script output buffering enabled<span class="error">*</span></b><br/>
Output buffering is needed to allow usage of GZIP compression of page output. See
<a href="http://www.php.net/manual/en/outcontrol.configuration.php#ini.output-buffering" target="_blank">output_buffering</a>
setting for more info.
</p>
<p>
<b>Cookies enabled</b><br/>
However In-Portal can work without cookies (by adding ?sid=XXXXXXXX into each page url), but it's strongly
advised to use cookies-enabled web browser for better user expirience.
</p>
<p>
<b>JavaScript enabled</b><br/>
JavaScript might not be required on Front-End (depends on used theme), but it must be enabled in web browser
during installation and Admin Console usage.
</p>
]]>
</step>
</steps>
Index: branches/5.2.x/core/install.php
===================================================================
--- branches/5.2.x/core/install.php (revision 16818)
+++ branches/5.2.x/core/install.php (revision 16819)
@@ -1,1841 +1,1852 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
ini_set('display_errors', 1);
error_reporting(E_ALL & ~E_STRICT);
define('IS_INSTALL', 1);
define('ADMIN', 1);
define('FULL_PATH', realpath(dirname(__FILE__).'/..') );
define('REL_PATH', '/core');
// run installator
$install_engine = new kInstallator();
$install_engine->Init();
$install_engine->Run();
$install_engine->Done();
class kInstallator {
/**
* Reference to kApplication class object
*
* @var kApplication
*/
var $Application = null;
/**
* Connection to database
*
* @var IDBConnection
*/
var $Conn = null;
/**
* XML file containing steps information
*
* @var string
*/
var $StepDBFile = '';
/**
* Step name, that currently being processed
*
* @var string
*/
var $currentStep = '';
/**
* Steps list (preset) to use for current installation
*
* @var string
*/
var $stepsPreset = '';
/**
* Installation steps to be done
*
* @var Array
*/
var $steps = Array (
'fresh_install' => Array ('sys_requirements', 'check_paths', 'db_config', 'select_license', /*'download_license',*/ 'select_domain', 'root_password', 'choose_modules', 'post_config', 'sys_config', 'select_theme', 'security', 'finish'),
'clean_reinstall' => Array ('install_setup', 'sys_requirements', 'check_paths', 'clean_db', 'db_config', 'select_license', /*'download_license',*/ 'select_domain', 'root_password', 'choose_modules', 'post_config', 'sys_config', 'select_theme', 'security', 'finish'),
'already_installed' => Array ('check_paths', 'install_setup'),
'upgrade' => Array ('check_paths', 'install_setup', 'sys_config', 'upgrade_modules', 'skin_upgrade', 'security', 'finish'),
'update_license' => Array ('check_paths', 'install_setup', 'select_license', /*'download_license',*/ 'select_domain', 'security', 'finish'),
'update_config' => Array ('check_paths', 'install_setup', 'sys_config', 'security', 'finish'),
'db_reconfig' => Array ('check_paths', 'install_setup', 'db_reconfig', 'security', 'finish'),
'sys_requirements' => Array ('check_paths', 'install_setup', 'sys_requirements', 'security', 'finish')
);
/**
* Steps, that doesn't required admin to be logged-in to proceed
*
* @var Array
*/
var $skipLoginSteps = Array ('sys_requirements', 'check_paths', 'select_license', /*'download_license',*/ 'select_domain', 'root_password', 'choose_modules', 'post_config', 'select_theme', 'security', 'finish', -1);
/**
* Steps, on which kApplication should not be initialized, because of missing correct db table structure
*
* @var Array
*/
var $skipApplicationSteps = Array ('sys_requirements', 'check_paths', 'clean_db', 'db_config', 'db_reconfig' /*, 'install_setup'*/); // remove install_setup when application will work separately from install
/**
* Folders that should be writeable to continue installation. $1 - main writeable folder from config.php ("/system" by default)
*
* @var Array
*/
var $writeableFolders = Array (
'$1',
'$1/.restricted',
'$1/images',
'$1/images/pending',
'$1/images/emoticons', // for "In-Bulletin"
'$1/user_files',
'$1/cache',
);
/**
* Contains last error message text
*
* @var string
*/
var $errorMessage = '';
/**
* Base path for includes in templates
*
* @var string
*/
var $baseURL = '';
/**
* Holds number of last executed query in the SQL
*
* @var int
*/
var $LastQueryNum = 0;
/**
* Dependencies, that should be used in upgrade process
*
* @var Array
*/
var $upgradeDepencies = Array ();
/**
* Log of upgrade - list of upgraded modules and their versions
*
* @var Array
*/
var $upgradeLog = Array ();
/**
* Common tools required for installation process
*
* @var kInstallToolkit
*/
var $toolkit = null;
function Init()
{
include_once(FULL_PATH . REL_PATH . '/kernel/kbase.php'); // required by kDBConnection class
include_once(FULL_PATH . REL_PATH . '/kernel/utility/multibyte.php'); // emulating multi-byte php extension
include_once(FULL_PATH . REL_PATH . '/kernel/utility/system_config.php');
require_once(FULL_PATH . REL_PATH . '/install/install_toolkit.php'); // toolkit required for module installations to installator
$this->toolkit = new kInstallToolkit();
$this->toolkit->setInstallator($this);
$this->StepDBFile = FULL_PATH.'/'.REL_PATH.'/install/steps_db.xml';
$https_mark = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : false;
$protocol = ($https_mark == 'on') || ($https_mark == '1') ? 'https://' : 'http://';
$this->baseURL = $protocol . $_SERVER['HTTP_HOST'] . $this->toolkit->systemConfig->get('WebsitePath', 'Misc') . '/core/install/';
set_error_handler( Array(&$this, 'ErrorHandler') );
if ( $this->toolkit->systemConfigFound() ) {
// if config.php found, then check his write permission too
$this->writeableFolders[] = $this->toolkit->systemConfig->get('WriteablePath', 'Misc') . '/config.php';
}
$this->currentStep = $this->GetVar('step');
// can't check login on steps where no application present anyways :)
$this->skipLoginSteps = array_unique(array_merge($this->skipLoginSteps, $this->skipApplicationSteps));
$this->SelectPreset();
if (!$this->currentStep) {
$this->SetFirstStep(); // sets first step of current preset
}
$this->InitStep();
}
function SetFirstStep()
{
reset($this->steps[$this->stepsPreset]);
$this->currentStep = current($this->steps[$this->stepsPreset]);
}
/**
* Selects preset to proceed based on various criteria
*
*/
function SelectPreset()
{
$preset = $this->GetVar('preset');
if ($this->toolkit->systemConfigFound()) {
// only at installation first step
$status = $this->CheckDatabase(false);
if ($status && $this->AlreadyInstalled()) {
// if already installed, then all future actions need login to work
$this->skipLoginSteps = Array ('check_paths', -1);
if (!$preset) {
$preset = 'already_installed';
$this->currentStep = '';
}
}
}
if ($preset === false) {
$preset = 'fresh_install'; // default preset
}
$this->stepsPreset = $preset;
}
/**
* Returns variable from request
*
* @param string $name
* @param mixed $default
* @return string|bool
* @access private
*/
private function GetVar($name, $default = false)
{
if ( array_key_exists($name, $_COOKIE) ) {
return $_COOKIE[$name];
}
if ( array_key_exists($name, $_POST) ) {
return $_POST[$name];
}
return array_key_exists($name, $_GET) ? $_GET[$name] : $default;
}
/**
* Sets new value for request variable
*
* @param string $name
* @param mixed $value
* @return void
* @access private
*/
private function SetVar($name, $value)
{
$_POST[$name] = $value;
}
/**
* Performs needed intialization of data, that step requires
*
*/
function InitStep()
{
$require_login = !in_array($this->currentStep, $this->skipLoginSteps);
$this->InitApplication($require_login);
if ($require_login) {
// step require login to proceed
if (!$this->Application->LoggedIn()) {
$this->stepsPreset = 'already_installed';
$this->currentStep = 'install_setup'; // manually set 2nd step, because 'check_paths' step doesn't contain login form
// $this->SetFirstStep();
}
}
switch ($this->currentStep) {
case 'sys_requirements':
$required_checks = Array (
'php_version', 'composer', 'curl', 'simplexml', 'freetype', 'gd_version',
'jpeg', 'mysql', 'json', 'openssl', 'date.timezone', 'output_buffering',
);
$check_results = $this->toolkit->CallPrerequisitesMethod('core/', 'CheckSystemRequirements');
$required_checks = array_diff($required_checks, array_keys( array_filter($check_results) ));
if ( $required_checks ) {
// php-based checks failed - show error
$this->errorMessage = '<br/>Installation can not continue until all required environment parameters are set correctly';
}
elseif ( $this->GetVar('js_enabled') === false ) {
// can't check JS without form submit - set some fake error, so user stays on this step
$this->errorMessage = '&nbsp;';
}
elseif ( !$this->GetVar('js_enabled') || !$this->GetVar('cookies_enabled') ) {
// js/cookies disabled
$this->errorMessage = '<br/>Installation can not continue until all required environment parameters are set correctly';
}
break;
case 'check_paths':
$writeable_base = $this->toolkit->systemConfig->get('WriteablePath', 'Misc');
foreach ($this->writeableFolders as $folder_path) {
$file_path = FULL_PATH . str_replace('$1', $writeable_base, $folder_path);
if (file_exists($file_path) && !is_writable($file_path)) {
$this->errorMessage = '<br/>Installation can not continue until all required permissions are set correctly';
break;
}
}
if ( !$this->errorMessage && $this->toolkit->systemConfig->get('DBType', 'Database') == 'mysql' ) {
$this->toolkit->systemConfig->set('DBType', 'Database', 'mysqli');
$this->toolkit->systemConfig->save();
}
break;
case 'clean_db':
// don't use Application, because all tables will be erased and it will crash
$sql = 'SELECT Path
FROM ' . TABLE_PREFIX . 'Modules';
$modules = $this->Conn->GetCol($sql);
foreach ($modules as $module_folder) {
$remove_file = '/' . $module_folder . 'install/remove_schema.sql';
if (file_exists(FULL_PATH . $remove_file)) {
$this->toolkit->RunSQL($remove_file);
}
}
$this->toolkit->deleteEditTables();
$this->currentStep = $this->GetNextStep();
break;
case 'db_config':
case 'db_reconfig':
$fields = Array (
'DBType', 'DBHost', 'DBName', 'DBUser',
'DBUserPassword', 'DBCollation', 'TablePrefix'
);
// set fields
foreach ($fields as $field_name) {
$submit_value = $this->GetVar($field_name);
if ($submit_value !== false) {
$this->toolkit->systemConfig->set($field_name, 'Database', $submit_value);
}
/*else {
$this->toolkit->systemConfig->set($field_name, 'Database', '');
}*/
}
break;
case 'download_license':
$license_source = $this->GetVar('license_source');
if ($license_source !== false && $license_source != 1) {
// previous step was "Select License" and not "Download from Intechnic" option was selected
$this->currentStep = $this->GetNextStep();
}
break;
case 'choose_modules':
// if no modules found, then proceed to next step
$modules = $this->ScanModules();
if (!$modules) {
$this->currentStep = $this->GetNextStep();
}
break;
case 'select_theme':
// put available theme list in database
$this->toolkit->rebuildThemes();
break;
case 'upgrade_modules':
// get installed modules from db and compare their versions to upgrade script
$modules = $this->GetUpgradableModules();
if (!$modules) {
$this->currentStep = $this->GetNextStep();
}
break;
case 'skin_upgrade':
if ($this->Application->RecallVar('SkinUpgradeLog') === false) {
// no errors during skin upgrade -> skip this step
$this->currentStep = $this->GetNextStep();
}
break;
case 'install_setup':
if ( $this->Application->TableFound(TABLE_PREFIX . 'UserSession', true) ) {
// update to 5.2.0 -> rename session table before using it
// don't rename any other table here, since their names could be used in upgrade script
$this->Conn->Query('RENAME TABLE ' . TABLE_PREFIX . 'UserSession TO ' . TABLE_PREFIX . 'UserSessions');
$this->Conn->Query('RENAME TABLE ' . TABLE_PREFIX . 'SessionData TO ' . TABLE_PREFIX . 'UserSessionData');
}
$sessions_table_structure = $this->Conn->Query('DESCRIBE ' . TABLE_PREFIX . 'UserSessions', 'Field');
if ( !array_key_exists('SessionId', $sessions_table_structure) ) {
// Update to 5.2.2-B3 -> add missing columns before creating sessions.
$this->Conn->Query('ALTER TABLE ' . TABLE_PREFIX . 'UserSessions DROP INDEX `PRIMARY`');
$this->Conn->Query(
'ALTER TABLE ' . TABLE_PREFIX . 'UserSessions
ADD `SessionId` int NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST'
);
$this->Conn->Query(
'ALTER TABLE ' . TABLE_PREFIX . 'UserSessions
CHANGE `SessionKey` `SessionKey` char(64) NOT NULL DEFAULT ""'
);
$this->Conn->Query(
'ALTER TABLE ' . TABLE_PREFIX . 'UserSessions
ADD UNIQUE INDEX `SessionKey` (`SessionKey`) USING BTREE'
);
$this->Conn->Query(
'ALTER TABLE ' . TABLE_PREFIX . 'UserSessionData
CHANGE `SessionKey` `SessionId` bigint unsigned NOT NULL DEFAULT "0"'
);
}
$next_preset = $this->Application->GetVar('next_preset');
if ($next_preset !== false) {
/** @var UserHelper $user_helper */
$user_helper = $this->Application->recallObject('UserHelper');
$username = $this->Application->GetVar('login');
$password = $this->Application->GetVar('password');
if ($username == 'root') {
// verify "root" user using configuration settings
$login_result = $user_helper->loginUser($username, $password);
if ($login_result != LoginResult::OK) {
$error_phrase = $login_result == LoginResult::NO_PERMISSION ? 'la_no_permissions' : 'la_invalid_password';
$this->errorMessage = $this->Application->Phrase($error_phrase) . '. If you don\'t know your username or password, contact Intechnic Support';
}
}
else {
// non "root" user -> verify using licensing server
$url_params = Array (
'login' => md5($username),
'password' => md5($password),
'action' => 'check',
'license_code' => base64_encode( $this->toolkit->systemConfig->get('LicenseCode', 'Intechnic') ),
'version' => '4.3.0',//$this->toolkit->GetMaxModuleVersion('core/'),
'domain' => base64_encode($_SERVER['HTTP_HOST']),
);
/** @var kCurlHelper $curl_helper */
$curl_helper = $this->Application->recallObject('CurlHelper');
$curl_helper->SetRequestData($url_params);
$file_data = $curl_helper->Send(GET_LICENSE_URL);
if ( !$curl_helper->isGoodResponseCode() ) {
$this->errorMessage = 'In-Portal servers temporarily unavailable. Please contact <a href="mailto:support@in-portal.com">In-Portal support</a> personnel directly.';
}
elseif (substr($file_data, 0, 5) == 'Error') {
$this->errorMessage = substr($file_data, 6) . ' If you don\'t know your username or password, contact Intechnic Support';
}
if ($this->errorMessage == '') {
$user_helper->loginUserById(USER_ROOT);
}
}
if ($this->errorMessage == '') {
// processed with redirect to selected step preset
if (!isset($this->steps[$next_preset])) {
$this->errorMessage = 'Preset "'.$next_preset.'" not yet implemented';
}
else {
$this->stepsPreset = $next_preset;
}
}
}
else {
// if preset was not choosen, then raise error
$this->errorMessage = 'Please select action to perform';
}
break;
case 'security':
// perform write check
if ($this->Application->GetVar('skip_security_check')) {
// administrator intensionally skips security checks
break;
}
$write_check = true;
$check_paths = Array ('/', '/index.php', $this->toolkit->systemConfig->get('WriteablePath', 'Misc') . '/config.php', ADMIN_DIRECTORY . '/index.php');
foreach ($check_paths as $check_path) {
$path_check_status = $this->toolkit->checkWritePermissions(FULL_PATH . $check_path);
if (is_bool($path_check_status) && $path_check_status) {
$write_check = false;
break;
}
}
// script execute check
if (file_exists(WRITEABLE . '/install_check.php')) {
unlink(WRITEABLE . '/install_check.php');
}
$fp = fopen(WRITEABLE . '/install_check.php', 'w');
fwrite($fp, "<?php\n\techo 'OK';\n");
fclose($fp);
/** @var kCurlHelper $curl_helper */
$curl_helper = $this->Application->recallObject('CurlHelper');
$output = $curl_helper->Send($this->Application->BaseURL(WRITEBALE_BASE) . 'install_check.php');
unlink(WRITEABLE . '/install_check.php');
$execute_check = ($output !== 'OK');
$directive_check = true;
$ini_vars = Array ('register_globals' => false, 'open_basedir' => true, 'allow_url_fopen' => false);
foreach ($ini_vars as $var_name => $var_value) {
$current_value = ini_get($var_name);
if (($var_value && !$current_value) || (!$var_value && $current_value)) {
$directive_check = false;
break;
}
}
if (!$write_check || !$execute_check || !$directive_check) {
$this->errorMessage = true;
}
/*else {
$this->currentStep = $this->GetNextStep();
}*/
break;
}
$this->PerformValidation(); // returns validation status (just in case)
}
/**
* Validates data entered by user
*
* @return bool
*/
function PerformValidation()
{
if ($this->GetVar('step') != $this->currentStep) {
// just redirect from previous step, don't validate
return true;
}
$status = true;
switch ($this->currentStep) {
case 'db_config':
case 'db_reconfig':
// 1. check if required fields are filled
$section_name = 'Database';
$required_fields = Array ('DBType', 'DBHost', 'DBName', 'DBUser', 'DBCollation');
foreach ($required_fields as $required_field) {
if (!$this->toolkit->systemConfig->get($required_field, $section_name)) {
$status = false;
$this->errorMessage = 'Please fill all required fields';
break;
}
}
if ( !$status ) {
break;
}
// 2. check permissions, that use have in this database
$status = $this->CheckDatabase(($this->currentStep == 'db_config') && !$this->GetVar('UseExistingSetup'));
+
+ if ( $status ) {
+ $db_collation = $this->toolkit->systemConfig->get('DBCollation', 'Database');
+ $sql = 'SHOW COLLATION LIKE ' . $this->Conn->qstr($db_collation);
+ $db_collation_data = $this->Conn->Query($sql);
+
+ if ( !is_array($db_collation_data) || !$db_collation_data ) {
+ $status = false;
+ $this->errorMessage = 'Chosen database collation isn\'t compatible with used MySQL Server version';
+ }
+ }
break;
case 'select_license':
$license_source = $this->GetVar('license_source');
if ($license_source == 2) {
// license from file -> file must be uploaded
$upload_error = $_FILES['license_file']['error'];
if ($upload_error != UPLOAD_ERR_OK) {
$this->errorMessage = 'Missing License File';
}
}
elseif (!is_numeric($license_source)) {
$this->errorMessage = 'Please select license';
}
$status = $this->errorMessage == '';
break;
case 'root_password':
// check, that password & verify password match
$password = $this->Application->GetVar('root_password');
$password_verify = $this->Application->GetVar('root_password_verify');
if ($password != $password_verify) {
$this->errorMessage = 'Passwords does not match';
}
elseif (mb_strlen($password) < 4) {
$this->errorMessage = 'Root Password must be at least 4 characters';
}
$status = $this->errorMessage == '';
break;
case 'choose_modules':
break;
case 'upgrade_modules':
$modules = $this->Application->GetVar('modules');
if (!$modules) {
$modules = Array ();
$this->errorMessage = 'Please select module(-s) to ' . ($this->currentStep == 'choose_modules' ? 'install' : 'upgrade');
}
// check interface module
$upgrade_data = $this->GetUpgradableModules();
if (array_key_exists('core', $upgrade_data) && !in_array('core', $modules)) {
// core can be upgraded, but isn't selected
$this->errorMessage = 'Please select "Core" as interface module';
}
$status = $this->errorMessage == '';
break;
}
return $status;
}
/**
* Perform installation step actions
*
*/
function Run()
{
if ($this->errorMessage) {
// was error during data validation stage
return ;
}
switch ($this->currentStep) {
case 'check_paths':
$this->generateSecurityKeys();
break;
case 'db_config':
case 'db_reconfig':
// store db configuration
$sql = 'SHOW COLLATION
LIKE \''.$this->toolkit->systemConfig->get('DBCollation', 'Database').'\'';
$collation_info = $this->Conn->Query($sql);
if ($collation_info) {
$this->toolkit->systemConfig->set('DBCharset', 'Database', $collation_info[0]['Charset']);
// database is already connected, that's why set collation on the fly
$this->Conn->Query('SET NAMES \''.$this->toolkit->systemConfig->get('DBCharset', 'Database').'\' COLLATE \''.$this->toolkit->systemConfig->get('DBCollation', 'Database').'\'');
}
$this->toolkit->systemConfig->save();
if ($this->currentStep == 'db_config') {
if ($this->GetVar('UseExistingSetup')) {
// abort clean install and redirect to already_installed
$this->stepsPreset = 'already_installed';
break;
}
// import base data into new database, not for db_reconfig
$this->toolkit->RunSQL('/core/install/install_schema.sql');
$this->toolkit->RunSQL('/core/install/install_data.sql');
// create category using sql, because Application is not available here
$table_name = $this->toolkit->systemConfig->get('TablePrefix', 'Database') . 'IdGenerator';
$this->Conn->Query('UPDATE ' . $table_name . ' SET lastid = lastid + 1');
$resource_id = $this->Conn->GetOne('SELECT lastid FROM ' . $table_name);
if ($resource_id === false) {
$this->Conn->Query('INSERT INTO '.$table_name.' (lastid) VALUES (2)');
$resource_id = 2;
}
// can't use USER_ROOT constant, since Application isn't available here
$fields_hash = Array (
'l1_Name' => 'Content', 'l1_MenuTitle' => 'Content', 'Filename' => 'Content',
'AutomaticFilename' => 0, 'CreatedById' => -1, 'CreatedOn' => time(),
'ResourceId' => $resource_id - 1, 'l1_Description' => 'Content', 'Status' => 4,
);
$this->Conn->doInsert($fields_hash, $this->toolkit->systemConfig->get('TablePrefix', 'Database') . 'Categories');
$this->toolkit->SetModuleRootCategory('Core', $this->Conn->getInsertID());
// set module "Core" version after install (based on upgrade scripts)
$this->toolkit->SetModuleVersion('Core', 'core/');
// for now we set "In-Portal" module version to "Core" module version (during clean install)
$this->toolkit->SetModuleVersion('In-Portal', 'core/');
}
break;
case 'select_license':
// reset memory cache, when application is first available (on fresh install and clean reinstall steps)
$this->Application->HandleEvent(new kEvent('adm:OnResetMemcache'));
$license_source = $this->GetVar('license_source');
switch ($license_source) {
case 1: // Download from Intechnic
break;
case 2: // Upload License File
$file_data = array_map('trim', file($_FILES['license_file']['tmp_name']));
if ((count($file_data) == 3) && $file_data[1]) {
/** @var kModulesHelper $modules_helper */
$modules_helper = $this->Application->recallObject('ModulesHelper');
if ($modules_helper->verifyLicense($file_data[1])) {
$this->toolkit->systemConfig->set('License', 'Intechnic', $file_data[1]);
$this->toolkit->systemConfig->set('LicenseCode', 'Intechnic', $file_data[2]);
$this->toolkit->systemConfig->save();
}
else {
$this->errorMessage = 'Invalid License File';
}
}
else {
$this->errorMessage = 'Invalid License File';
}
break;
case 3: // Use Existing License
$license_hash = $this->toolkit->systemConfig->get('License', 'Intechnic');
if ($license_hash) {
/** @var kModulesHelper $modules_helper */
$modules_helper = $this->Application->recallObject('ModulesHelper');
if (!$modules_helper->verifyLicense($license_hash)) {
$this->errorMessage = 'Invalid or corrupt license detected';
}
}
else {
// happens, when browser's "Back" button is used
$this->errorMessage = 'Missing License File';
}
break;
case 4: // Skip License (Local Domain Installation)
if ($this->toolkit->sectionFound('Intechnic')) {
// remove any previous license information
$this->toolkit->systemConfig->set('License', 'Intechnic');
$this->toolkit->systemConfig->set('LicenseCode', 'Intechnic');
$this->toolkit->systemConfig->save();
}
break;
}
break;
case 'download_license':
$license_login = $this->GetVar('login');
$license_password = $this->GetVar('password');
$license_id = $this->GetVar('licenses');
/** @var kCurlHelper $curl_helper */
$curl_helper = $this->Application->recallObject('CurlHelper');
if (strlen($license_login) && strlen($license_password) && !$license_id) {
// Here we determine weather login is ok & check available licenses
$url_params = Array (
'login' => md5($license_login),
'password' => md5($license_password),
'version' => $this->toolkit->GetMaxModuleVersion('core/'),
'domain' => base64_encode($_SERVER['HTTP_HOST']),
);
$curl_helper->SetRequestData($url_params);
$file_data = $curl_helper->Send(GET_LICENSE_URL);
if (!$file_data) {
// error connecting to licensing server
$this->errorMessage = 'Unable to connect to the Intechnic server! Please try again later!';
}
else {
if (substr($file_data, 0, 5) == 'Error') {
// after processing data server returned error
$this->errorMessage = substr($file_data, 6);
}
else {
// license received
if (substr($file_data, 0, 3) == 'SEL') {
// we have more, then one license -> let user choose
$this->SetVar('license_selection', base64_encode( substr($file_data, 4) )); // we received html with radio buttons with names "licenses"
$this->errorMessage = 'Please select which license to use';
}
else {
// we have one license
$this->toolkit->processLicense($file_data);
}
}
}
}
else if (!$license_id) {
// licenses were not queried AND user/password missing
$this->errorMessage = 'Incorrect Username or Password. If you don\'t know your username or password, contact Intechnic Support';
}
else {
// Here we download license
$url_params = Array (
'license_id' => md5($license_id),
'dlog' => md5($license_login),
'dpass' => md5($license_password),
'version' => $this->toolkit->GetMaxModuleVersion('core/'),
'domain' => base64_encode($_SERVER['HTTP_HOST']),
);
$curl_helper->SetRequestData($url_params);
$file_data = $curl_helper->Send(GET_LICENSE_URL);
if (!$file_data) {
// error connecting to licensing server
$this->errorMessage = 'Unable to connect to the Intechnic server! Please try again later!';
}
else {
if (substr($file_data, 0, 5) == 'Error') {
// after processing data server returned error
$this->errorMessage = substr($file_data, 6);
}
else {
$this->toolkit->processLicense($file_data);
}
}
}
break;
case 'select_domain':
/** @var kModulesHelper $modules_helper */
$modules_helper = $this->Application->recallObject('ModulesHelper');
// get domain name as entered by user on the form
$domain = $this->GetVar('domain') == 1 ? $_SERVER['HTTP_HOST'] : str_replace(' ', '', $this->GetVar('other'));
$license_hash = $this->toolkit->systemConfig->get('License', 'Intechnic');
if ($license_hash) {
// when license present, then extract domain from it
$license_hash = base64_decode($license_hash);
list ( , , $license_keys) = $modules_helper->_ParseLicense($license_hash);
$license_domain = $license_keys[0]['domain'];
}
else {
// when license missing, then use current domain or domain entered by user
$license_domain = $domain;
}
if ($domain != '') {
if (strstr($domain, $license_domain) || $modules_helper->_IsLocalSite($domain)) {
$this->toolkit->systemConfig->set('Domain', 'Misc', $domain);
$this->toolkit->systemConfig->save();
}
else {
$this->errorMessage = 'Domain name entered does not match domain name in the license!';
}
}
else {
$this->errorMessage = 'Please enter valid domain!';
}
break;
case 'sys_config':
$config_data = $this->GetVar('system_config');
foreach ($config_data as $section => $section_vars) {
foreach ($section_vars as $var_name => $var_value) {
$this->toolkit->systemConfig->set($var_name, $section, $var_value);
}
}
$this->toolkit->systemConfig->save();
break;
case 'root_password':
// update root password in database
/** @var kPasswordFormatter $password_formatter */
$password_formatter = $this->Application->recallObject('kPasswordFormatter');
$config_values = Array (
'RootPass' => $password_formatter->hashPassword($this->Application->GetVar('root_password')),
'Backup_Path' => FULL_PATH . $this->toolkit->systemConfig->get('WriteablePath', 'Misc') . DIRECTORY_SEPARATOR . 'backupdata',
'DefaultEmailSender' => 'portal@' . $this->toolkit->systemConfig->get('Domain', 'Misc')
);
$site_timezone = date_default_timezone_get();
if ($site_timezone) {
$config_values['Config_Site_Time'] = $site_timezone;
}
$this->toolkit->saveConfigValues($config_values);
/** @var UserHelper $user_helper */
$user_helper = $this->Application->recallObject('UserHelper');
// login as "root", when no errors on password screen
$user_helper->loginUser('root', $this->Application->GetVar('root_password'));
// import base language for core (english)
$this->toolkit->ImportLanguage('/core/install/english');
// make sure imported language is set as active in session, created during installation
$this->Application->Session->SetField('Language', 1);
// set imported language as primary
/** @var LanguagesItem $lang */
$lang = $this->Application->recallObject('lang.-item', null, Array('skip_autoload' => true));
$lang->Load(1); // fresh install => ID=1
$lang->setPrimary(true); // for Front-End
break;
case 'choose_modules':
// run module install scripts
$modules = $this->Application->GetVar('modules');
if ($modules) {
foreach ($modules as $module) {
$install_file = MODULES_PATH.'/'.$module.'/install.php';
if (file_exists($install_file)) {
include_once($install_file);
}
}
}
// update category cache
/** @var kPermCacheUpdater $updater */
$updater = $this->Application->makeClass('kPermCacheUpdater');
$updater->OneStepRun();
break;
case 'post_config':
$this->toolkit->saveConfigValues( $this->GetVar('config') );
break;
case 'select_theme':
// 1. mark theme, that user is selected
$theme_id = $this->GetVar('theme');
$theme_table = $this->Application->getUnitOption('theme', 'TableName');
$theme_idfield = $this->Application->getUnitOption('theme', 'IDField');
$sql = 'UPDATE ' . $theme_table . '
SET Enabled = 1, PrimaryTheme = 1
WHERE ' . $theme_idfield . ' = ' . $theme_id;
$this->Conn->Query($sql);
$this->toolkit->rebuildThemes(); // rescan theme to create structure after theme is enabled !!!
// install theme dependent demo data
if ($this->Application->GetVar('install_demo_data')) {
$sql = 'SELECT Name
FROM ' . $theme_table . '
WHERE ' . $theme_idfield . ' = ' . $theme_id;
$theme_name = $this->Conn->GetOne($sql);
$site_path = $this->toolkit->systemConfig->get('WebsitePath','Misc') . '/';
/** @var FileHelper $file_helper */
$file_helper = $this->Application->recallObject('FileHelper');
foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
if ($module_name == 'In-Portal') {
continue;
}
$template_path = '/themes' . '/' . $theme_name . '/' . $module_info['TemplatePath'];
$this->toolkit->RunSQL( $template_path . '_install/install_data.sql', Array('{ThemeId}', '{SitePath}'), Array($theme_id, $site_path) );
if ( file_exists(FULL_PATH . $template_path . '_install/images') ) {
// copy theme demo images into writable path accessible by FCKEditor
$file_helper->copyFolderRecursive(FULL_PATH . $template_path . '_install/images' . DIRECTORY_SEPARATOR, WRITEABLE . '/user_files/Images');
}
}
}
break;
case 'upgrade_modules':
// get installed modules from db and compare their versions to upgrade script
$modules = $this->Application->GetVar('modules');
if ($modules) {
$upgrade_data = $this->GetUpgradableModules();
$start_from_query = $this->Application->GetVar('start_from_query');
$this->upgradeDepencies = $this->getUpgradeDependencies($modules, $upgrade_data);
if ($start_from_query !== false) {
$this->upgradeLog = unserialize( $this->Application->RecallVar('UpgradeLog') );
}
else {
$start_from_query = 0;
$this->upgradeLog = Array ('ModuleVersions' => Array ());
// remember each module version, before upgrade scripts are executed
foreach ($modules as $module_name) {
$module_info = $upgrade_data[$module_name];
$this->upgradeLog['ModuleVersions'][$module_name] = $module_info['FromVersion'];
}
$this->Application->RemoveVar('UpgradeLog');
}
// 1. perform "php before", "sql", "php after" upgrades
foreach ($modules as $module_name) {
$module_info = $upgrade_data[$module_name];
/*echo '<h2>Upgrading "' . $module_info['Name'] . '" to "' . $module_info['ToVersion'] . '"</h2>' . "\n";
flush();*/
if (!$this->RunUpgrade($module_info['Name'], $module_info['ToVersion'], $upgrade_data, $start_from_query)) {
$this->Application->StoreVar('UpgradeLog', serialize($this->upgradeLog));
$this->Done();
}
// restore upgradable module version (makes sense after sql error processing)
$upgrade_data[$module_name]['FromVersion'] = $this->upgradeLog['ModuleVersions'][$module_name];
}
// 2. import language pack, perform "languagepack" upgrade for all upgraded versions
foreach ($modules as $module_name) {
$module_info = $upgrade_data[$module_name];
$sqls =& $this->getUpgradeQueriesFromVersion($module_info['Path'], $module_info['FromVersion']);
preg_match_all('/' . VERSION_MARK . '/s', $sqls, $regs);
// import module language pack
$this->toolkit->ImportLanguage('/' . $module_info['Path'] . 'install/english', true);
// perform advanced language pack upgrade
foreach ($regs[1] as $version) {
$this->RunUpgradeScript($module_info['Path'], $version, 'languagepack');
}
}
// 3. update all theme language packs
/** @var kThemesHelper $themes_helper */
$themes_helper = $this->Application->recallObject('ThemesHelper');
$themes_helper->synchronizeModule(false);
// 4. upgrade admin skin
if (in_array('core', $modules)) {
$skin_upgrade_log = $this->toolkit->upgradeSkin($upgrade_data['core']);
if ($skin_upgrade_log === true) {
$this->Application->RemoveVar('SkinUpgradeLog');
}
else {
$this->Application->StoreVar('SkinUpgradeLog', serialize($skin_upgrade_log));
}
// for now we set "In-Portal" module version to "Core" module version (during upgrade)
$this->toolkit->SetModuleVersion('In-Portal', false, $upgrade_data['core']['ToVersion']);
}
}
break;
case 'finish':
// delete cache
$this->toolkit->deleteCache();
$this->toolkit->rebuildThemes();
// compile admin skin, so it will be available in 3 frames at once
/** @var SkinHelper $skin_helper */
$skin_helper = $this->Application->recallObject('SkinHelper');
/** @var kDBItem $skin */
$skin = $this->Application->recallObject('skin', null, Array ('skip_autoload' => true));
$skin->Load(1, 'IsPrimary');
$skin_helper->compile($skin);
// set installation finished mark
if ($this->Application->ConfigValue('InstallFinished') === false) {
$fields_hash = Array (
'VariableName' => 'InstallFinished',
'VariableValue' => 1,
);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX.'SystemSettings');
}
break;
}
if ($this->errorMessage) {
// was error during run stage
return ;
}
$this->currentStep = $this->GetNextStep();
$this->InitStep(); // init next step (that will be shown now)
$this->InitApplication();
if ($this->currentStep == -1) {
// step after last step -> redirect to admin
/** @var UserHelper $user_helper */
$user_helper = $this->Application->recallObject('UserHelper');
$user_helper->logoutUser();
$this->Application->Redirect($user_helper->event->redirect, $user_helper->event->getRedirectParams(), '', 'index.php');
}
}
/**
* Generates a security keys.
*
* @return void
*/
protected function generateSecurityKeys()
{
if ( $this->toolkit->systemConfig->get('SecurityHmacKey', 'Misc')
&& $this->toolkit->systemConfig->get('SecurityEncryptionKey', 'Misc')
) {
return;
}
// Include class declarations manually, because kApplication isn't available.
require_once FULL_PATH . '/core/kernel/security/SecurityEncrypter.php';
require_once FULL_PATH . '/core/kernel/security/SecurityGenerator.php';
require_once FULL_PATH . '/core/kernel/security/SecurityGeneratorPromise.php';
// Include dependencies, to make "random_int" function available in earlier PHP versions.
require_once FULL_PATH . '/vendor/autoload.php';
// Generate missing security-related settings.
$this->toolkit->systemConfig->set(
'SecurityHmacKey',
'Misc',
base64_encode(SecurityGenerator::generateString(
SecurityEncrypter::HASHING_KEY_LENGTH,
SecurityGenerator::CHAR_ALNUM | SecurityGenerator::CHAR_SYMBOLS
))
);
$this->toolkit->systemConfig->set(
'SecurityEncryptionKey',
'Misc',
SecurityGenerator::generateBytes(SecurityEncrypter::ENCRYPTION_KEY_LENGTH)
);
$this->toolkit->systemConfig->save();
}
function getUpgradeDependencies($modules, &$upgrade_data)
{
$dependencies = Array ();
foreach ($modules as $module_name) {
$module_info = $upgrade_data[$module_name];
$upgrade_object =& $this->getUpgradeObject($module_info['Path']);
if (!is_object($upgrade_object)) {
continue;
}
foreach ($upgrade_object->dependencies as $dependent_version => $version_dependencies) {
if (!$version_dependencies) {
// module is independent -> skip
continue;
}
$parent_name = key($version_dependencies);
$parent_version = $version_dependencies[$parent_name];
if (!array_key_exists($parent_name, $dependencies)) {
// parent module
$dependencies[$parent_name] = Array ();
}
if (!array_key_exists($parent_version, $dependencies[$parent_name])) {
// parent module versions, that are required by other module versions
$dependencies[$parent_name][$parent_version] = Array ();
}
$dependencies[$parent_name][$parent_version][] = Array ($module_info['Name'] => $dependent_version);
}
}
return $dependencies;
}
/**
* Returns database queries, that should be executed to perform upgrade from given to lastest version of given module path
*
* @param string $module_path
* @param string $from_version
* @return string
*/
function &getUpgradeQueriesFromVersion($module_path, $from_version)
{
$upgrades_file = sprintf(UPGRADES_FILE, $module_path, 'sql');
$sqls = file_get_contents($upgrades_file);
$version_mark = preg_replace('/(\(.*?\))/', $from_version, VERSION_MARK);
// get only sqls from next (relative to current) version to end of file
$start_pos = strpos($sqls, $version_mark);
$sqls = substr($sqls, $start_pos);
return $sqls;
}
function RunUpgrade($module_name, $to_version, &$upgrade_data, &$start_from_query)
{
$module_info = $upgrade_data[ strtolower($module_name) ];
$sqls =& $this->getUpgradeQueriesFromVersion($module_info['Path'], $module_info['FromVersion']);
preg_match_all('/(' . VERSION_MARK . ')/s', $sqls, $matches, PREG_SET_ORDER + PREG_OFFSET_CAPTURE);
foreach ($matches as $index => $match) {
// upgrade version
$version = $match[2][0];
if ($this->toolkit->ConvertModuleVersion($version) > $this->toolkit->ConvertModuleVersion($to_version)) {
// only upgrade to $to_version, not further
break;
}
if (!in_array($module_name . ':' . $version, $this->upgradeLog)) {
if ($this->Application->isDebugMode()) {
$this->Application->Debugger->appendHTML('Upgrading "' . $module_name . '" to "' . $version . '" version: BEGIN.');
}
/*echo 'Upgrading "' . $module_name . '" to "' . $version . '".<br/>' . "\n";
flush();*/
// don't upgrade same version twice
$start_pos = $match[0][1] + strlen($match[0][0]);
$end_pos = array_key_exists($index + 1, $matches) ? $matches[$index + 1][0][1] : strlen($sqls);
$version_sqls = substr($sqls, $start_pos, $end_pos - $start_pos);
if ($start_from_query == 0) {
$this->RunUpgradeScript($module_info['Path'], $version, 'before');
}
if (!$this->toolkit->RunSQLText($version_sqls, null, null, $start_from_query)) {
$this->errorMessage .= '<input type="hidden" name="start_from_query" value="' . $this->LastQueryNum . '">';
$this->errorMessage .= '<br/>Module "' . $module_name . '" upgrade to "' . $version . '" failed.';
$this->errorMessage .= '<br/>Click Continue button below to skip this query and go further<br/>';
return false;
}
else {
// reset query counter, when all queries were processed
$start_from_query = 0;
}
$this->RunUpgradeScript($module_info['Path'], $version, 'after');
if ($this->Application->isDebugMode()) {
$this->Application->Debugger->appendHTML('Upgrading "' . $module_name . '" to "' . $version . '" version: END.');
}
// remember, that we've already upgraded given version
$this->upgradeLog[] = $module_name . ':' . $version;
}
if (array_key_exists($module_name, $this->upgradeDepencies) && array_key_exists($version, $this->upgradeDepencies[$module_name])) {
foreach ($this->upgradeDepencies[$module_name][$version] as $dependency_info) {
$dependent_module = key($dependency_info);
$dependent_version = $dependency_info[$dependent_module];
if (!$this->RunUpgrade($dependent_module, $dependent_version, $upgrade_data, $start_from_query)) {
return false;
}
}
}
// only mark module as updated, when all it's dependent modules are upgraded
$this->toolkit->SetModuleVersion($module_name, false, $version);
}
return true;
}
/**
* Run upgrade PHP scripts for module with specified path
*
* @param string $module_path
* @param Array $version
* @param string $mode upgrade mode = {before,after,languagepack}
*/
function RunUpgradeScript($module_path, $version, $mode)
{
$upgrade_object =& $this->getUpgradeObject($module_path);
if (!is_object($upgrade_object)) {
return ;
}
$upgrade_method = 'Upgrade_' . str_replace(Array ('.', '-'), '_', $version);
if (method_exists($upgrade_object, $upgrade_method)) {
$upgrade_object->$upgrade_method($mode);
}
}
/**
* Returns upgrade class for given module path
*
* @param string $module_path
* @return kUpgradeHelper
*/
function &getUpgradeObject($module_path)
{
static $upgrade_classes = Array ();
$upgrades_file = sprintf(UPGRADES_FILE, $module_path, 'php');
if (!file_exists($upgrades_file)) {
$false = false;
return $false;
}
if (!isset($upgrade_classes[$module_path])) {
require_once(FULL_PATH . REL_PATH . '/install/upgrade_helper.php');
// save class name, because 2nd time (in after call)
// $upgrade_class variable will not be present
include_once $upgrades_file;
$upgrade_classes[$module_path] = $upgrade_class;
}
/** @var CoreUpgrades $upgrade_object */
$upgrade_object = new $upgrade_classes[$module_path]();
$upgrade_object->setToolkit($this->toolkit);
return $upgrade_object;
}
/**
* Initialize kApplication
*
* @param bool $force initialize in any case
*/
function InitApplication($force = false)
{
if (($force || !in_array($this->currentStep, $this->skipApplicationSteps)) && !isset($this->Application)) {
// step is allowed for application usage & it was not initialized in previous step
global $start, $debugger, $dbg_options;
include_once(FULL_PATH.'/core/kernel/startup.php');
$this->Application =& kApplication::Instance();
$this->toolkit->Application =& kApplication::Instance();
$this->includeModuleConstants();
$this->Application->Init();
$this->Conn =& $this->Application->GetADODBConnection();
$this->toolkit->Conn =& $this->Application->GetADODBConnection();
}
}
/**
* When no modules installed, then pre-include all modules contants, since they are used in unit configs
*
*/
function includeModuleConstants()
{
$modules = $this->ScanModules();
foreach ($modules as $module_path) {
$constants_file = MODULES_PATH . '/' . $module_path . '/constants.php';
if ( file_exists($constants_file) ) {
kUtil::includeOnce($constants_file);
}
}
}
/**
* Show next step screen
*
* @param string $error_message
* @return void
*/
function Done($error_message = null)
{
if ( isset($error_message) ) {
$this->errorMessage = $error_message;
}
include_once (FULL_PATH . '/' . REL_PATH . '/install/incs/install.tpl');
if ( isset($this->Application) ) {
$this->Application->Done();
}
exit;
}
function ConnectToDatabase()
{
include_once FULL_PATH . '/core/kernel/db/i_db_connection.php';
include_once FULL_PATH . '/core/kernel/db/db_connection.php';
$required_keys = Array ('DBType', 'DBUser', 'DBName');
foreach ($required_keys as $required_key) {
if (!$this->toolkit->systemConfig->get($required_key, 'Database')) {
// one of required db connection settings missing -> abort connection
return false;
}
}
$this->Conn = new kDBConnection($this->toolkit->systemConfig->get('DBType', 'Database'), Array(&$this, 'DBErrorHandler'));
$this->Conn->setup($this->toolkit->systemConfig->getData());
// setup toolkit too
$this->toolkit->Conn =& $this->Conn;
return !$this->Conn->hasError();
}
/**
* Checks if core is already installed
*
* @return bool
*/
function AlreadyInstalled()
{
$table_prefix = $this->toolkit->systemConfig->get('TablePrefix', 'Database');
$settings_table = $this->TableExists('ConfigurationValues') ? 'ConfigurationValues' : 'SystemSettings';
$sql = 'SELECT VariableValue
FROM ' . $table_prefix . $settings_table . '
WHERE VariableName = "InstallFinished"';
return $this->TableExists($settings_table) && $this->Conn->GetOne($sql);
}
function CheckDatabase($check_installed = true)
{
// perform various check type to database specified
// 1. user is allowed to connect to database
// 2. user has all types of permissions in database
// 3. database environment settings met minimum requirements
if (mb_strlen($this->toolkit->systemConfig->get('TablePrefix', 'Database')) > 7) {
$this->errorMessage = 'Table prefix should not be longer than 7 characters';
return false;
}
// connect to database
$status = $this->ConnectToDatabase();
if ($status) {
// if connected, then check if all sql statements work
$sql_tests[] = 'DROP TABLE IF EXISTS test_table';
$sql_tests[] = 'CREATE TABLE test_table(test_col mediumint(6))';
$sql_tests[] = 'LOCK TABLES test_table WRITE';
$sql_tests[] = 'INSERT INTO test_table(test_col) VALUES (5)';
$sql_tests[] = 'UPDATE test_table SET test_col = 12';
$sql_tests[] = 'UNLOCK TABLES';
$sql_tests[] = 'ALTER TABLE test_table ADD COLUMN new_col varchar(10)';
$sql_tests[] = 'SELECT * FROM test_table';
$sql_tests[] = 'DELETE FROM test_table';
$sql_tests[] = 'DROP TABLE IF EXISTS test_table';
foreach ($sql_tests as $sql_test) {
$this->Conn->Query($sql_test);
if ($this->Conn->getErrorCode() != 0) {
$status = false;
break;
}
}
if ($status) {
// if statements work & connection made, then check table existance
if ($check_installed && $this->AlreadyInstalled()) {
$this->errorMessage = 'An In-Portal Database already exists at this location';
return false;
}
$requirements_error = Array ();
$db_check_results = $this->toolkit->CallPrerequisitesMethod('core/', 'CheckDBRequirements');
if ( !$db_check_results['version'] ) {
$requirements_error[] = '- MySQL Version is below 5.0';
}
if ( !$db_check_results['packet_size'] ) {
$requirements_error[] = '- MySQL Packet Size is below 1 MB';
}
if ( $requirements_error ) {
$this->errorMessage = 'Connection successful, but following system requirements were not met:<br/>' . implode('<br/>', $requirements_error);
return false;
}
}
else {
// user has insufficient permissions in database specified
$this->errorMessage = 'Permission Error: ('.$this->Conn->getErrorCode().') '.$this->Conn->getErrorMsg();
return false;
}
}
else {
// was error while connecting
if (!$this->Conn) return false;
$this->errorMessage = 'Connection Error: ('.$this->Conn->getErrorCode().') '.$this->Conn->getErrorMsg();
return false;
}
return true;
}
/**
* Checks if all passed tables exists
*
* @param string $tables comma separated tables list
* @return bool
*/
function TableExists($tables)
{
$prefix = $this->toolkit->systemConfig->get('TablePrefix', 'Database');
$all_found = true;
$tables = explode(',', $tables);
foreach ($tables as $table_name) {
$sql = 'SHOW TABLES LIKE "'.$prefix.$table_name.'"';
if (count($this->Conn->Query($sql)) == 0) {
$all_found = false;
break;
}
}
return $all_found;
}
/**
* Returns modules list found in modules folder
*
* @return Array
*/
function ScanModules()
{
static $modules = null;
if ( !isset($modules) ) {
// use direct include, because it's called before kApplication::Init, that creates class factory
kUtil::includeOnce( KERNEL_PATH . kApplication::MODULE_HELPER_PATH );
$modules_helper = new kModulesHelper();
$modules = $modules_helper->getModules();
}
return $modules;
}
/**
* Virtually place module under "modules" folder or it won't be recognized during upgrade to 5.1.0 version
*
* @param string $name
* @param string $path
* @param string $version
* @return string
*/
function getModulePath($name, $path, $version)
{
if ($name == 'Core') {
// don't transform path for Core module
return $path;
}
if (!preg_match('/^modules\//', $path)) {
// upgrade from 5.0.x/1.0.x to 5.1.x/1.1.x
return 'modules/' . $path;
}
return $path;
}
/**
* Returns list of modules, that can be upgraded
*
*/
function GetUpgradableModules()
{
$ret = Array ();
foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
if ($module_name == 'In-Portal') {
// don't show In-Portal, because it shares upgrade scripts with Core module
continue;
}
$module_info['Path'] = $this->getModulePath($module_name, $module_info['Path'], $module_info['Version']);
$upgrades_file = sprintf(UPGRADES_FILE, $module_info['Path'], 'sql');
if (!file_exists($upgrades_file)) {
// no upgrade file
continue;
}
$sqls = file_get_contents($upgrades_file);
$versions_found = preg_match_all('/'.VERSION_MARK.'/s', $sqls, $regs);
if (!$versions_found) {
// upgrades file doesn't contain version definitions
continue;
}
$to_version = end($regs[1]);
$this_version = $this->toolkit->ConvertModuleVersion($module_info['Version']);
if ($this->toolkit->ConvertModuleVersion($to_version) > $this_version) {
// destination version is greather then current
foreach ($regs[1] as $version) {
if ($this->toolkit->ConvertModuleVersion($version) > $this_version) {
$from_version = $version;
break;
}
}
$version_info = Array (
'FromVersion' => $from_version,
'ToVersion' => $to_version,
);
$ret[ strtolower($module_name) ] = array_merge($module_info, $version_info);
}
}
return $ret;
}
/**
* Returns content to show for current step
*
* @return string
*/
function GetStepBody()
{
$step_template = FULL_PATH.'/core/install/step_templates/'.$this->currentStep.'.tpl';
if (file_exists($step_template)) {
ob_start();
include_once ($step_template);
return ob_get_clean();
}
return '{step template "'.$this->currentStep.'" missing}';
}
/**
* Parses step information file, cache result for current step ONLY & return it
*
* @return Array
*/
function &_getStepInfo()
{
static $info = Array('help_title' => null, 'step_title' => null, 'help_body' => null, 'queried' => false);
if (!$info['queried']) {
$fdata = file_get_contents($this->StepDBFile);
$parser = xml_parser_create();
xml_parse_into_struct($parser, $fdata, $values, $index);
xml_parser_free($parser);
foreach ($index['STEP'] as $section_index) {
$step_data =& $values[$section_index];
if ($step_data['attributes']['NAME'] == $this->currentStep) {
$info['step_title'] = $step_data['attributes']['TITLE'];
if (isset($step_data['attributes']['HELP_TITLE'])) {
$info['help_title'] = $step_data['attributes']['HELP_TITLE'];
}
else {
// if help title not set, then use step title
$info['help_title'] = $step_data['attributes']['TITLE'];
}
$info['help_body'] = trim($step_data['value']);
break;
}
}
$info['queried'] = true;
}
return $info;
}
/**
* Returns particular information abou current step
*
* @param string $info_type
* @return string
*/
function GetStepInfo($info_type)
{
$step_info =& $this->_getStepInfo();
if (isset($step_info[$info_type])) {
return $step_info[$info_type];
}
return '{step "'.$this->currentStep.'"; param "'.$info_type.'" missing}';
}
/**
* Returns passed steps titles
*
* @param Array $steps
* @return Array
* @see kInstaller:PrintSteps
*/
function _getStepTitles($steps)
{
$fdata = file_get_contents($this->StepDBFile);
$parser = xml_parser_create();
xml_parse_into_struct($parser, $fdata, $values, $index);
xml_parser_free($parser);
$ret = Array ();
foreach ($index['STEP'] as $section_index) {
$step_data =& $values[$section_index];
if (in_array($step_data['attributes']['NAME'], $steps)) {
$ret[ $step_data['attributes']['NAME'] ] = $step_data['attributes']['TITLE'];
}
}
return $ret;
}
/**
* Returns current step number in active steps_preset.
* Value can't be cached, because same step can have different number in different presets
*
* @return int
*/
function GetStepNumber()
{
return array_search($this->currentStep, $this->steps[$this->stepsPreset]) + 1;
}
/**
* Returns step name to process next
*
* @return string
*/
function GetNextStep()
{
$next_index = $this->GetStepNumber();
if ($next_index > count($this->steps[$this->stepsPreset]) - 1) {
return -1;
}
return $this->steps[$this->stepsPreset][$next_index];
}
/**
* Returns step name, that was processed before this step
*
* @return string
*/
function GetPreviousStep()
{
$next_index = $this->GetStepNumber() - 1;
if ($next_index < 0) {
$next_index = 0;
}
return $this->steps[$this->stepsPreset][$next_index];
}
/**
* Prints all steps from active steps preset and highlights current step
*
* @param string $active_tpl
* @param string $passive_tpl
* @return string
*/
function PrintSteps($active_tpl, $passive_tpl)
{
$ret = '';
$step_titles = $this->_getStepTitles($this->steps[$this->stepsPreset]);
foreach ($this->steps[$this->stepsPreset] as $step_name) {
$template = $step_name == $this->currentStep ? $active_tpl : $passive_tpl;
$ret .= sprintf($template, $step_titles[$step_name]);
}
return $ret;
}
/**
* Installation error handler for sql errors
*
* @param int $code
* @param string $msg
* @param string $sql
* @return bool
* @access private
*/
function DBErrorHandler($code, $msg, $sql)
{
$this->errorMessage = 'Query: <br />'.htmlspecialchars($sql, ENT_QUOTES, 'UTF-8').'<br />execution result is error:<br />['.$code.'] '.$msg;
return true;
}
/**
* Installation error handler
*
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
* @param Array|string $errcontext
*/
function ErrorHandler($errno, $errstr, $errfile = '', $errline = 0, $errcontext = '')
{
if ($errno == E_USER_ERROR) {
// only react on user fatal errors
$this->Done($errstr);
}
}
/**
* Checks, that given button should be visible on current installation step
*
* @param string $name
* @return bool
*/
function buttonVisible($name)
{
$button_visibility = Array (
'continue' => $this->GetNextStep() != -1 || ($this->stepsPreset == 'already_installed'),
'refresh' => in_array($this->currentStep, Array ('sys_requirements', 'check_paths', 'security')),
'back' => in_array($this->currentStep, Array (/*'select_license',*/ 'download_license', 'select_domain')),
);
if ($name == 'any') {
foreach ($button_visibility as $button_name => $button_visible) {
if ($button_visible) {
return true;
}
}
return false;
}
return array_key_exists($name, $button_visibility) ? $button_visibility[$name] : true;
}
}

Event Timeline