diff --git a/src/mibew/.htaccess b/src/mibew/.htaccess
index a37136a0..b773f43b 100644
--- a/src/mibew/.htaccess
+++ b/src/mibew/.htaccess
@@ -34,9 +34,13 @@ Options +FollowSymLinks
RewriteEngine On
+ # Use separate front controller for the system installator
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteRule ^install(|/(.*))$ install.php [QSA,L]
+
# Alter only requests for files that do not exist
RewriteCond %{REQUEST_FILENAME} !-f
- # Rewrite all requests to front controller
+ # Rewrite all other requests to front controller
RewriteRule ^(.*)$ app.php [QSA,L]
diff --git a/src/mibew/app.php b/src/mibew/app.php
index ce6f51ff..78927baa 100644
--- a/src/mibew/app.php
+++ b/src/mibew/app.php
@@ -27,7 +27,10 @@ use Symfony\Component\Config\FileLocator;
$file_locator = new FileLocator(array(MIBEW_FS_ROOT));
$router = new Router(new RouteCollectionLoader($file_locator));
-$router->setOption('route_collection', RouteCollectionLoader::ROUTES_ALL);
+$router->setOption(
+ 'route_collection',
+ RouteCollectionLoader::ROUTES_CORE | RouteCollectionLoader::ROUTES_PLUGINS
+);
$application = new Application($router, new AuthenticationManager());
diff --git a/src/mibew/install.php b/src/mibew/install.php
new file mode 100644
index 00000000..99c1b0f9
--- /dev/null
+++ b/src/mibew/install.php
@@ -0,0 +1,45 @@
+setOption(
+ 'route_collection',
+ RouteCollectionLoader::ROUTES_CORE | RouteCollectionLoader::ROUTES_INSTALLATION
+);
+
+$application = new Application($router, new DummyAuthenticationManager());
+
+// Process request
+$request = Request::createFromGlobals();
+$response = $application->handleRequest($request);
+
+// Send response to the user
+$response->prepare($request);
+$response->send();
diff --git a/src/mibew/install/dbinfo.php b/src/mibew/install/dbinfo.php
deleted file mode 100644
index 1d8d7c2f..00000000
--- a/src/mibew/install/dbinfo.php
+++ /dev/null
@@ -1,455 +0,0 @@
- array(
- "groupid" => "int NOT NULL auto_increment PRIMARY KEY",
- "parent" => "int DEFAULT NULL",
- "vcemail" => "varchar(64)",
- "vclocalname" => "varchar(64) NOT NULL",
- "vccommonname" => "varchar(64) NOT NULL",
- "vclocaldescription" => "varchar(1024) NOT NULL",
- "vccommondescription" => "varchar(1024) NOT NULL",
- "iweight" => "int NOT NULL DEFAULT 0",
- "vctitle" => "varchar(255) DEFAULT ''",
- "vcchattitle" => "varchar(255) DEFAULT ''",
- "vclogo" => "varchar(255) DEFAULT ''",
- "vchosturl" => "varchar(255) DEFAULT ''",
- ),
-
- // Chat threads
- "${mysqlprefix}chatthread" => array(
- // ID of the thread.
- "threadid" => "int NOT NULL auto_increment PRIMARY KEY",
- // Name of the user in chat.
- "userName" => "varchar(64) NOT NULL",
- // ID of the user. This field is foreign key for
- // {chatsitevisitor}.userid
- "userid" => "varchar(255)",
- // Name of the operator who took place in the chat.
- "agentName" => "varchar(64)",
- // ID of the operator who took place in the chat.
- "agentId" => "int NOT NULL DEFAULT 0",
- // Unix timestamp of the moment when the thread was created.
- "dtmcreated" => "int NOT NULL DEFAULT 0",
- // Unix timestamp of the moment when chat actually started.
- "dtmchatstarted" => "int NOT NULL DEFAULT 0",
- // Unix timestamp of the last thread modification.
- "dtmmodified" => "int NOT NULL DEFAULT 0",
- // Unix timestamp of the moment when the thread was closed.
- "dtmclosed" => "int NOT NULL DEFAULT 0",
- // ID of the last thread revision.
- "lrevision" => "int NOT NULL DEFAULT 0",
- // State of the thread. It is one of Thread::STATE_* constants.
- "istate" => "int NOT NULL DEFAULT 0",
- // State of invitation related with the thread. It is one of
- // Thread::INVITATION_* constants.
- "invitationstate" => "int NOT NULL DEFAULT 0",
- // Last token of the thread.
- "ltoken" => "int NOT NULL",
- // IP address of the user.
- "remote" => "varchar(255)",
- // Page from which chat thread was started.
- "referer" => "text",
- // ID of the operator who will next in the chat.
- "nextagent" => "int NOT NULL DEFAULT 0",
- // Code of chat locale.
- "locale" => "varchar(8)",
- // Unix timestamp of the last request from user's window to server.
- "lastpinguser" => "int NOT NULL DEFAULT 0",
- // Unix timestamp of the last request from operator's window to server.
- "lastpingagent" => "int NOT NULL DEFAULT 0",
- // Indicates if user typing or not. It can take two values 0 and 1.
- "userTyping" => "int DEFAULT 0",
- // Indicates if operator typing or not. It can take two values 0 and 1.
- "agentTyping" => "int DEFAULT 0",
- // ID of shown message in the chat.
- "shownmessageid" => "int NOT NULL DEFAULT 0",
- // User agent description that took from 'User-Agent' HTTP header.
- "userAgent" => "varchar(255)",
- // Total count of user's messages related with the thread.
- "messageCount" => "varchar(16)",
- // ID of the group at Mibew side related with the thread.
- "groupid" => "int references ${mysqlprefix}chatgroup(groupid)",
- ),
-
- "${mysqlprefix}chatthreadstatistics" => array(
- "statid" => "int NOT NULL auto_increment PRIMARY KEY",
- "date" => "int NOT NULL DEFAULT 0",
- "threads" => "int NOT NULL DEFAULT 0",
- "missedthreads" => "int NOT NULL DEFAULT 0",
- "sentinvitations" => "int NOT NULL DEFAULT 0",
- "acceptedinvitations" => "int NOT NULL DEFAULT 0",
- "rejectedinvitations" => "int NOT NULL DEFAULT 0",
- "ignoredinvitations" => "int NOT NULL DEFAULT 0",
- "operatormessages" => "int NOT NULL DEFAULT 0",
- "usermessages" => "int NOT NULL DEFAULT 0",
- "averagewaitingtime" => "FLOAT(10, 1) NOT NULL DEFAULT 0",
- "averagechattime" => "FLOAT(10, 1) NOT NULL DEFAULT 0"
- ),
-
- "${mysqlprefix}requestbuffer" => array(
- "requestid" => "int NOT NULL auto_increment PRIMARY KEY",
- // Use MD5 hashes as keys
- "requestkey" => "char(32) NOT NULL",
- "request" => "text NOT NULL"
- ),
-
- "${mysqlprefix}requestcallback" => array(
- "callbackid" => "int NOT NULL auto_increment PRIMARY KEY",
- "token" => "varchar(64) NOT NULL DEFAULT ''",
- "function" => "varchar(64) NOT NULL",
- "arguments" => "varchar(1024)"
- ),
-
- // Contains updated translations
- "${mysqlprefix}translation" => array(
- "stringid" => "int NOT NULL auto_increment PRIMARY KEY",
- "locale" => "varchar(5) NOT NULL",
- "context" => "varchar(256) NOT NULL DEFAULT ''",
- "source" => "text COLLATE utf8_bin",
- "translation" => "text",
- ),
-
- // Contains locales info
- "${mysqlprefix}locale" => array(
- // Artificial primary key
- "localeid" => "int NOT NULL auto_increment PRIMARY KEY",
- // Locale code
- "code" => "varchar(5) NOT NULL",
- // Indicates if a locale is enabled or not.
- "enabled" => "tinyint NOT NULL DEFAULT 0",
- ),
-
- // Contains localized mail templates
- "${mysqlprefix}mailtemplate" => array(
- // Artificial primary key
- "templateid" => "int NOT NULL auto_increment PRIMARY KEY",
- // Locale code a template belongs to
- "locale" => "varchar(5) NOT NULL",
- // Machine name of a template
- "name" => "varchar(256) NOT NULL",
- // Mail subject
- "subject" => "varchar(1024) NOT NULL",
- // Mail body
- "body" => "text",
- ),
-
- // Store chat thread messages
- "${mysqlprefix}chatmessage" => array(
- // Message ID.
- "messageid" => "int NOT NULL auto_increment PRIMARY KEY",
- // ID of the thread related with the message.
- "threadid" => "int NOT NULL references ${mysqlprefix}chatthread(threadid)",
- // Message kind. It is one of Thread::KIND_* constants.
- "ikind" => "int NOT NULL",
- // ID of operator who sent the message. This value will be ignored for
- // system messages and messages which sent by users.
- "agentId" => "int NOT NULL DEFAULT 0",
- // Message text body.
- "tmessage" => "text NOT NULL",
- // Name of the plugin which sent the message. If message was not sent by
- // a plugin this field equals to an empty string.
- "plugin" => "varchar(256) NOT NULL DEFAULT ''",
- // Arbitrary serialized data related with message.
- "data" => "text",
- // Unix timestamp when message was created.
- "dtmcreated" => "int NOT NULL DEFAULT 0",
- // Name of the message sender.
- "tname" => "varchar(64)"
- ),
-
- "${mysqlprefix}chatoperator" => array(
- "operatorid" => "int NOT NULL auto_increment PRIMARY KEY",
- "vclogin" => "varchar(64) NOT NULL",
- "vcpassword" => "varchar(64) NOT NULL",
- "vclocalename" => "varchar(64) NOT NULL",
- "vccommonname" => "varchar(64) NOT NULL",
- "vcemail" => "varchar(64)",
- "dtmlastvisited" => "int NOT NULL DEFAULT 0",
- "istatus" => "int DEFAULT 0", /* 0 - online, 1 - away */
- "idisabled" => "int DEFAULT 0",
- "vcavatar" => "varchar(255)",
- "vcjabbername" => "varchar(255)",
- "iperm" => "int DEFAULT 0", /* Do not grant all privileges by default */
- "dtmrestore" => "int NOT NULL DEFAULT 0",
- "vcrestoretoken" => "varchar(64)",
- // Use to start chat with specified operator
- "code" => "varchar(64) DEFAULT ''"
- ),
-
- "${mysqlprefix}chatoperatorstatistics" => array(
- "statid" => "int NOT NULL auto_increment PRIMARY KEY",
- "date" => "int NOT NULL DEFAULT 0",
- "operatorid" => "int NOT NULL",
- "threads" => "int NOT NULL DEFAULT 0",
- "messages" => "int NOT NULL DEFAULT 0",
- "averagelength" => "FLOAT(10, 1) NOT NULL DEFAULT 0",
- "sentinvitations" => "int NOT NULL DEFAULT 0",
- "acceptedinvitations" => "int NOT NULL DEFAULT 0",
- "rejectedinvitations" => "int NOT NULL DEFAULT 0",
- "ignoredinvitations" => "int NOT NULL DEFAULT 0"
- ),
-
- "${mysqlprefix}chatrevision" => array(
- "id" => "INT NOT NULL"
- ),
-
- "${mysqlprefix}chatgroupoperator" => array(
- "groupid" => "int NOT NULL references ${mysqlprefix}chatgroup(groupid)",
- "operatorid" => "int NOT NULL references ${mysqlprefix}chatoperator(operatorid)",
- ),
-
- "${mysqlprefix}chatban" => array(
- "banid" => "INT NOT NULL auto_increment PRIMARY KEY",
- "dtmcreated" => "int NOT NULL DEFAULT 0",
- "dtmtill" => "int NOT NULL DEFAULT 0",
- "address" => "varchar(255)",
- "comment" => "varchar(255)",
- "blockedCount" => "int DEFAULT 0"
- ),
-
- "${mysqlprefix}chatconfig" => array(
- "id" => "INT NOT NULL auto_increment PRIMARY KEY",
- "vckey" => "varchar(255)",
- "vcvalue" => "varchar(255)",
- ),
-
- "${mysqlprefix}chatresponses" => array(
- "id" => "INT NOT NULL auto_increment PRIMARY KEY",
- "locale" => "varchar(8)",
- "groupid" => "int references ${mysqlprefix}chatgroup(groupid)",
- "vctitle" => "varchar(100) NOT NULL DEFAULT ''",
- "vcvalue" => "varchar(1024) NOT NULL",
- ),
-
- "${mysqlprefix}chatsitevisitor" => array(
- "visitorid" => "INT NOT NULL auto_increment PRIMARY KEY",
- "userid" => "varchar(255) NOT NULL",
- "username" => "varchar(64)",
- "firsttime" => "int NOT NULL DEFAULT 0",
- "lasttime" => "int NOT NULL DEFAULT 0",
- "entry" => "text NOT NULL",
- "details" => "text NOT NULL",
- "invitations" => "INT NOT NULL DEFAULT 0",
- "chats" => "INT NOT NULL DEFAULT 0",
- "threadid" => "INT references ${mysqlprefix}chatthread(threadid) on delete set null"
- ),
-
- "${mysqlprefix}visitedpage" => array(
- "pageid" => "INT NOT NULL auto_increment PRIMARY KEY",
- "address" => "varchar(1024)",
- "visittime" => "int NOT NULL DEFAULT 0",
- "visitorid" => "INT",
- // Indicates if path included in 'by page' statistics
- "calculated" => "tinyint NOT NULL DEFAULT 0"
- ),
-
- "${mysqlprefix}visitedpagestatistics" => array(
- "pageid" => "INT NOT NULL auto_increment PRIMARY KEY",
- "date" => "int NOT NULL DEFAULT 0",
- "address" => "varchar(1024)",
- "visits" => "int NOT NULL DEFAULT 0",
- "chats" => "int NOT NULL DEFAULT 0",
- "sentinvitations" => "int NOT NULL DEFAULT 0",
- "acceptedinvitations" => "int NOT NULL DEFAULT 0",
- "rejectedinvitations" => "int NOT NULL DEFAULT 0",
- "ignoredinvitations" => "int NOT NULL DEFAULT 0"
- ),
-);
-
-$dbtables_indexes = array(
- "${mysqlprefix}chatgroup" => array(
- "parent" => "parent"
- ),
- "${mysqlprefix}chatoperatorstatistics" => array(
- "operatorid" => "operatorid"
- ),
- "${mysqlprefix}chatgroupoperator" => array(
- "groupid" => "groupid",
- "operatorid" => "operatorid"
- ),
- "${mysqlprefix}requestbuffer" => array(
- "requestkey" => "requestkey"
- ),
- "${mysqlprefix}chatmessage" => array(
- "idx_agentid" => "agentid"
- ),
- "${mysqlprefix}chatsitevisitor" => array(
- "threadid" => "threadid"
- ),
- "${mysqlprefix}requestcallback" => array(
- "token" => "token"
- ),
- "${mysqlprefix}visitedpage" => array(
- "visitorid" => "visitorid"
- )
-);
-
-$memtables = array();
-
-$dbtables_can_update = array(
- "${mysqlprefix}chatthread" => array("agentId", "userTyping", "agentTyping", "messageCount", "nextagent", "shownmessageid", "userid", "userAgent", "groupid", "dtmchatstarted", "dtmclosed", "invitationstate"),
- "${mysqlprefix}chatthreadstatistics" => array("missedthreads", "sentinvitations", "acceptedinvitations", "rejectedinvitations", "ignoredinvitations"),
- "${mysqlprefix}requestbuffer" => array("requestid", "requestkey", "request"),
- "${mysqlprefix}chatmessage" => array("agentId", "plugin", "data"),
- "${mysqlprefix}chatoperator" => array("vcavatar", "vcjabbername", "iperm", "istatus", "idisabled", "vcemail", "dtmrestore", "vcrestoretoken", "code"),
- "${mysqlprefix}chatoperatorstatistics" => array("sentinvitations", "acceptedinvitations", "rejectedinvitations", "ignoredinvitations"),
- "${mysqlprefix}chatban" => array(),
- "${mysqlprefix}chatgroup" => array("vcemail", "iweight", "parent", "vctitle", "vcchattitle", "vclogo", "vchosturl"),
- "${mysqlprefix}chatgroupoperator" => array(),
- "${mysqlprefix}chatresponses" => array("vctitle"),
- "${mysqlprefix}chatsitevisitor" => array(),
- "${mysqlprefix}requestcallback" => array("callbackid", "token", "function", "arguments"),
- "${mysqlprefix}visitedpage" => array(),
- "${mysqlprefix}visitedpagestatistics" => array("sentinvitations", "acceptedinvitations", "rejectedinvitations", "ignoredinvitations"),
-);
-
-function show_install_err($text)
-{
- global $page;
- $page = array(
- 'version' => MIBEW_VERSION,
- 'localeLinks' => get_locale_links(),
- 'title' => getlocal("Problem"),
- 'no_right_menu' => true,
- 'fixedwrap' => true,
- 'errors' => array($text),
- );
- $page_style = new \Mibew\Style\PageStyle('default');
- start_html_output();
- echo($page_style->render('install_err', $page));
- exit;
-}
-
-function create_table($id, $link)
-{
- global $dbtables, $dbtables_indexes, $memtables, $mysqlprefix;
-
- if (!isset($dbtables[$id])) {
- show_install_err("Unknown table: $id, " . mysql_error($link));
- }
-
- $query =
- "CREATE TABLE $id\n" .
- "(\n";
- foreach ($dbtables[$id] as $k => $v) {
- $query .= " $k $v,\n";
- }
-
- if (isset($dbtables_indexes[$id])) {
- foreach ($dbtables_indexes[$id] as $k => $v) {
- $query .= " INDEX $k ($v),\n";
- }
- }
-
- $query = preg_replace("/,\n$/", "", $query);
- $query .= ") charset utf8";
- if (in_array($id, $memtables)) {
- $query .= " ENGINE=MEMORY";
- } else {
- $query .= " ENGINE=InnoDb";
- }
-
- mysql_query($query, $link) or show_install_err(' Query failed: ' . mysql_error($link));
-
- if ($id == "${mysqlprefix}chatoperator") {
- // Create First Administrator
- // Grant all privileges by default only for First Administrator
- mysql_query(
- "INSERT INTO ${mysqlprefix}chatoperator ( " .
- "vclogin, " .
- "vcpassword, " .
- "vclocalename, " .
- "vccommonname, " .
- "vcavatar, " .
- "vcemail, " .
- "iperm " .
- ") values ( " .
- "'admin', " .
- "MD5(''), " .
- "'', " .
- "'Administrator', " .
- "'Administrator', " .
- "'', " .
- "65535" .
- ")",
- $link
- );
- } else if ($id == "${mysqlprefix}chatrevision") {
- $result = mysql_query("INSERT INTO ${mysqlprefix}chatrevision VALUES (1)", $link);
- if (! $result) {
- die(' Query failed: ' . mysql_error($link));
- }
- }
-}
-
-function get_tables($link)
-{
- global $mysqldb, $errors;
- $result = mysql_query("SHOW TABLES FROM `$mysqldb`", $link);
- if ($result) {
- $arr = array();
- while ($row = mysql_fetch_array($result, MYSQL_NUM)) {
- $arr[] = $row[0];
- }
- mysql_free_result($result);
- return $arr;
-
- } else {
- $errors[] = "Cannot get tables from database. Error: " . mysql_error($link);
- return false;
- }
-}
-
-function get_columns($tablename, $link)
-{
- global $errors;
- $result = mysql_query("SHOW COLUMNS FROM $tablename", $link);
- if ($result) {
- $arr = array();
- while ($row = mysql_fetch_array($result, MYSQL_NUM)) {
- $arr[] = $row[0];
- }
- mysql_free_result($result);
- return $arr;
-
- } else {
- $errors[] = "Cannot get columns from table \"$tablename\". Error: " . mysql_error($link);
- return false;
- }
-}
-
-function get_indexes($tablename, $link)
-{
- global $mysqldb, $errors;
- $result = mysql_query("SELECT index_name FROM information_schema.statistics where table_schema = '$mysqldb' and table_name = '$tablename' and index_name != 'PRIMARY'", $link);
- if ($result) {
- $arr = array();
- while ($row = mysql_fetch_array($result, MYSQL_NUM)) {
- $arr[] = $row[0];
- }
- mysql_free_result($result);
- return $arr;
-
- } else {
- $errors[] = "Cannot get indexes for table \"$tablename\". Error: " . mysql_error($link);
- return false;
- }
-}
-
-?>
\ No newline at end of file
diff --git a/src/mibew/install/dbperform.php b/src/mibew/install/dbperform.php
deleted file mode 100644
index 026ae192..00000000
--- a/src/mibew/install/dbperform.php
+++ /dev/null
@@ -1,333 +0,0 @@
- $columns) {
- $curr_columns = get_columns($id, $link);
- if ($curr_columns === false) {
- show_install_err($errors[0]);
- }
- $tocreate = array_diff(array_keys($columns), $curr_columns);
- foreach ($tocreate as $v) {
- $absent_columns[] = "$id.$v";
- }
- }
-
- if (in_array("${mysqlprefix}chatmessage.agentId", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatmessage ADD agentId int NOT NULL DEFAULT 0 AFTER ikind", $link);
- runsql("update ${mysqlprefix}chatmessage, ${mysqlprefix}chatoperator set agentId = operatorid where agentId = 0 AND ikind = 2 AND (vclocalename = tname OR vccommonname = tname)", $link);
- }
-
- if (in_array("${mysqlprefix}chatmessage.plugin", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatmessage ADD plugin varchar(256) NOT NULL DEFAULT '' AFTER tmessage", $link);
- }
-
- if (in_array("${mysqlprefix}chatmessage.data", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatmessage ADD data text AFTER plugin", $link);
- }
-
- if (in_array("${mysqlprefix}chatthread.agentId", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthread ADD agentId int NOT NULL DEFAULT 0 AFTER agentName", $link);
- runsql("update ${mysqlprefix}chatthread, ${mysqlprefix}chatoperator set agentId = operatorid where agentId = 0 AND (vclocalename = agentName OR vccommonname = agentName)", $link);
- }
-
- if (in_array("${mysqlprefix}chatthread.dtmchatstarted", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthread ADD dtmchatstarted int NOT NULL DEFAULT 0 AFTER dtmcreated", $link);
- runsql("update ${mysqlprefix}chatthread set dtmchatstarted = dtmcreated", $link);
- }
-
- if (in_array("${mysqlprefix}chatthread.dtmclosed", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthread ADD dtmclosed int NOT NULL DEFAULT 0 AFTER dtmmodified", $link);
- runsql("update ${mysqlprefix}chatthread set dtmclosed = dtmmodified", $link);
- }
-
- if (in_array("${mysqlprefix}chatthread.agentTyping", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthread ADD agentTyping int DEFAULT 0", $link);
- }
-
- if (in_array("${mysqlprefix}chatthread.userTyping", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthread ADD userTyping int DEFAULT 0", $link);
- }
-
- if (in_array("${mysqlprefix}chatthread.messageCount", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthread ADD messageCount varchar(16)", $link);
- runsql("ALTER TABLE ${mysqlprefix}chatmessage ADD INDEX idx_threadid_ikind (threadid, ikind)", $link);
- runsql("UPDATE ${mysqlprefix}chatthread t SET t.messageCount = (SELECT COUNT(*) FROM ${mysqlprefix}chatmessage WHERE ${mysqlprefix}chatmessage.threadid = t.threadid AND ikind = 1)", $link);
- runsql("ALTER TABLE ${mysqlprefix}chatmessage DROP INDEX idx_threadid_ikind", $link);
- }
-
- if (in_array("${mysqlprefix}chatthread.nextagent", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthread ADD nextagent int NOT NULL DEFAULT 0", $link);
- }
-
- if (in_array("${mysqlprefix}chatthread.shownmessageid", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthread ADD shownmessageid int NOT NULL DEFAULT 0", $link);
- }
-
- if (in_array("${mysqlprefix}chatthread.userid", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthread ADD userid varchar(255) DEFAULT \"\"", $link);
- }
-
- if (in_array("${mysqlprefix}chatthread.invitationstate", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthread ADD invitationstate int NOT NULL DEFAULT 0 AFTER istate", $link);
- }
-
- if (in_array("${mysqlprefix}chatthreadstatistics.missedthreads", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthreadstatistics ADD missedthreads int NOT NULL DEFAULT 0 AFTER threads", $link);
- }
-
- if (in_array("${mysqlprefix}chatthreadstatistics.sentinvitations", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthreadstatistics ADD sentinvitations int NOT NULL DEFAULT 0 AFTER missedthreads", $link);
- }
-
- if (in_array("${mysqlprefix}chatthreadstatistics.acceptedinvitations", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthreadstatistics ADD acceptedinvitations int NOT NULL DEFAULT 0 AFTER sentinvitations", $link);
- }
-
- if (in_array("${mysqlprefix}chatthreadstatistics.rejectedinvitations", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthreadstatistics ADD rejectedinvitations int NOT NULL DEFAULT 0 AFTER acceptedinvitations", $link);
- }
-
- if (in_array("${mysqlprefix}chatthreadstatistics.ignoredinvitations", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthreadstatistics ADD ignoredinvitations int NOT NULL DEFAULT 0 AFTER rejectedinvitations", $link);
- }
-
- if (in_array("${mysqlprefix}chatoperator.iperm", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatoperator ADD iperm int DEFAULT 65535", $link);
- }
-
- if (in_array("${mysqlprefix}chatoperator.istatus", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatoperator ADD istatus int DEFAULT 0", $link);
- }
-
- if (in_array("${mysqlprefix}chatoperator.idisabled", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatoperator ADD idisabled int DEFAULT 0 AFTER istatus", $link);
- }
-
- if (in_array("${mysqlprefix}chatoperator.vcavatar", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatoperator ADD vcavatar varchar(255)", $link);
- }
-
- if (in_array("${mysqlprefix}chatoperator.vcjabbername", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatoperator ADD vcjabbername varchar(255)", $link);
- }
-
- if (in_array("${mysqlprefix}chatoperator.vcemail", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatoperator ADD vcemail varchar(64)", $link);
- }
-
- if (in_array("${mysqlprefix}chatoperator.dtmrestore", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatoperator ADD dtmrestore int NOT NULL DEFAULT 0", $link);
- }
-
- if (in_array("${mysqlprefix}chatoperator.vcrestoretoken", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatoperator ADD vcrestoretoken varchar(64)", $link);
- }
-
- if (in_array("${mysqlprefix}chatoperator.code", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatoperator ADD code varchar(64) DEFAULT ''", $link);
- }
-
- if (in_array("${mysqlprefix}chatoperatorstatistics.sentinvitations", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatoperatorstatistics ADD sentinvitations int NOT NULL DEFAULT 0", $link);
- }
-
- if (in_array("${mysqlprefix}chatoperatorstatistics.acceptedinvitations", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatoperatorstatistics ADD acceptedinvitations int NOT NULL DEFAULT 0", $link);
- }
-
- if (in_array("${mysqlprefix}chatoperatorstatistics.rejectedinvitations", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatoperatorstatistics ADD rejectedinvitations int NOT NULL DEFAULT 0", $link);
- }
-
- if (in_array("${mysqlprefix}chatoperatorstatistics.ignoredinvitations", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatoperatorstatistics ADD ignoredinvitations int NOT NULL DEFAULT 0", $link);
- }
-
- if (in_array("${mysqlprefix}chatresponses.vctitle", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatresponses ADD vctitle varchar(100) NOT NULL DEFAULT '' AFTER groupid", $link);
- }
-
- if (in_array("${mysqlprefix}chatthread.groupid", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthread ADD groupid int references ${mysqlprefix}chatgroup(groupid)", $link);
- }
-
- if (in_array("${mysqlprefix}chatthread.userAgent", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatthread ADD userAgent varchar(255)", $link);
- }
-
- if (in_array("${mysqlprefix}chatgroup.vcemail", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatgroup ADD vcemail varchar(64)", $link);
- }
-
- if (in_array("${mysqlprefix}chatgroup.iweight", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatgroup ADD iweight int DEFAULT 0", $link);
- }
-
- if (in_array("${mysqlprefix}chatgroup.parent", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatgroup ADD parent int DEFAULT NULL AFTER groupid", $link);
- }
-
- if (in_array("${mysqlprefix}chatgroup.vctitle", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatgroup ADD vctitle varchar(255) DEFAULT ''", $link);
- }
-
- if (in_array("${mysqlprefix}chatgroup.vcchattitle", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatgroup ADD vcchattitle varchar(255) DEFAULT ''", $link);
- }
-
- if (in_array("${mysqlprefix}chatgroup.vclogo", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatgroup ADD vclogo varchar(255) DEFAULT ''", $link);
- }
-
- if (in_array("${mysqlprefix}chatgroup.vchosturl", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}chatgroup ADD vchosturl varchar(255) DEFAULT ''", $link);
- }
-
- if (in_array("${mysqlprefix}visitedpagestatistics.sentinvitations", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}visitedpagestatistics ADD sentinvitations int NOT NULL DEFAULT 0", $link);
- }
-
- if (in_array("${mysqlprefix}visitedpagestatistics.acceptedinvitations", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}visitedpagestatistics ADD acceptedinvitations int NOT NULL DEFAULT 0", $link);
- }
-
- if (in_array("${mysqlprefix}visitedpagestatistics.rejectedinvitations", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}visitedpagestatistics ADD rejectedinvitations int NOT NULL DEFAULT 0", $link);
- }
-
- if (in_array("${mysqlprefix}visitedpagestatistics.ignoredinvitations", $absent_columns)) {
- runsql("ALTER TABLE ${mysqlprefix}visitedpagestatistics ADD ignoredinvitations int NOT NULL DEFAULT 0", $link);
- }
-
-// Add absent indexes
- $absent_indexes = array();
- foreach ($dbtables_indexes as $id => $indexes) {
- $curr_indexes = get_indexes($id, $link);
- if ($curr_indexes === false) {
- show_install_err($errors[0]);
- }
- $tocreate = array_diff(array_keys($indexes), $curr_indexes);
- foreach ($tocreate as $i) {
- $absent_indexes[] = "$id.$i";
- }
- }
-
- if (in_array("${mysqlprefix}chatgroup.parent", $absent_indexes)) {
- runsql("ALTER TABLE ${mysqlprefix}chatgroup ADD INDEX (parent)", $link);
- }
-
- if (in_array("${mysqlprefix}chatgroupoperator.groupid", $absent_indexes)) {
- runsql("ALTER TABLE ${mysqlprefix}chatgroupoperator ADD INDEX (groupid)", $link);
- }
-
- if (in_array("${mysqlprefix}chatgroupoperator.operatorid", $absent_indexes)) {
- runsql("ALTER TABLE ${mysqlprefix}chatgroupoperator ADD INDEX (operatorid)", $link);
- }
-
- if (in_array("${mysqlprefix}chatmessage.idx_agentid", $absent_indexes)) {
- runsql("ALTER TABLE ${mysqlprefix}chatmessage ADD INDEX idx_agentid (agentid)", $link);
- }
-
- if (in_array("${mysqlprefix}chatsitevisitor.threadid", $absent_indexes)) {
- runsql("ALTER TABLE ${mysqlprefix}chatsitevisitor ADD INDEX (threadid)", $link);
- }
-
- if (in_array("${mysqlprefix}visitedpage.visitorid", $absent_indexes)) {
- runsql("ALTER TABLE ${mysqlprefix}visitedpage ADD INDEX (visitorid)", $link);
- }
-
- if (in_array("${mysqlprefix}chatoperatorstatistics.operatorid", $absent_indexes)) {
- runsql("ALTER TABLE ${mysqlprefix}chatoperatorstatistics ADD INDEX (operatorid)", $link);
- }
- }
-}
-
-mysql_close($link);
-header("Location: " . MIBEW_WEB_ROOT . "/install/index.php");
-exit;
-?>
\ No newline at end of file
diff --git a/src/mibew/install/index.php b/src/mibew/install/index.php
deleted file mode 100644
index 5c821ef2..00000000
--- a/src/mibew/install/index.php
+++ /dev/null
@@ -1,505 +0,0 @@
- MIBEW_VERSION,
- 'localeLinks' => get_locale_links()
-);
-
-$page['done'] = array();
-$page['nextstep'] = false;
-$page['nextnotice'] = false;
-$page['soundcheck'] = false;
-$errors = array();
-
-function check_mibewroot()
-{
- global $page, $errors;
-
- if (MIBEW_CONFIG_WEB_ROOT != MIBEW_WEB_ROOT) {
- $errors[] = "Please, check file " . MIBEW_WEB_ROOT . "/libs/config.php
Wrong value of \$mibewroot variable, should be \"" . MIBEW_WEB_ROOT . "\"";
- return false;
- }
-
- $page['done'][] = getlocal("Application path is {0}", array(MIBEW_WEB_ROOT));
- return true;
-}
-
-function fpermissions($file)
-{
- $perms = fileperms($file);
- if (($perms & 0x8000) == 0x8000) {
- $info = '-';
- } elseif (($perms & 0x4000) == 0x4000) {
- $info = 'd';
- } else {
- $info = '?';
- }
-
- // Owner
- $info .= (($perms & 0x0100) ? 'r' : '-');
- $info .= (($perms & 0x0080) ? 'w' : '-');
- $info .= (($perms & 0x0040) ?
- (($perms & 0x0800) ? 's' : 'x') :
- (($perms & 0x0800) ? 'S' : '-'));
-
- // Group
- $info .= (($perms & 0x0020) ? 'r' : '-');
- $info .= (($perms & 0x0010) ? 'w' : '-');
- $info .= (($perms & 0x0008) ?
- (($perms & 0x0400) ? 's' : 'x') :
- (($perms & 0x0400) ? 'S' : '-'));
-
- // World
- $info .= (($perms & 0x0004) ? 'r' : '-');
- $info .= (($perms & 0x0002) ? 'w' : '-');
- $info .= (($perms & 0x0001) ?
- (($perms & 0x0200) ? 't' : 'x') :
- (($perms & 0x0200) ? 'T' : '-'));
-
- return $info;
-}
-
-function check_files()
-{
- global $page, $errors;
-
- $packageFile = MIBEW_FS_ROOT . "/install/package";
- $fp = @fopen($packageFile, "r");
- if ($fp === FALSE) {
- $errors[] = getlocal("Cannot read file {0}", array(MIBEW_WEB_ROOT . "/install/package"));
- if (file_exists($packageFile)) {
- $errors[] = getlocal("Insufficient file permissions {0}", array(fpermissions($packageFile)));
- }
- return false;
- }
-
- $knownFiles = array();
- while (!feof($fp)) {
- $line = fgets($fp, 4096);
- $keyval = preg_split("/ /", $line, 2);
- if (isset($keyval[1])) {
- $knownFiles[$keyval[0]] = trim($keyval[1]);
- }
- }
- fclose($fp);
-
- foreach ($knownFiles as $file => $sum) {
- $relativeName = MIBEW_FS_ROOT . "/$file";
- if (!is_readable($relativeName)) {
- if (file_exists($relativeName)) {
- $errors[] = getlocal("Cannot read file {0}", array(MIBEW_WEB_ROOT . "/$file"));
- $errors[] = getlocal("Insufficient file permissions {0}", array(fpermissions($relativeName)));
- } else {
- $errors[] = getlocal("File is absent: {0}", array(MIBEW_WEB_ROOT . "/$file"));
- }
- return false;
- }
- if ($sum != "-") {
- $result = md5_file($relativeName);
- if ($result != $sum) {
- // try without \r
- $result = md5(str_replace("\r", "", file_get_contents($relativeName)));
- }
- if ($result != $sum) {
- $errors[] = getlocal("Checksum differs for {0}", array(MIBEW_WEB_ROOT . "/$file"));
- $errors[] = getlocal("Please, re-upload files to the server.");
- return false;
- }
- }
- }
-
- $page['done'][] = getlocal("Mibew package is valid.");
- return true;
-}
-
-function check_connection()
-{
- global $mysqlhost, $mysqllogin, $mysqlpass, $page, $errors;
- $link = @mysql_connect($mysqlhost, $mysqllogin, $mysqlpass);
- if ($link) {
- $result = mysql_query("SELECT VERSION() as c", $link);
- if ($result && $ver = mysql_fetch_array($result, MYSQL_ASSOC)) {
- $page['done'][] = getlocal("You are connected to MySQL server version {0}", array($ver['c']));
- mysql_free_result($result);
- } else {
- $errors[] = "Version of your SQL server is unknown. Please check. Error: " . mysql_error($link);
- mysql_close($link);
- return null;
- }
- return $link;
- } else {
- $errors[] = getlocal("Could not connect. Please check server settings in config.php. Error: {0}", array(mysql_error()));
- return null;
- }
-}
-
-function check_database($link)
-{
- global $mysqldb, $page;
- if (mysql_select_db($mysqldb, $link)) {
- $page['done'][] = getlocal("Database \"{0}\" is created.", array($mysqldb));
- mysql_query("SET character set utf8", $link);
-
- return true;
- } else {
- $page['nextstep'] = getlocal("Create database \"{0}\"", array($mysqldb));
- $page['nextnotice'] = getlocal("The database was not found on the server. If you have permissions to create it now, click on the following link.");
- $page['nextstepurl'] = MIBEW_WEB_ROOT . "/install/dbperform.php?act=createdb";
- }
- return false;
-}
-
-function check_tables($link)
-{
- global $dbtables, $page;
- $curr_tables = get_tables($link);
- if ($curr_tables !== false) {
- $tocreate = array_diff(array_keys($dbtables), $curr_tables);
- if (count($tocreate) == 0) {
- $page['done'][] = getlocal("Required tables are created.");
- return true;
- } else {
- $page['nextstep'] = getlocal("Create required tables.");
- $page['nextstepurl'] = MIBEW_WEB_ROOT . "/install/dbperform.php?act=ct";
- }
- }
- return false;
-}
-
-function check_columns($link)
-{
- global $dbtables, $dbtables_can_update, $dbtables_indexes, $errors, $page;
-
- $need_to_create_columns = false;
- foreach ($dbtables as $id => $columns) {
- $curr_columns = get_columns($id, $link);
- if ($curr_columns === false) {
- return false;
- }
- $tocreate = array_diff(array_keys($columns), $curr_columns);
- if (count($tocreate) != 0) {
- $cannot_update = array_diff($tocreate, $dbtables_can_update[$id]);
- if (count($cannot_update) != 0) {
- $errors[] = "Key columns are absent in table `$id'. Unable to continue installation.";
- $page['nextstep'] = getlocal("Drop existing tables from database");
- $page['nextstepurl'] = MIBEW_WEB_ROOT . "/install/dbperform.php?act=dt";
- $page['nextnotice'] = getlocal("Impossible to update tables structure. Try to do it manually or recreate all tables (warning: all your data will be lost).");
- return false;
- }
- $need_to_create_columns = true;
- }
- }
-
- $need_to_create_indexes = false;
- foreach ($dbtables_indexes as $id => $indexes) {
- $curr_indexes = get_indexes($id, $link);
- if ($curr_indexes === false) {
- return false;
- }
- $tocreate = array_diff(array_keys($indexes), $curr_indexes);
- if (count($tocreate) != 0) {
- $need_to_create_indexes = true;
- }
- }
-
- if ($need_to_create_columns || $need_to_create_indexes) {
- $page['nextstep'] = getlocal("Update tables");
- $page['nextstepurl'] = MIBEW_WEB_ROOT . "/install/dbperform.php?act=addcolumns";
- $page['nextnotice'] = getlocal("Structure of your tables should be adjusted for new version of Messenger.");
- return false;
- }
-
- $page['done'][] = getlocal("Tables structure is up to date.");
- return true;
-}
-
-function check_sound()
-{
- global $page;
-
- $page['soundcheck'] = true;
- $page['done'][] = getlocal("Click to check the sound: {0} and {1}", array(
- "" . getlocal("New Visitor") . "",
- "" . getlocal("New Message") . ""
- ));
-}
-
-function check_admin($link)
-{
- global $mysqlprefix;
- $result = mysql_query("select * from ${mysqlprefix}chatoperator where vclogin = 'admin'", $link);
- if ($result) {
- $line = mysql_fetch_array($result, MYSQL_ASSOC);
- mysql_free_result($result);
- return $line['vcpassword'] != md5('');
- }
-
- return false;
-}
-
-function add_canned_messages($link){
- global $mysqlprefix;
- $localesresult = mysql_query("select locale from ${mysqlprefix}chatresponses", $link);
- $existlocales = array();
- for ($i = 0; $i < mysql_num_rows($localesresult); $i++) {
- $existlocales[] = mysql_result($localesresult, $i, 'locale');
- }
- $result = array();
- foreach (get_available_locales() as $locale) {
- if (in_array($locale, $existlocales)) {
- // Do not export canned messages for existing locales
- continue;
- }
-
- $file_path = MIBEW_FS_ROOT . '/locales/' . $locale . '/canned_messages.yml';
- if (!is_readable($file_path)) {
- // Export canned messages only for locales which have canned messages
- continue;
- }
-
- $canned_messages = get_yml_file_content($file_path);
- foreach ($canned_messages as $answer) {
- $result[] = array('locale' => $locale, 'vctitle' => cut_string($answer, 97, '...'), 'vcvalue' => $answer);
- }
- }
- if (count($result) > 0) {
- $updatequery = "insert into ${mysqlprefix}chatresponses (vctitle,vcvalue,locale,groupid) values ";
- for ($i = 0; $i < count($result); $i++) {
- if ($i > 0) {
- $updatequery .= ", ";
- }
- $updatequery .= "('" . mysql_real_escape_string($result[$i]['vctitle'], $link) . "', "
- . "'" . mysql_real_escape_string($result[$i]['vcvalue'], $link) . "', "
- . "'" . mysql_real_escape_string($result[$i]['locale'], $link) . "', NULL)";
- }
- mysql_query($updatequery, $link);
- }
-}
-
-function add_mail_templates($link){
- global $mysqlprefix;
- $localesresult = mysql_query("select distinct locale from ${mysqlprefix}mailtemplate", $link);
- $existlocales = array();
- for ($i = 0; $i < mysql_num_rows($localesresult); $i++) {
- $existlocales[] = mysql_result($localesresult, $i, 'locale');
- }
- $result = array();
- foreach (get_available_locales() as $locale) {
- if (in_array($locale, $existlocales)) {
- // Do not export mail templates for existing locales
- continue;
- }
-
- $file_path = MIBEW_FS_ROOT . '/locales/' . $locale . '/mail_templates.yml';
- if (!is_readable($file_path)) {
- // Export templates only for locales which have templates
- continue;
- }
-
- $templates = get_yml_file_content($file_path);
- if (isset($templates['user_history'])) {
- $result[] = array(
- 'locale' => $locale,
- 'name' => 'user_history',
- 'subject' => $templates['user_history']['subject'],
- 'body' => $templates['user_history']['body'],
- );
- }
-
- if (isset($templates['password_recovery'])) {
- $result[] = array(
- 'locale' => $locale,
- 'name' => 'password_recovery',
- 'subject' => $templates['password_recovery']['subject'],
- 'body' => $templates['password_recovery']['body'],
- );
- }
-
- if (isset($templates['leave_message'])) {
- $result[] = array(
- 'locale' => $locale,
- 'name' => 'leave_message',
- 'subject' => $templates['leave_message']['subject'],
- 'body' => $templates['leave_message']['body'],
- );
- }
- }
- if (count($result) > 0) {
- $updatequery = "insert into ${mysqlprefix}mailtemplate (name,locale,subject,body) values ";
- for ($i = 0; $i < count($result); $i++) {
- if ($i > 0) {
- $updatequery .= ", ";
- }
- $updatequery .= "('" . mysql_real_escape_string($result[$i]['name'], $link) . "', "
- . "'" . mysql_real_escape_string($result[$i]['locale'], $link) . "', "
- . "'" . mysql_real_escape_string($result[$i]['subject'], $link) . "', "
- . "'" . mysql_real_escape_string($result[$i]['body'], $link) . "')";
- }
- mysql_query($updatequery, $link);
- }
-}
-
-function add_locales($link)
-{
- global $mysqlprefix;
-
- $localesresult = mysql_query("select code from ${mysqlprefix}locale", $link);
- $existlocales = array();
- for ($i = 0; $i < mysql_num_rows($localesresult); $i++) {
- $existlocales[] = mysql_result($localesresult, $i, 'code');
- }
- $locales = discover_locales();
- foreach ($locales as $locale) {
- if (in_array($locale, $existlocales)) {
- // Do not add locales twice.
- continue;
- }
- $query = "insert into ${mysqlprefix}locale (code, enabled) values ('"
- . mysql_real_escape_string($locale, $link) . "', 1)";
- mysql_query($query, $link);
- }
-}
-
-function get_yml_file_content($file)
-{
- $yaml = new \Symfony\Component\Yaml\Parser();
-
- return $yaml->parse(file_get_contents($file));
-}
-
-function check_status()
-{
- global $page, $mysqlprefix;
-
- $page['done'][] = getlocal("PHP version {0}", array(phpversion()));
-
- if (!check_mibewroot()) {
- return;
- }
-
- if (!check_files()) {
- return;
- }
-
- $link = check_connection();
- if (!$link) {
- return;
- }
-
- if (!check_database($link)) {
- mysql_close($link);
- return;
- }
-
- if (!check_tables($link)) {
- mysql_close($link);
- return;
- }
-
- if (!check_columns($link)) {
- mysql_close($link);
- return;
- }
-
- add_locales($link);
- add_canned_messages($link);
- add_mail_templates($link);
-
- check_sound();
-
- $page['done'][] = getlocal("Application installed successfully.");
-
- if (!check_admin($link)) {
- $page['nextstep'] = getlocal("Proceed to the login page");
- $page['nextnotice'] = getlocal("You can logon as admin with empty password.
!!! For security reasons please change your password immediately and remove the {0} folder from your server.", array(MIBEW_WEB_ROOT . "/install/"));
- $page['nextstepurl'] = MIBEW_WEB_ROOT . "/operator/login?login=admin";
- }
-
- $page['show_small_login'] = true;
-
- // Update current dbversion
- $res = mysql_query("select COUNT(*) as count from ${mysqlprefix}chatconfig where vckey = 'dbversion'", $link);
- if(mysql_result($res, 0, 'count') == 0) {
- mysql_query("insert into ${mysqlprefix}chatconfig (vckey) values ('dbversion')", $link);
- }
-
- mysql_query("update ${mysqlprefix}chatconfig set vcvalue = '" . DB_VERSION . "' where vckey='dbversion'", $link);
- mysql_close($link);
-
-}
-
-check_status();
-
-$page['title'] = getlocal("Installation");
-$page['fixedwrap'] = true;
-$page['errors'] = $errors;
-
-$page_style = new \Mibew\Style\PageStyle('default');
-
-start_html_output();
-echo($page_style->render('install_index', $page));
-
-?>
\ No newline at end of file
diff --git a/src/mibew/install/migrate.php b/src/mibew/install/migrate.php
deleted file mode 100644
index f7161738..00000000
--- a/src/mibew/install/migrate.php
+++ /dev/null
@@ -1,68 +0,0 @@
-throwExeptions(true);
-
-$update_datetime = array(
- '{chatthread}' => array(
- 'dtmcreated',
- 'dtmchatstarted',
- 'dtmmodified',
- 'lastpinguser',
- 'lastpingagent'
- ),
- '{chatmessage}' => array(
- 'dtmcreated'
- ),
- '{chatoperator}' => array(
- 'dtmlastvisited',
- 'dtmrestore'
- ),
- '{chatban}' => array(
- 'dtmcreated',
- 'dtmtill'
- ),
- '{chatsitevisitor}' => array(
- 'firsttime',
- 'lasttime',
- 'invitationtime'
- ),
- '{visitedpage}' => array(
- 'visittime'
- ),
- '{visitedpagestatistics}' => array(
- 'visittime'
- )
-);
-
-foreach($update_datetime as $table => $columns) {
- echo("Table: {$table}
");
- foreach($columns as $column) {
- echo("-- Column: {$column}
");
- $db->query("ALTER TABLE {$table} CHANGE {$column} {$column}_tmp datetime");
- $db->query("ALTER TABLE {$table} ADD COLUMN {$column} int NOT NULL DEFAULT 0 AFTER {$column}_tmp");
- $db->query("UPDATE {$table} SET {$column} = UNIX_TIMESTAMP({$column}_tmp)");
- $db->query("ALTER TABLE {$table} DROP COLUMN {$column}_tmp");
- }
-}
-
-
-?>
\ No newline at end of file
diff --git a/src/mibew/libs/classes/Mibew/Authentication/DummyAuthenticationManager.php b/src/mibew/libs/classes/Mibew/Authentication/DummyAuthenticationManager.php
new file mode 100644
index 00000000..03e14058
--- /dev/null
+++ b/src/mibew/libs/classes/Mibew/Authentication/DummyAuthenticationManager.php
@@ -0,0 +1,73 @@
+ MIBEW_VERSION,
+ 'localeLinks' => get_locale_links(),
+ 'fixedwrap' => true,
+ 'title' => getlocal("Installation"),
+ );
+
+ $installer = $this->getInstaller();
+ $state = $installer->install($request->getBasePath());
+ $installation_error = $state == Installer::STATE_NEED_UPDATE_TABLES
+ || $state == Installer::STATE_ERROR;
+
+ if ($installation_error) {
+ $page['title'] = getlocal('Problem');
+ $page['no_right_menu'] = true;
+
+ if ($state == Installer::STATE_NEED_UPDATE_TABLES) {
+ // The installer should not update tables structure.
+ $page['errors'] = array(
+ getlocal('Mibew is already installed and must be updated. Use the updater.')
+ );
+ } else {
+ // Installer thinks that something went wrong. Believe it and
+ // use its errors.
+ $page['errors'] = $installer->getErrors();
+ }
+
+ return $this->render('install_err', $page);
+ }
+
+ $page['done'] = $installer->getLog();
+ $page['errors'] = $installer->getErrors();
+
+ if ($state == Installer::STATE_SUCCESS || $state == Installer::STATE_NEED_CHANGE_PASSWORD) {
+ // Everything is ok. The installation is completed.
+ $page['soundcheck'] = true;
+ $page['done'][] = getlocal("Click to check the sound: {0} and {1}", array(
+ "" . getlocal("New Visitor") . "",
+ "" . getlocal("New Message") . ""
+ ));
+ $page['done'][] = getlocal("Application installed successfully.");
+
+ if ($state == Installer::STATE_NEED_CHANGE_PASSWORD) {
+ $notice = getlocal('You can logon as admin with empty password.')
+ . '
'
+ . ''
+ . getlocal(
+ 'For security reasons please change your password immediately and remove {0} file from your server.',
+ array(MIBEW_WEB_ROOT . '/install.php')
+ )
+ . '';
+
+ $page['nextstep'] = getlocal("Proceed to the login page");
+ $page['nextnotice'] = $notice;
+ $page['nextstepurl'] = $this->generateUrl('login', array('login' => 'admin'));
+ }
+ } elseif ($state == Installer::STATE_NEED_CREATE_TABLES) {
+ // There is no tables in the database. We need to create them.
+ $page['nextstep'] = getlocal("Create required tables.");
+ $page['nextstepurl'] = $this->generateUrl('install_create_tables');
+ } else {
+ throw new \RuntimeException(
+ sprintf('Unknown installer state "%s".', $state)
+ );
+ }
+
+ return $this->render('install_index', $page);
+ }
+
+ /**
+ * An action that create necessary database tables.
+ *
+ * @param Request $request Incoming request
+ * @return string Rendered page content.
+ */
+ public function createTablesAction(Request $request)
+ {
+ $installer = $this->getInstaller();
+
+ if (!$installer->createTables()) {
+ // By some reasons tables cannot be created. Tell it to the user.
+ return $this->render(
+ 'install_err',
+ array(
+ 'version' => MIBEW_VERSION,
+ 'localeLinks' => get_locale_links(),
+ 'title' => getlocal('Problem'),
+ 'no_right_menu' => true,
+ 'fixedwrap' => true,
+ 'errors' => $installer->getErrors(),
+ )
+ );
+ }
+
+ // Tables are successfully created. Go back to the main installation
+ // page.
+ return $this->redirect($this->generateUrl('install'));
+ }
+
+ /**
+ * Initialize installer.
+ *
+ * @return \Mibew\Installer
+ */
+ protected function getInstaller()
+ {
+ if (is_null($this->installer)) {
+ $this->installer = new Installer(load_system_configs());
+ }
+
+ return $this->installer;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getStyle()
+ {
+ if (is_null($this->style)) {
+ $this->style = new PageStyle('default');
+ }
+
+ return $this->style;
+ }
+}
diff --git a/src/mibew/libs/classes/Mibew/Installer.php b/src/mibew/libs/classes/Mibew/Installer.php
new file mode 100644
index 00000000..5e869245
--- /dev/null
+++ b/src/mibew/libs/classes/Mibew/Installer.php
@@ -0,0 +1,771 @@
+configs = $system_configs;
+ $this->parser = new YamlParser();
+ }
+
+ /**
+ * Retuns list of all errors that took place during installation process.
+ *
+ * @return string[]
+ */
+ public function getErrors()
+ {
+ return $this->errors;
+ }
+
+ /**
+ * Returns list of all information messages.
+ *
+ * @return string[]
+ */
+ public function getLog()
+ {
+ return $this->log;
+ }
+
+ /**
+ * Install Mibew.
+ *
+ * @param string $real_base_path Real base path of the Mibew instance. For
+ * example if one tries to install Mibew to http://example.com/foo/mibew/
+ * the argument should be equal to "foo/mibew".
+ * @return string Installation state. One of Installer::STATE_* constant.
+ */
+ public function install($real_base_path)
+ {
+ if (!$this->checkPhpVersion()) {
+ return self::STATE_ERROR;
+ }
+
+ $this->log[] = getlocal(
+ 'PHP version {0}',
+ array(format_version_id($this->getPhpVersionId()))
+ );
+
+ if (!$this->checkMibewRoot($real_base_path)) {
+ return self::STATE_ERROR;
+ }
+
+ $this->log[] = getlocal(
+ 'Application path is {0}',
+ array($real_base_path)
+ );
+
+ if (!$this->checkConnection()) {
+ return self::STATE_ERROR;
+ }
+
+ if (!$this->checkMysqlVersion()) {
+ return self::STATE_ERROR;
+ }
+
+ $this->log[] = getlocal(
+ 'You are connected to MySQL server version {0}',
+ array($this->getMysqlVersion())
+ );
+
+ if (!$this->databaseExists()) {
+ return self::STATE_NEED_CREATE_TABLES;
+ }
+
+ if ($this->databaseNeedUpdate()) {
+ return self::STATE_NEED_UPDATE_TABLES;
+ }
+
+ $this->log[] = getlocal('Required tables are created.');
+ $this->log[] = getlocal('Tables structure is up to date.');
+
+ if (!$this->importLocales()) {
+ return self::STATE_ERROR;
+ }
+ $this->log[] = getlocal('Locales are imported.');
+
+ if (!$this->importLocalesContent()) {
+ return self::STATE_ERROR;
+ }
+ $this->log[] = getlocal('Locales content is imported.');
+
+ if ($this->needChangePassword()) {
+ return self::STATE_NEED_CHANGE_PASSWORD;
+ }
+
+ return self::STATE_SUCCESS;
+ }
+
+ /**
+ * Creates necessary tables.
+ *
+ * @return boolean Indicates if tables created or not. A list of all errors
+ * can be got using {@link \Mibew\Installer::getErrors()} method.
+ */
+ public function createTables()
+ {
+ if (!($db = $this->getDatabase())) {
+ return false;
+ }
+
+ try {
+ // Create tables according to database schema
+ $schema = $this->getDatabaseSchema();
+ foreach ($schema as $table => $table_structure) {
+ $table_items = array();
+
+ // Add fields
+ foreach ($table_structure['fields'] as $field => $definition) {
+ $table_items[] = sprintf('%s %s', $field, $definition);
+ }
+
+ // Add indexes
+ if (!empty($table_structure['indexes'])) {
+ foreach ($table_structure['indexes'] as $index => $fields) {
+ $table_items[] = sprintf(
+ 'INDEX %s (%s)',
+ $index,
+ implode(', ', $fields)
+ );
+ }
+ }
+
+ // Add unique keys
+ if (!empty($table_structure['unique_keys'])) {
+ foreach ($table_structure['unique_keys'] as $key => $fields) {
+ $table_items[] = sprintf(
+ 'UNIQUE KEY %s (%s)',
+ $key,
+ implode(', ', $fields)
+ );
+ }
+ }
+
+ $db->query(sprintf(
+ 'CREATE TABLE IF NOT EXISTS {%s} (%s) charset utf8 ENGINE=InnoDb',
+ $table,
+ implode(', ', $table_items)
+ ));
+ }
+ } catch(\Exception $e) {
+ $this->errors[] = getlocal(
+ 'Cannot create tables. Error: {0}',
+ array($e->getMessage())
+ );
+
+ return false;
+ }
+
+ if (!$this->prepopulateDatabase()) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Saves some necessary data in the database.
+ *
+ * This method is called just once after tables are created.
+ *
+ * @return boolean Indicates if the data are saved to the database or not.
+ */
+ protected function prepopulateDatabase()
+ {
+ if (!($db = $this->getDatabase())) {
+ return false;
+ }
+
+ // Create The First Administrator if needed
+ try {
+ list($count) = $db->query(
+ 'SELECT COUNT(*) FROM {chatoperator} WHERE vclogin = :login',
+ array(':login' => 'admin'),
+ array(
+ 'return_rows' => Database::RETURN_ONE_ROW,
+ 'fetch_type' => Database::FETCH_NUM
+ )
+ );
+ if ($count == 0) {
+ $db->query(
+ ('INSERT INTO {chatoperator} ( '
+ . 'vclogin, vcpassword, vclocalename, vccommonname, '
+ . 'vcavatar, vcemail, iperm '
+ . ') values ( '
+ . ':login, :pass, :local_name, :common_name, '
+ . ':avatar, :email, :permissions)'),
+ array(
+ ':login' => 'admin',
+ ':pass' => md5(''),
+ ':local_name' => 'Administrator',
+ ':common_name' => 'Administrator',
+ ':avatar' => '',
+ ':email' => '',
+ ':permissions' => 65535,
+ )
+ );
+ }
+ } catch(\Exception $e) {
+ $this->errors[] = getlocal(
+ 'Cannot create the first administrator. Error {0}',
+ array($e->getMessage())
+ );
+
+ return false;
+ }
+
+ // Initialize chat revision counter if it is needed
+ try {
+ list($count) = $db->query(
+ 'SELECT COUNT(*) FROM {chatrevision}',
+ null,
+ array(
+ 'return_rows' => Database::RETURN_ONE_ROW,
+ 'fetch_type' => Database::FETCH_NUM
+ )
+ );
+ if ($count == 0) {
+ $db->query(
+ 'INSERT INTO {chatrevision} VALUES (:init_revision)',
+ array(':init_revision' => 1)
+ );
+ }
+ } catch(\Exception $e) {
+ $this->errors[] = getlocal(
+ 'Cannot initialize chat revision sequence. Error {0}',
+ array($e->getMessage())
+ );
+
+ return false;
+ }
+
+ // Set correct database structure version if needed
+ try {
+ list($count) = $db->query(
+ 'SELECT COUNT(*) FROM {chatconfig} WHERE vckey = :key',
+ array(':key' => 'dbversion'),
+ array(
+ 'return_rows' => Database::RETURN_ONE_ROW,
+ 'fetch_type' => Database::FETCH_NUM
+ )
+ );
+ if ($count == 0) {
+ $db->query(
+ 'INSERT INTO {chatconfig} (vckey, vcvalue) VALUES (:key, :value)',
+ array(
+ ':key' => 'dbversion',
+ ':value' => DB_VERSION,
+ )
+ );
+ }
+ } catch(\Exception $e) {
+ $this->errors[] = getlocal(
+ 'Cannot store database structure version. Error {0}',
+ array($e->getMessage())
+ );
+
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks if $mibewroot param in system configs is correct or not.
+ *
+ * @param string $real_base_path Real base path of the Mibew instance.
+ * @return boolean True if the $mibewroot param in config is correct and
+ * false otherwise.
+ */
+ protected function checkMibewRoot($real_base_path)
+ {
+ if ($real_base_path != MIBEW_WEB_ROOT) {
+ $this->errors[] = getlocal(
+ "Please, check file {0}
Wrong value of \$mibewroot variable, should be \"{1}\"",
+ array(
+ $real_base_path . "/libs/config.php",
+ $real_base_path
+ )
+ );
+
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks database connection.
+ *
+ * @return boolean True if connection is established and false otherwise.
+ */
+ protected function checkConnection()
+ {
+ if (!$this->getDatabase()) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks if PHP version is high enough to run Mibew.
+ *
+ * @return boolean True if PHP version is suitable and false otherwise.
+ */
+ protected function checkPhpVersion()
+ {
+ $current_version = $this->getPhpVersionId();
+
+ if ($current_version < self::MIN_PHP_VERSION) {
+ $this->errors[] = getlocal(
+ "PHP version is {0}, but Mibew works with {1} and later versions.",
+ array(
+ format_version_id($current_version),
+ format_version_id(self::MIN_PHP_VERSION)
+ )
+ );
+
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks if MySQL version is high enough or not to run Mibew.
+ *
+ * @return boolean True if MySQL version is suitable and false otherwise.
+ * @todo Add real version check.
+ */
+ protected function checkMysqlVersion()
+ {
+ // At the moment minimal MySQL version is unknown. One should find
+ // it out and replace the following with a real check.
+ return ($this->getMysqlVersion() !== false);
+ }
+
+ /**
+ * Returns current PHP version ID.
+ *
+ * For example, for PHP 5.3.3 the number 50303 will be returned.
+ *
+ * @return integer Verison ID.
+ */
+ protected function getPhpVersionId()
+ {
+ // PHP_VERSION_ID is available as of PHP 5.2.7 so we need to use
+ // workaround for lower versions.
+ return defined('PHP_VERSION_ID') ? PHP_VERSION_ID : 0;
+ }
+
+ /**
+ * Returns current MySQL server version.
+ *
+ * @return string|boolean Current MySQL version or boolean false it it
+ * cannot be determined.
+ */
+ protected function getMysqlVersion()
+ {
+ if (!($db = $this->getDatabase())) {
+ return false;
+ }
+
+ try {
+ $result = $db->query(
+ "SELECT VERSION() as c",
+ null,
+ array('return_rows' => Database::RETURN_ONE_ROW)
+ );
+ } catch (\Exception $e) {
+ return false;
+ }
+
+ return $result['c'];
+ }
+
+ /**
+ * Gets version of existing database structure.
+ *
+ * If Mibew is not installed yet boolean false will be returned.
+ *
+ * @return int|boolean Database structure version or boolean false if the
+ * version cannot be determined.
+ */
+ protected function getDatabaseVersion()
+ {
+ if (!($db = $this->getDatabase())) {
+ return false;
+ }
+
+ try {
+ $result = $db->query(
+ "SELECT vcvalue AS version FROM {chatconfig} WHERE vckey = :key LIMIT 1",
+ array(':key' => 'dbversion'),
+ array('return_rows' => Database::RETURN_ONE_ROW)
+ );
+ } catch (\Exception $e) {
+ return false;
+ }
+
+ if (!$result) {
+ // It seems that database structure version isn't stored in the
+ // database.
+ return 0;
+ }
+
+ return intval($result['version']);
+ }
+
+ /**
+ * Checks if the database structure must be updated.
+ *
+ * @return boolean
+ */
+ protected function databaseNeedUpdate()
+ {
+ return ($this->getDatabaseVersion() < DB_VERSION);
+ }
+
+ /**
+ * Checks if database structure is already created.
+ *
+ * @return boolean
+ */
+ protected function databaseExists()
+ {
+ return ($this->getDatabaseVersion() !== false);
+ }
+
+ /**
+ * Check if the admin must change his password to a new one.
+ *
+ * @return boolean True if the password must be changed and false otherwise.
+ */
+ protected function needChangePassword()
+ {
+ if (!($db = $this->getDatabase())) {
+ return false;
+ }
+
+ try {
+ $admin = $db->query(
+ 'SELECT * FROM {chatoperator} WHERE vclogin = :login',
+ array(':login' => 'admin'),
+ array('return_rows' => Database::RETURN_ONE_ROW)
+ );
+ } catch (\Exception $e) {
+ $this->errors[] = getlocal(
+ 'Cannot load the main administrator\'s data. Error: {0}',
+ array($e->getMessage())
+ );
+
+ return false;
+ }
+
+ if (!$admin) {
+ $this->errors[] = getlocal('The main administrator has disappeared '
+ . 'from the database. Do not know how to continue');
+
+ return false;
+ }
+
+ return ($admin['vcpassword'] == md5(''));
+ }
+
+ /**
+ * Import all available locales to the database and enable each of them.
+ *
+ * @return boolean Indicates if the locales were imported correctly. True if
+ * everything is OK and false otherwise.
+ */
+ protected function importLocales()
+ {
+ if (!($db = $this->getDatabase())) {
+ return false;
+ }
+
+ try {
+ $rows = $db->query(
+ 'SELECT code FROM {locale}',
+ null,
+ array('return_rows' => Database::RETURN_ALL_ROWS)
+ );
+ $exist_locales = array();
+ foreach ($rows as $row) {
+ $exist_locales[] = $row['code'];
+ }
+
+ $fs_locales = discover_locales();
+ foreach ($fs_locales as $locale) {
+ if (in_array($locale, $exist_locales)) {
+ // Do not create locales twice.
+ continue;
+ }
+
+ $db->query(
+ 'INSERT INTO {locale} (code, enabled) values (:code, :enabled)',
+ array(
+ ':code' => $locale,
+ // Mark the locale as disabled to indicate that it's
+ // content is not imported yet.
+ ':enabled' => 0,
+ )
+ );
+ }
+ } catch (\Exception $e) {
+ $this->errors[] = getlocal(
+ 'Cannot import locales. Error: {0}',
+ array($e->getMessage())
+ );
+
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Import locales content, namely translations, canned messages and mail
+ * templates.
+ *
+ * When the content will be imported the locale will be marked as enabled.
+ * @return boolean True if all content was imported successfully and false
+ * otherwise.
+ */
+ protected function importLocalesContent()
+ {
+ if (!($db = $this->getDatabase())) {
+ return false;
+ }
+
+ try {
+ $locales = $db->query(
+ 'SELECT * FROM {locale} WHERE enabled = :enabled',
+ array(':enabled' => 0),
+ array('return_rows' => Database::RETURN_ALL_ROWS)
+ );
+
+ foreach ($locales as $locale_info) {
+ $locale = $locale_info['code'];
+
+ // Import localized messages
+ import_messages(
+ $locale,
+ MIBEW_FS_ROOT . '/locales/' . $locale . '/translation.po',
+ true
+ );
+
+ // Import canned messages
+ $canned_messages_file = MIBEW_FS_ROOT . '/locales/' . $locale
+ . '/canned_messages.yml';
+ if (is_readable($canned_messages_file)) {
+ import_canned_messages($locale, $canned_messages_file);
+ }
+
+ // Import mail templates
+ $mail_templates_file = MIBEW_FS_ROOT . '/locales/' . $locale
+ . '/mail_templates.yml';
+ if (is_readable($mail_templates_file)) {
+ import_mail_templates($locale, $mail_templates_file);
+ }
+
+ // Mark the locale as "enabled" to indicate that all its content
+ // is imported.
+ $db->query(
+ 'UPDATE {locale} SET enabled = :enabled WHERE code = :locale',
+ array(
+ ':locale' => $locale,
+ ':enabled' => 1,
+ )
+ );
+ }
+ } catch (\Exception $e) {
+ $this->errors[] = getlocal(
+ 'Cannot import locales content. Error: {0}',
+ array($e->getMessage())
+ );
+
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns initialized database object.
+ *
+ * @return \Mibew\Database|boolean A database class instance or boolean
+ * false if something went wrong.
+ */
+ protected function getDatabase()
+ {
+ if (!Database::isInitialized()) {
+ try {
+ Database::initialize(
+ $this->configs['database']['host'],
+ $this->configs['database']['login'],
+ $this->configs['database']['pass'],
+ $this->configs['database']['use_persistent_connection'],
+ $this->configs['database']['db'],
+ $this->configs['database']['tables_prefix']
+ );
+ } catch(\PDOException $e) {
+ $this->errors[] = getlocal(
+ "Could not connect. Please check server settings in config.php. Error: {0}",
+ array($e->getMessage())
+ );
+
+ return false;
+ }
+ }
+
+ $db = Database::getInstance();
+ $db->throwExeptions(true);
+
+ return $db;
+ }
+
+ /**
+ * Loads database schema.
+ *
+ * @return array Associative array of database schema. Each key of the array
+ * is a table name and each value is its description. Table array itself
+ * is an associative array with the following keys:
+ * - fields: An associative array, which keys are MySQL columns names
+ * and values are columns definitions.
+ * - unique_keys: An associative array. Each its value is a name of a
+ * table's unique key. Each value is an array with names of the
+ * columns the key is based on.
+ * - indexes: An associative array. Each its value is a name of a
+ * table's index. Each value is an array with names of the
+ * columns the index is based on.
+ */
+ protected function getDatabaseSchema()
+ {
+ return $this->parser->parse(file_get_contents(MIBEW_FS_ROOT . '/libs/database_schema.yml'));
+ }
+
+ /**
+ * Loads available canned messages for specified locale.
+ *
+ * @param string $locale Locale code.
+ * @return string[]|boolean List of canned messages boolean false if
+ * something went wrong.
+ */
+ protected function getCannedMessages($locale)
+ {
+ $file_path = MIBEW_FS_ROOT . '/locales/' . $locale . '/canned_messages.yml';
+ if (!is_readable($file_path)) {
+ return false;
+ }
+ $messages = $this->parser->parse(file_get_contents($file_path));
+
+ return $messages ? $messages : false;
+ }
+
+ /**
+ * Loads available mail templates for the specified locale.
+ *
+ * @param string $locale Locale code.
+ * @return array|boolean List of mail template arrays or boolean false if
+ * something went wrong.
+ */
+ protected function getMailTemplates($locale)
+ {
+ $file_path = MIBEW_FS_ROOT . '/locales/' . $locale . '/mail_templates.yml';
+ if (!is_readable($file_path)) {
+ return false;
+ }
+ $templates = $this->parser->parse(file_get_contents($file_path));
+
+ return $templates ? $templates : false;
+ }
+}
diff --git a/src/mibew/libs/classes/Mibew/Routing/RouteCollectionLoader.php b/src/mibew/libs/classes/Mibew/Routing/RouteCollectionLoader.php
index 4b0774a9..56fa1d18 100644
--- a/src/mibew/libs/classes/Mibew/Routing/RouteCollectionLoader.php
+++ b/src/mibew/libs/classes/Mibew/Routing/RouteCollectionLoader.php
@@ -38,10 +38,15 @@ class RouteCollectionLoader
*/
const ROUTES_PLUGINS = 2;
+ /**
+ * Indicates that only routes related with installation should be loaded.
+ */
+ const ROUTES_INSTALLATION = 4;
+
/**
* Indicates that all available routes should be loaded.
*/
- const ROUTES_ALL = 3;
+ const ROUTES_ALL = 7;
/**
* @var YamlFileLoader|null
@@ -72,6 +77,11 @@ class RouteCollectionLoader
$collection->addCollection($this->loadCoreRoutes());
}
+ // Load installation routes if needed
+ if ($type & self::ROUTES_INSTALLATION) {
+ $collection->addCollection($this->loadInstallationRoutes());
+ }
+
// Load plugins routes if needed
if ($type & self::ROUTES_PLUGINS) {
$collection->addCollection($this->loadPluginRoutes());
@@ -95,6 +105,17 @@ class RouteCollectionLoader
return $this->loader->load('libs/routing.yml');
}
+ /**
+ * Loads routes related with installation process.
+ *
+ * @return RouteCollection
+ * @throws \RuntimeException If core installation routing file is not found.
+ */
+ protected function loadInstallationRoutes()
+ {
+ return $this->loader->load('libs/routing_install.yml');
+ }
+
/**
* Loads plugins' routes.
*
diff --git a/src/mibew/libs/common/constants.php b/src/mibew/libs/common/constants.php
index 7bb5aa5c..4d180167 100644
--- a/src/mibew/libs/common/constants.php
+++ b/src/mibew/libs/common/constants.php
@@ -23,7 +23,7 @@ define('MIBEW_VERSION', '2.0');
/**
* Current version of database structure
*/
-define('DB_VERSION', '2.0');
+define('DB_VERSION', 20000);
/**
* Current version of implemented features
diff --git a/src/mibew/libs/common/string.php b/src/mibew/libs/common/string.php
index e1fb6a9b..32e5b5be 100644
--- a/src/mibew/libs/common/string.php
+++ b/src/mibew/libs/common/string.php
@@ -167,3 +167,28 @@ function safe_htmlspecialchars($string)
$string = preg_replace('/[\x00-\x08\x0b\x0c\x0e-\x1f]/', '', $string);
return htmlspecialchars($string, ENT_QUOTES);
}
+
+/**
+ * Converts version ID to human readable representation.
+ *
+ * Example of usage:
+ *
+ * $version = 50303;
+ * echo(format_version_id($version)); // Outputs "5.3.3"
+ *
+ *
+ * @param int $version_id Version ID
+ * @return string Human readable version.
+ */
+function format_version_id($version_id)
+{
+ $parts = array();
+ $tmp = (int)$version_id;
+
+ for ($i = 0; $i < 3; $i++) {
+ $parts[] = $tmp % 100;
+ $tmp = floor($tmp / 100);
+ }
+
+ return implode('.', array_reverse($parts));
+}
diff --git a/src/mibew/libs/database_schema.yml b/src/mibew/libs/database_schema.yml
new file mode 100644
index 00000000..368c32df
--- /dev/null
+++ b/src/mibew/libs/database_schema.yml
@@ -0,0 +1,284 @@
+# This file contains current database schema that is used for installation.
+# Do not change anything in this file unless you know what you are doing!
+
+# Contains information about chat groups
+chatgroup:
+ fields:
+ groupid: "int NOT NULL auto_increment PRIMARY KEY"
+ parent: "int DEFAULT NULL"
+ vcemail: "varchar(64)"
+ vclocalname: "varchar(64) NOT NULL"
+ vccommonname: "varchar(64) NOT NULL"
+ vclocaldescription: "varchar(1024) NOT NULL"
+ vccommondescription: "varchar(1024) NOT NULL"
+ iweight: "int NOT NULL DEFAULT 0"
+ vctitle: "varchar(255) DEFAULT ''"
+ vcchattitle: "varchar(255) DEFAULT ''"
+ vclogo: "varchar(255) DEFAULT ''"
+ vchosturl: "varchar(255) DEFAULT ''"
+ indexes:
+ parent: [parent]
+
+# Contains info about chat threads
+chatthread:
+ fields:
+ # ID of the thread.
+ threadid: "int NOT NULL auto_increment PRIMARY KEY"
+ # Name of the user in chat.
+ userName: "varchar(64) NOT NULL"
+ # ID of the user. This field is foreign key for {chatsitevisitor}.userid
+ userid: "varchar(255)"
+ # Name of the operator who took place in the chat.
+ agentName: "varchar(64)"
+ # ID of the operator who took place in the chat.
+ agentId: "int NOT NULL DEFAULT 0"
+ # Unix timestamp of the moment when the thread was created.
+ dtmcreated: "int NOT NULL DEFAULT 0"
+ # Unix timestamp of the moment when chat actually started.
+ dtmchatstarted: "int NOT NULL DEFAULT 0"
+ # Unix timestamp of the last thread modification.
+ dtmmodified: "int NOT NULL DEFAULT 0"
+ # Unix timestamp of the moment when the thread was closed.
+ dtmclosed: "int NOT NULL DEFAULT 0"
+ # ID of the last thread revision.
+ lrevision: "int NOT NULL DEFAULT 0"
+ # State of the thread. It is one of Thread::STATE_* constants.
+ istate: "int NOT NULL DEFAULT 0"
+ # State of invitation related with the thread. It is one of
+ # Thread::INVITATION_* constants.
+ invitationstate: "int NOT NULL DEFAULT 0"
+ # Last token of the thread.
+ ltoken: "int NOT NULL"
+ # IP address of the user.
+ remote: "varchar(255)"
+ # Page from which chat thread was started.
+ referer: "text"
+ # ID of the operator who will next in the chat.
+ nextagent: "int NOT NULL DEFAULT 0"
+ # Code of chat locale.
+ locale: "varchar(8)"
+ # Unix timestamp of the last request from user's window to server.
+ lastpinguser: "int NOT NULL DEFAULT 0"
+ # Unix timestamp of the last request from operator's window to server.
+ lastpingagent: "int NOT NULL DEFAULT 0"
+ # Indicates if user typing or not. It can take two values 0 and 1.
+ userTyping: "int DEFAULT 0"
+ # Indicates if operator typing or not. It can take two values 0 and 1.
+ agentTyping: "int DEFAULT 0"
+ # ID of shown message in the chat.
+ shownmessageid: "int NOT NULL DEFAULT 0"
+ # User agent description that took from 'User-Agent' HTTP header.
+ userAgent: "varchar(255)"
+ # Total count of user's messages related with the thread.
+ messageCount: "varchar(16)"
+ # ID of the group at Mibew side related with the thread.
+ groupid: "int references {chatgroup}(groupid)"
+
+# Contains "by thread" statistics
+chatthreadstatistics:
+ fields:
+ statid: "int NOT NULL auto_increment PRIMARY KEY"
+ date: "int NOT NULL DEFAULT 0"
+ threads: "int NOT NULL DEFAULT 0"
+ missedthreads: "int NOT NULL DEFAULT 0"
+ sentinvitations: "int NOT NULL DEFAULT 0"
+ acceptedinvitations: "int NOT NULL DEFAULT 0"
+ rejectedinvitations: "int NOT NULL DEFAULT 0"
+ ignoredinvitations: "int NOT NULL DEFAULT 0"
+ operatormessages: "int NOT NULL DEFAULT 0"
+ usermessages: "int NOT NULL DEFAULT 0"
+ averagewaitingtime: "FLOAT(10, 1) NOT NULL DEFAULT 0"
+ averagechattime: "FLOAT(10, 1) NOT NULL DEFAULT 0"
+
+requestbuffer:
+ fields:
+ requestid: "int NOT NULL auto_increment PRIMARY KEY"
+ # Use MD5 hashes as keys
+ requestkey: "char(32) NOT NULL"
+ request: "text NOT NULL"
+ indexes:
+ requestkey: [requestkey]
+
+requestcallback:
+ fields:
+ callbackid: "int NOT NULL auto_increment PRIMARY KEY"
+ token: "varchar(64) NOT NULL DEFAULT ''"
+ function: "varchar(64) NOT NULL"
+ arguments: "varchar(1024)"
+ indexes:
+ token: [token]
+
+# Contains updated translations
+translation:
+ fields:
+ stringid: "int NOT NULL auto_increment PRIMARY KEY"
+ locale: "varchar(5) NOT NULL"
+ context: "varchar(256) NOT NULL DEFAULT ''"
+ source: "text COLLATE utf8_bin"
+ translation: "text"
+
+# Contains locales info
+locale:
+ fields:
+ # Artificial primary key
+ localeid: "int NOT NULL auto_increment PRIMARY KEY"
+ # Locale code
+ code: "varchar(5) NOT NULL"
+ # Indicates if a locale is enabled or not.
+ enabled: "tinyint NOT NULL DEFAULT 0"
+
+# Contains localized mail templates
+mailtemplate:
+ fields:
+ # Artificial primary key
+ templateid: "int NOT NULL auto_increment PRIMARY KEY"
+ # Locale code a template belongs to
+ locale: "varchar(5) NOT NULL"
+ # Machine name of a template
+ name: "varchar(256) NOT NULL"
+ # Mail subject
+ subject: "varchar(1024) NOT NULL"
+ # Mail body
+ body: "text"
+
+# Store chat thread messages
+chatmessage:
+ fields:
+ # Message ID.
+ messageid: "int NOT NULL auto_increment PRIMARY KEY"
+ # ID of the thread related with the message.
+ threadid: "int NOT NULL references {chatthread}(threadid)"
+ # Message kind. It is one of Thread::KIND_* constants.
+ ikind: "int NOT NULL"
+ # ID of operator who sent the message. This value will be ignored for
+ # system messages and messages which sent by users.
+ agentId: "int NOT NULL DEFAULT 0"
+ # Message text body.
+ tmessage: "text NOT NULL"
+ # Name of the plugin which sent the message. If message was not sent by
+ # a plugin this field equals to an empty string.
+ plugin: "varchar(256) NOT NULL DEFAULT ''"
+ # Arbitrary serialized data related with message.
+ data: "text"
+ # Unix timestamp when message was created.
+ dtmcreated: "int NOT NULL DEFAULT 0"
+ # Name of the message sender.
+ tname: "varchar(64)"
+ indexes:
+ idx_agentid: [agentid]
+
+# Contains info about operators
+chatoperator:
+ fields:
+ operatorid: "int NOT NULL auto_increment PRIMARY KEY"
+ vclogin: "varchar(64) NOT NULL"
+ vcpassword: "varchar(64) NOT NULL"
+ vclocalename: "varchar(64) NOT NULL"
+ vccommonname: "varchar(64) NOT NULL"
+ vcemail: "varchar(64)"
+ dtmlastvisited: "int NOT NULL DEFAULT 0"
+ # Current status of an operator: 0 - online, 1 - away
+ istatus: "int DEFAULT 0"
+ idisabled: "int DEFAULT 0"
+ vcavatar: "varchar(255)"
+ vcjabbername: "varchar(255)"
+ # Operators privileges bitmask.
+ iperm: "int DEFAULT 0"
+ dtmrestore: "int NOT NULL DEFAULT 0"
+ vcrestoretoken: "varchar(64)"
+ # Use to start chat with specified operator.
+ code: "varchar(64) DEFAULT ''"
+
+# Contains "by operator" statistics
+chatoperatorstatistics:
+ fields:
+ statid: "int NOT NULL auto_increment PRIMARY KEY"
+ date: "int NOT NULL DEFAULT 0"
+ operatorid: "int NOT NULL"
+ threads: "int NOT NULL DEFAULT 0"
+ messages: "int NOT NULL DEFAULT 0"
+ averagelength: "FLOAT(10, 1) NOT NULL DEFAULT 0"
+ sentinvitations: "int NOT NULL DEFAULT 0"
+ acceptedinvitations: "int NOT NULL DEFAULT 0"
+ rejectedinvitations: "int NOT NULL DEFAULT 0"
+ ignoredinvitations: "int NOT NULL DEFAULT 0"
+ indexes:
+ operatorid: [operatorid]
+
+chatrevision:
+ fields:
+ id: "INT NOT NULL"
+
+# Contains relations between operators and groups
+chatgroupoperator:
+ fields:
+ groupid: "int NOT NULL references {chatgroup}(groupid)"
+ operatorid: "int NOT NULL references {chatoperator}(operatorid)"
+ indexes:
+ groupid: [groupid]
+ operatorid: [operatorid]
+
+# Contains banned visitors
+chatban:
+ fields:
+ banid: "INT NOT NULL auto_increment PRIMARY KEY"
+ dtmcreated: "int NOT NULL DEFAULT 0"
+ dtmtill: "int NOT NULL DEFAULT 0"
+ address: "varchar(255)"
+ comment: "varchar(255)"
+ blockedCount: "int DEFAULT 0"
+
+# Contains dynamic configs
+chatconfig:
+ fields:
+ id: "INT NOT NULL auto_increment PRIMARY KEY"
+ vckey: "varchar(255)"
+ vcvalue: "varchar(255)"
+
+# Contains canned messages
+chatresponses:
+ fields:
+ id: "INT NOT NULL auto_increment PRIMARY KEY"
+ locale: "varchar(8)"
+ groupid: "int references {chatgroup}(groupid)"
+ vctitle: "varchar(100) NOT NULL DEFAULT ''"
+ vcvalue: "varchar(1024) NOT NULL"
+
+chatsitevisitor:
+ fields:
+ visitorid: "INT NOT NULL auto_increment PRIMARY KEY"
+ userid: "varchar(255) NOT NULL"
+ username: "varchar(64)"
+ firsttime: "int NOT NULL DEFAULT 0"
+ lasttime: "int NOT NULL DEFAULT 0"
+ entry: "text NOT NULL"
+ details: "text NOT NULL"
+ invitations: "INT NOT NULL DEFAULT 0"
+ chats: "INT NOT NULL DEFAULT 0"
+ threadid: "INT references {chatthread}(threadid) on delete set null"
+ indexes:
+ threadid: [threadid]
+
+visitedpage:
+ fields:
+ pageid: "INT NOT NULL auto_increment PRIMARY KEY"
+ address: "varchar(1024)"
+ visittime: "int NOT NULL DEFAULT 0"
+ visitorid: "INT"
+ # Indicates if path included in 'by page' statistics
+ calculated: "tinyint NOT NULL DEFAULT 0"
+ indexes:
+ visitorid: [visitorid]
+
+# Contains "by page" statistics
+visitedpagestatistics:
+ fields:
+ pageid: "INT NOT NULL auto_increment PRIMARY KEY"
+ date: "int NOT NULL DEFAULT 0"
+ address: "varchar(1024)"
+ visits: "int NOT NULL DEFAULT 0"
+ chats: "int NOT NULL DEFAULT 0"
+ sentinvitations: "int NOT NULL DEFAULT 0"
+ acceptedinvitations: "int NOT NULL DEFAULT 0"
+ rejectedinvitations: "int NOT NULL DEFAULT 0"
+ ignoredinvitations: "int NOT NULL DEFAULT 0"
diff --git a/src/mibew/libs/routing_install.yml b/src/mibew/libs/routing_install.yml
new file mode 100644
index 00000000..90ea3289
--- /dev/null
+++ b/src/mibew/libs/routing_install.yml
@@ -0,0 +1,9 @@
+install:
+ path: /install
+ defaults:
+ _controller: Mibew\Controller\InstallController::indexAction
+
+install_create_tables:
+ path: /install/create-tables
+ defaults:
+ _controller: Mibew\Controller\InstallController::createTablesAction