Эх сурвалжийг харах

Merge branch 'master' into master

FusionPBX 6 жил өмнө
parent
commit
3a68f2e890
100 өөрчлөгдсөн 7552 нэмэгдсэн , 3864 устгасан
  1. 3 0
      .htaccess
  2. 7 6
      core/authentication/resources/classes/plugins/database.php
  3. 2 2
      core/authentication/resources/classes/plugins/ldap.php
  4. 1 1
      core/databases/database_delete.php
  5. 11 11
      core/databases/database_edit.php
  6. 11 11
      core/databases/databases.php
  7. 13 61
      core/default_settings/app_config.php
  8. 100 0
      core/default_settings/app_languages.php
  9. 25 6
      core/default_settings/default_setting_edit.php
  10. 2 2
      core/default_settings/default_setting_toggle.php
  11. 10 5
      core/default_settings/default_settings.php
  12. 1 1
      core/default_settings/default_settings_reload.php
  13. 1 1
      core/domain_settings/app_config.php
  14. 124 118
      core/domain_settings/domain_delete.php
  15. 54 2
      core/domain_settings/domain_edit.php
  16. 1 1
      core/domain_settings/domain_setting_delete.php
  17. 23 3
      core/domain_settings/domain_setting_edit.php
  18. 101 2
      core/domain_settings/domain_settings.php
  19. 3 2
      core/domain_settings/domains.php
  20. 3 76
      core/groups/app_config.php
  21. 4 4
      core/groups/app_defaults.php
  22. 8 8
      core/groups/group_permissions.php
  23. 2 2
      core/groups/groupadd.php
  24. 4 4
      core/groups/groupdelete.php
  25. 17 17
      core/groups/groupedit.php
  26. 4 4
      core/groups/groupmemberadd.php
  27. 3 3
      core/groups/groupmemberdelete.php
  28. 12 12
      core/groups/groupmembers.php
  29. 2 2
      core/groups/groups.php
  30. 1 1
      core/groups/permissions_copy.php
  31. 1 1
      core/groups/permissions_default.php
  32. 1 1
      core/install/install.php
  33. 4 4
      core/install/resources/classes/install_fusionpbx.php
  34. 6 4
      core/menu/app_menu.php
  35. 6 6
      core/menu/menu.php
  36. 1 1
      core/menu/menu_delete.php
  37. 6 6
      core/menu/menu_edit.php
  38. 1 1
      core/menu/menu_item_delete.php
  39. 17 17
      core/menu/menu_item_edit.php
  40. 1 1
      core/menu/menu_item_move_down.php
  41. 1 1
      core/menu/menu_item_move_up.php
  42. 1 1
      core/menu/menu_restore_default.php
  43. 6 6
      core/upgrade/index.php
  44. 0 20
      core/user_settings/app_languages.php
  45. 4 3
      core/user_settings/app_menu.php
  46. 4 2
      core/user_settings/user_dashboard.php
  47. 93 1
      core/users/app_config.php
  48. 76 6
      core/users/app_defaults.php
  49. 222 2
      core/users/app_languages.php
  50. 3 2
      core/users/app_menu.php
  51. 3 3
      core/users/user_delete.php
  52. 486 372
      core/users/user_edit.php
  53. 501 0
      core/users/user_imports.php
  54. 1 1
      core/users/user_setting_delete.php
  55. 19 19
      core/users/user_setting_edit.php
  56. 10 10
      core/users/user_settings.php
  57. 61 63
      core/users/users.php
  58. 568 80
      resources/app_languages.php
  59. 0 124
      resources/captcha/img.php
  60. 2 2
      resources/check_auth.php
  61. 7 6
      resources/classes/cache.php
  62. 161 0
      resources/classes/captcha.php
  63. 242 468
      resources/classes/database.php
  64. 229 27
      resources/classes/destinations.php
  65. 0 7
      resources/classes/menu.php
  66. 9 5
      resources/classes/message.php
  67. 0 924
      resources/classes/orm.php
  68. 35 15
      resources/classes/schema.php
  69. 1 1
      resources/fpdf/fpdf.php
  70. 265 110
      resources/functions.php
  71. 1 32
      resources/licenses.php
  72. 60 0
      resources/login.php
  73. 4 4
      resources/pdo.php
  74. 81 0
      resources/qr_code/QR8bitByte.php
  75. 107 0
      resources/qr_code/QRBitBuffer.php
  76. 41 0
      resources/qr_code/QRByte.php
  77. 656 0
      resources/qr_code/QRCode.php
  78. 14 0
      resources/qr_code/QRCodeException.php
  79. 187 0
      resources/qr_code/QRCodeImage.php
  80. 20 0
      resources/qr_code/QRErrorCorrectLevel.php
  81. 145 0
      resources/qr_code/QRMath.php
  82. 20 0
      resources/qr_code/QRMode.php
  83. 145 0
      resources/qr_code/QRPolynominal.php
  84. 503 0
      resources/qr_code/QRRSBlock.php
  85. 464 0
      resources/qr_code/QRUtil.php
  86. 30 0
      resources/qr_code/README.md
  87. 0 0
      resources/qr_code/rsblock.dat
  88. 0 268
      resources/recaptchalib.php
  89. 110 0
      resources/templates/engine/smarty/Autoloader.php
  90. 15 1
      resources/templates/engine/smarty/LICENSE
  91. 11 10
      resources/templates/engine/smarty/README
  92. 359 426
      resources/templates/engine/smarty/Smarty.class.php
  93. 477 0
      resources/templates/engine/smarty/SmartyBC.class.php
  94. 16 0
      resources/templates/engine/smarty/bootstrap.php
  95. 154 127
      resources/templates/engine/smarty/debug.tpl
  96. 39 28
      resources/templates/engine/smarty/plugins/block.textformat.php
  97. 31 45
      resources/templates/engine/smarty/plugins/function.counter.php
  98. 43 56
      resources/templates/engine/smarty/plugins/function.cycle.php
  99. 65 80
      resources/templates/engine/smarty/plugins/function.fetch.php
  100. 147 96
      resources/templates/engine/smarty/plugins/function.html_checkboxes.php

+ 3 - 0
.htaccess

@@ -1,5 +1,8 @@
 RewriteEngine    On
 
+#REST api
+RewriteRule ^(.*)/api/(.*)$                                                     $1/api/index.php?rewrite_uri=$2 [QSA]
+
 # $mac or $mac.cfg/xml
 RewriteRule     ^.*([A-Fa-f0-9]{12})(?:\.xml|\.cfg)?$                           app/provision/index.php?mac=$1 [QSA]
 

+ 7 - 6
core/authentication/resources/classes/plugins/database.php

@@ -36,20 +36,20 @@ class plugin_database {
 		//check the username and password if they don't match then redirect to the login
 			$sql = "select * from v_users ";
 			if (strlen($this->key) > 30) {
-				$sql .= "where api_key=:key ";
-				//$sql .= "where api_key='".$this->key."' ";
+				$sql .= "where api_key = :key ";
+				//$sql .= "where api_key = '".$this->key."' ";
 			}
 			else {
-				$sql .= "where username=:username ";
-				//$sql .= "where username='".$this->username."' ";
+				$sql .= "where lower(username) = lower(:username) ";
+				//$sql .= "where username = '".$this->username."' ";
 			}
 			if ($_SESSION["user"]["unique"]["text"] == "global") {
 				//unique username - global (example: email address)
 			}
 			else {
 				//unique username - per domain
-				$sql .= "and domain_uuid=:domain_uuid ";
-				//$sql .= "and domain_uuid='".$this->domain_uuid."' ";
+				$sql .= "and domain_uuid = :domain_uuid ";
+				//$sql .= "and domain_uuid = '".$this->domain_uuid."' ";
 			}
 			$sql .= "and (user_enabled = 'true' or user_enabled is null) ";
 			//echo $sql."<br />\n";
@@ -119,6 +119,7 @@ class plugin_database {
 			}
 			$result["user_uuid"] = $this->user_uuid;
 			$result["domain_uuid"] = $this->domain_uuid;
+			$result["contact_uuid"] = $this->contact_uuid;
 			$result["sql"] = $sql;
 			if ($user_authorized) {
 				$result["authorized"] = "true";

+ 2 - 2
core/authentication/resources/classes/plugins/ldap.php

@@ -157,9 +157,9 @@ class plugin_ldap {
 
 					//add the user to group user
 						$group_name = 'user';
-						$sql = "insert into v_group_users ";
+						$sql = "insert into v_user_groups ";
 						$sql .= "(";
-						$sql .= "group_user_uuid, ";
+						$sql .= "user_group_uuid, ";
 						$sql .= "domain_uuid, ";
 						$sql .= "group_name, ";
 						$sql .= "user_uuid ";

+ 1 - 1
core/databases/database_delete.php

@@ -54,7 +54,7 @@ else {
 	}
 
 //redirect the browser
-	messages::add($text['message-delete']);
+	message::add($text['message-delete']);
 	header("Location: databases.php");
 	return;
 

+ 11 - 11
core/databases/database_edit.php

@@ -141,7 +141,7 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 				require_once "app_defaults.php";
 
 			//redirect the browser
-				messages::add($text['message-add']);
+				message::add($text['message-add']);
 				header("Location: databases.php");
 				return;
 		} //if ($action == "add")
@@ -167,7 +167,7 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 				require_once "app_defaults.php";
 
 			//redirect the browser
-				messages::add($text['message-update']);
+				message::add($text['message-update']);
 				header("Location: databases.php");
 				return;
 		} //if ($action == "update")
@@ -312,7 +312,7 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 	echo "	".$text['label-host']."\n";
 	echo "</td>\n";
 	echo "<td class='vtable' align='left'>\n";
-	echo "	<input class='formfld' type='text' name='database_host' maxlength='255' value=\"$database_host\">\n";
+	echo "	<input class='formfld' type='text' name='database_host' maxlength='255' value=\"".escape($database_host)."\">\n";
 	echo "<br />\n";
 	echo $text['description-host']."\n";
 	echo "</td>\n";
@@ -323,7 +323,7 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 	echo "	".$text['label-port']."\n";
 	echo "</td>\n";
 	echo "<td class='vtable' align='left'>\n";
-	echo "	<input class='formfld' type='text' name='database_port' maxlength='255' value=\"$database_port\">\n";
+	echo "	<input class='formfld' type='text' name='database_port' maxlength='255' value=\"".escape($database_port)."\">\n";
 	echo "<br />\n";
 	echo $text['description-port']."\n";
 	echo "</td>\n";
@@ -334,7 +334,7 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 	echo "	".$text['label-name']."\n";
 	echo "</td>\n";
 	echo "<td class='vtable' align='left'>\n";
-	echo "	<input class='formfld' type='text' name='database_name' maxlength='255' value=\"$database_name\">\n";
+	echo "	<input class='formfld' type='text' name='database_name' maxlength='255' value=\"".escape($database_name)."\">\n";
 	echo "<br />\n";
 	echo $text['description-name']."\n";
 	echo "</td>\n";
@@ -345,7 +345,7 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 	echo "	".$text['label-username']."\n";
 	echo "</td>\n";
 	echo "<td class='vtable' align='left'>\n";
-	echo "	<input class='formfld' type='text' name='database_username' maxlength='255' value=\"$database_username\">\n";
+	echo "	<input class='formfld' type='text' name='database_username' maxlength='255' value=\"".escape($database_username)."\">\n";
 	echo "<br />\n";
 	echo $text['description-username']."\n";
 	echo "</td>\n";
@@ -356,7 +356,7 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 	echo "	".$text['label-password']."\n";
 	echo "</td>\n";
 	echo "<td class='vtable' align='left'>\n";
-	echo "	<input class='formfld' type='text' name='database_password' maxlength='255' value=\"$database_password\">\n";
+	echo "	<input class='formfld' type='text' name='database_password' maxlength='255' value=\"".escape($database_password)."\">\n";
 	echo "<br />\n";
 	echo $text['description-password']."\n";
 	echo "</td>\n";
@@ -367,7 +367,7 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 	echo "	".$text['label-path']."\n";
 	echo "</td>\n";
 	echo "<td class='vtable' align='left'>\n";
-	echo "	<input class='formfld' type='text' name='database_path' maxlength='255' value=\"$database_path\">\n";
+	echo "	<input class='formfld' type='text' name='database_path' maxlength='255' value=\"".escape($database_path)."\">\n";
 	echo "<br />\n";
 	echo $text['description-path']."\n";
 	echo "</td>\n";
@@ -378,7 +378,7 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 	echo "	".$text['label-description']."\n";
 	echo "</td>\n";
 	echo "<td class='vtable' align='left'>\n";
-	echo "	<input class='formfld' type='text' name='database_description' maxlength='255' value=\"$database_description\">\n";
+	echo "	<input class='formfld' type='text' name='database_description' maxlength='255' value=\"".escape($database_description)."\">\n";
 	echo "<br />\n";
 	echo $text['description-description']."\n";
 	echo "</td>\n";
@@ -386,7 +386,7 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 	echo "	<tr>\n";
 	echo "		<td colspan='2' align='right'>\n";
 	if ($action == "update") {
-		echo "		<input type='hidden' name='database_uuid' value='$database_uuid'>\n";
+		echo "		<input type='hidden' name='database_uuid' value='".escape($database_uuid)."'>\n";
 	}
 	echo "			<br>";
 	echo "			<input type='submit' name='submit' class='btn' value='".$text['button-save']."'>\n";
@@ -398,4 +398,4 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 
 //include the footer
 	require_once "resources/footer.php";
-?>
+?>

+ 11 - 11
core/databases/databases.php

@@ -117,17 +117,17 @@ else {
 		foreach($result as $row) {
 			$tr_link = "href='database_edit.php?id=".$row['database_uuid']."'";
 			echo "<tr ".$tr_link.">\n";
-			echo "	<td valign='top' class='".$row_style[$c]."'>".$row['database_driver']."&nbsp;</td>\n";
-			echo "	<td valign='top' class='".$row_style[$c]."'>".$row['database_type']."&nbsp;</td>\n";
-			echo "	<td valign='top' class='".$row_style[$c]."'>".$row['database_host']."&nbsp;</td>\n";
-			//echo "	<td valign='top' class='".$row_style[$c]."'>".$row['database_port']."&nbsp;</td>\n";
-			echo "	<td valign='top' class='".$row_style[$c]."'><a href='database_edit.php?id=".$row['database_uuid']."'>".$row['database_name']."</a>&nbsp;</td>\n";
-			//echo "	<td valign='top' class='".$row_style[$c]."'>".$row['database_username']."&nbsp;</td>\n";
-			//echo "	<td valign='top' class='".$row_style[$c]."'>".$row['database_path']."&nbsp;</td>\n";
-			echo "	<td valign='top' class='row_stylebg'>".$row['database_description']."&nbsp;</td>\n";
+			echo "	<td valign='top' class='".$row_style[$c]."'>".escape($row['database_driver'])."&nbsp;</td>\n";
+			echo "	<td valign='top' class='".$row_style[$c]."'>".escape($row['database_type'])."&nbsp;</td>\n";
+			echo "	<td valign='top' class='".$row_style[$c]."'>".escape($row['database_host'])."&nbsp;</td>\n";
+			//echo "	<td valign='top' class='".$row_style[$c]."'>".escape($row['database_port'])."&nbsp;</td>\n";
+			echo "	<td valign='top' class='".$row_style[$c]."'><a href='database_edit.php?id=".$row['database_uuid']."'>".escape($row['database_name'])."</a>&nbsp;</td>\n";
+			//echo "	<td valign='top' class='".$row_style[$c]."'>".escape($row['database_username'])."&nbsp;</td>\n";
+			//echo "	<td valign='top' class='".$row_style[$c]."'>".escape($row['database_path'])."&nbsp;</td>\n";
+			echo "	<td valign='top' class='row_stylebg'>".escape($row['database_description'])."&nbsp;</td>\n";
 			echo "	<td class='list_control_icons'>";
-			echo 		"<a href='database_edit.php?id=".$row['database_uuid']."' alt='".$text['button-edit']."'>$v_link_label_edit</a>";
-			echo 		"<a href='database_delete.php?id=".$row['database_uuid']."' alt='".$text['button-delete']."' onclick=\"return confirm('".$text['confirm-delete']."')\">$v_link_label_delete</a>";
+			echo 		"<a href='database_edit.php?id=".escape($row['database_uuid'])."' alt='".$text['button-edit']."'>$v_link_label_edit</a>";
+			echo 		"<a href='database_delete.php?id=".escape($row['database_uuid'])."' alt='".$text['button-delete']."' onclick=\"return confirm('".$text['confirm-delete']."')\">$v_link_label_delete</a>";
 			echo "	</td>\n";
 			echo "</tr>\n";
 			if ($c==0) { $c=1; } else { $c=0; }
@@ -154,4 +154,4 @@ else {
 
 //include the footer
 	require_once "resources/footer.php";
-?>
+?>

+ 13 - 61
core/default_settings/app_config.php

@@ -105,7 +105,7 @@
 		$apps[$x]['default_settings'][$y]['default_setting_category'] = "domain";
 		$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "bridge";
 		$apps[$x]['default_settings'][$y]['default_setting_name'] = "text";
-		$apps[$x]['default_settings'][$y]['default_setting_value'] = "outbound";
+		$apps[$x]['default_settings'][$y]['default_setting_value'] = "loopback";
 		$apps[$x]['default_settings'][$y]['default_setting_enabled'] = "true";
 		$apps[$x]['default_settings'][$y]['default_setting_description'] = "outbound,loopback,lcr";
 		$y++;
@@ -117,62 +117,6 @@
 		$apps[$x]['default_settings'][$y]['default_setting_enabled'] = "true";
 		$apps[$x]['default_settings'][$y]['default_setting_description'] = "Set the maximum number of records displayed per page. (Default: 50)";
 		$y++;
-		$apps[$x]['default_settings'][$y]['default_setting_uuid'] = "57d81b35-bc24-4e92-8436-4335ab5e9d0b";
-		$apps[$x]['default_settings'][$y]['default_setting_category'] = "security";
-		$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "password_length";
-		$apps[$x]['default_settings'][$y]['default_setting_name'] = "numeric";
-		$apps[$x]['default_settings'][$y]['default_setting_value'] = "10";
-		$apps[$x]['default_settings'][$y]['default_setting_enabled'] = "true";
-		$apps[$x]['default_settings'][$y]['default_setting_description'] = "Set the required length for the generated passwords.";
-		$y++;
-		$apps[$x]['default_settings'][$y]['default_setting_uuid'] = "0fa21a56-7515-4c65-b5f8-270cc24ea375";
-		$apps[$x]['default_settings'][$y]['default_setting_category'] = "security";
-		$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "password_number";
-		$apps[$x]['default_settings'][$y]['default_setting_name'] = "boolean";
-		$apps[$x]['default_settings'][$y]['default_setting_value'] = "true";
-		$apps[$x]['default_settings'][$y]['default_setting_enabled'] = "false";
-		$apps[$x]['default_settings'][$y]['default_setting_description'] = "Set whether to require at least one number in passwords.";
-		$y++;
-		$apps[$x]['default_settings'][$y]['default_setting_uuid'] = "d5f9acbd-857c-42eb-9e9a-92a850fcb734";
-		$apps[$x]['default_settings'][$y]['default_setting_category'] = "security";
-		$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "password_lowercase";
-		$apps[$x]['default_settings'][$y]['default_setting_name'] = "boolean";
-		$apps[$x]['default_settings'][$y]['default_setting_value'] = "true";
-		$apps[$x]['default_settings'][$y]['default_setting_enabled'] = "true";
-		$apps[$x]['default_settings'][$y]['default_setting_description'] = "Set whether to require at least one lowecase letter in passwords.";
-		$y++;
-		$apps[$x]['default_settings'][$y]['default_setting_uuid'] = "256b0d87-a43e-4618-b96b-541e191879c7";
-		$apps[$x]['default_settings'][$y]['default_setting_category'] = "security";
-		$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "password_uppercase";
-		$apps[$x]['default_settings'][$y]['default_setting_name'] = "boolean";
-		$apps[$x]['default_settings'][$y]['default_setting_value'] = "true";
-		$apps[$x]['default_settings'][$y]['default_setting_enabled'] = "false";
-		$apps[$x]['default_settings'][$y]['default_setting_description'] = "Set whether to require at least one uppercase letter in passwords.";
-		$y++;
-		$apps[$x]['default_settings'][$y]['default_setting_uuid'] = "4209ff1f-6ea8-4b77-81be-bd75e8670785";
-		$apps[$x]['default_settings'][$y]['default_setting_category'] = "security";
-		$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "password_special";
-		$apps[$x]['default_settings'][$y]['default_setting_name'] = "boolean";
-		$apps[$x]['default_settings'][$y]['default_setting_value'] = "true";
-		$apps[$x]['default_settings'][$y]['default_setting_enabled'] = "false";
-		$apps[$x]['default_settings'][$y]['default_setting_description'] = "Set whether to require at least one special character in passwords.";
-		$y++;
-		$apps[$x]['default_settings'][$y]['default_setting_uuid'] = "718b1641-fa3c-4861-b1f3-40635c951888";
-		$apps[$x]['default_settings'][$y]['default_setting_category'] = "security";
-		$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "password_strength";
-		$apps[$x]['default_settings'][$y]['default_setting_name'] = "numeric";
-		$apps[$x]['default_settings'][$y]['default_setting_value'] = "4";
-		$apps[$x]['default_settings'][$y]['default_setting_enabled'] = "true";
-		$apps[$x]['default_settings'][$y]['default_setting_description'] = "Set the default strength for generated passwords. Valid Options: 1 - Numeric Only, 2 - Include Lower Apha, 3 - Include Upper Alpha, 4 - Include Special Characters.";
-		$y++;
-		$apps[$x]['default_settings'][$y]['default_setting_uuid'] = "33914c55-9081-4b95-b62e-f1a500088d78";
-		$apps[$x]['default_settings'][$y]['default_setting_category'] = "security";
-		$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "session_rotate";
-		$apps[$x]['default_settings'][$y]['default_setting_name'] = "boolean";
-		$apps[$x]['default_settings'][$y]['default_setting_value'] = "true";
-		$apps[$x]['default_settings'][$y]['default_setting_enabled'] = "true";
-		$apps[$x]['default_settings'][$y]['default_setting_description'] = "Whether to regenerate the session ID.";
-		$y++;
 		$apps[$x]['default_settings'][$y]['default_setting_uuid'] = "97a2410b-cfc8-4194-9172-dd5b0acfa9f3";
 		$apps[$x]['default_settings'][$y]['default_setting_category'] = "email";
 		$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "smtp_auth";
@@ -213,6 +157,14 @@
 		$apps[$x]['default_settings'][$y]['default_setting_enabled'] = "true";
 		$apps[$x]['default_settings'][$y]['default_setting_description'] = "";
 		$y++;
+		$apps[$x]['default_settings'][$y]['default_setting_uuid'] = "82bfc038-5e8d-427e-9773-0eb31bc3a6c3";
+		$apps[$x]['default_settings'][$y]['default_setting_category'] = "email";
+		$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "smtp_hostname";
+		$apps[$x]['default_settings'][$y]['default_setting_name'] = "text";
+		$apps[$x]['default_settings'][$y]['default_setting_value'] = "";
+		$apps[$x]['default_settings'][$y]['default_setting_enabled'] = "false";
+		$apps[$x]['default_settings'][$y]['default_setting_description'] = "Define the local hostname to be used when sending mail.";
+		$y++;
 		$apps[$x]['default_settings'][$y]['default_setting_uuid'] = "0bd788c1-3262-4336-92f4-ef7869062380";
 		$apps[$x]['default_settings'][$y]['default_setting_category'] = "email";
 		$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "smtp_host";
@@ -257,7 +209,7 @@
 		$apps[$x]['default_settings'][$y]['default_setting_category'] = "login";
 		$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "password_reset_key";
 		$apps[$x]['default_settings'][$y]['default_setting_name'] = "text";
-		$apps[$x]['default_settings'][$y]['default_setting_value'] = generate_password('20', '4');
+		$apps[$x]['default_settings'][$y]['default_setting_value'] = base64_encode(openssl_random_pseudo_bytes(32));
 		$apps[$x]['default_settings'][$y]['default_setting_enabled'] = "false";
 		$apps[$x]['default_settings'][$y]['default_setting_description'] = "Display a Reset Password link on the login box (requires smtp_host be defined).";
 		$y++;
@@ -473,15 +425,15 @@
 		$apps[$x]['default_settings'][$y]['default_setting_category'] = "cache";
 		$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "method";
 		$apps[$x]['default_settings'][$y]['default_setting_name'] = "text";
-		$apps[$x]['default_settings'][$y]['default_setting_value'] = "memcache";
+		$apps[$x]['default_settings'][$y]['default_setting_value'] = "file";
 		$apps[$x]['default_settings'][$y]['default_setting_enabled'] = "true";
-		$apps[$x]['default_settings'][$y]['default_setting_description'] = "Cache methods file and memcache.";
+		$apps[$x]['default_settings'][$y]['default_setting_description'] = "Cache methods file or memcache.";
 		$y++;
 		$apps[$x]['default_settings'][$y]['default_setting_uuid'] = "7b644bfb-124f-4212-9541-1ca564be9d79";
 		$apps[$x]['default_settings'][$y]['default_setting_category'] = "cache";
 		$apps[$x]['default_settings'][$y]['default_setting_subcategory'] = "location";
 		$apps[$x]['default_settings'][$y]['default_setting_name'] = "text";
-		$apps[$x]['default_settings'][$y]['default_setting_value'] = "/tmp";
+		$apps[$x]['default_settings'][$y]['default_setting_value'] = "/var/cache/fusionpbx";
 		$apps[$x]['default_settings'][$y]['default_setting_enabled'] = "true";
 		$apps[$x]['default_settings'][$y]['default_setting_description'] = "Location for the file cache.";
 

+ 100 - 0
core/default_settings/app_languages.php

@@ -481,6 +481,26 @@ $text['label-fixed']['ru-ru'] = "Фиксированный";
 $text['label-fixed']['sv-se'] = "Fast";
 $text['label-fixed']['uk-ua'] = "фіксований";
 
+$text['label-side']['en-us'] = "Side";
+$text['label-side']['ar-eg'] = "";
+$text['label-side']['de-at'] = "";
+$text['label-side']['de-ch'] = "";
+$text['label-side']['de-de'] = "";
+$text['label-side']['es-cl'] = "";
+$text['label-side']['es-mx'] = "";
+$text['label-side']['fr-ca'] = "";
+$text['label-side']['fr-fr'] = "";
+$text['label-side']['he-il'] = "";
+$text['label-side']['it-it'] = "";
+$text['label-side']['nl-nl'] = "";
+$text['label-side']['pl-pl'] = "";
+$text['label-side']['pt-br'] = "";
+$text['label-side']['pt-pt'] = "";
+$text['label-side']['ro-ro'] = "";
+$text['label-side']['ru-ru'] = "";
+$text['label-side']['sv-se'] = "";
+$text['label-side']['uk-ua'] = "";
+
 $text['label-fine']['en-us'] = "Fine";
 $text['label-fine']['ar-eg'] = "";
 $text['label-fine']['de-at'] = "Fein"; //copied from de-de
@@ -581,6 +601,86 @@ $text['label-12-hour']['ru-ru'] = "12-часовой";
 $text['label-12-hour']['sv-se'] = "12-timmars";
 $text['label-12-hour']['uk-ua'] = "12-годинний";
 
+$text['label-hours']['en-us'] = "Hour(s)";
+$text['label-hours']['ar-eg'] = "";
+$text['label-hours']['de-at'] = "";
+$text['label-hours']['de-ch'] = "";
+$text['label-hours']['de-de'] = "";
+$text['label-hours']['es-cl'] = "";
+$text['label-hours']['es-mx'] = "";
+$text['label-hours']['fr-ca'] = "";
+$text['label-hours']['fr-fr'] = "";
+$text['label-hours']['he-il'] = "";
+$text['label-hours']['it-it'] = "";
+$text['label-hours']['nl-nl'] = "";
+$text['label-hours']['pl-pl'] = "";
+$text['label-hours']['pt-br'] = "";
+$text['label-hours']['pt-pt'] = "";
+$text['label-hours']['ro-ro'] = "";
+$text['label-hours']['ru-ru'] = "";
+$text['label-hours']['sv-se'] = "";
+$text['label-hours']['uk-ua'] = "";
+
+$text['label-days']['en-us'] = "Day(s)";
+$text['label-days']['ar-eg'] = "";
+$text['label-days']['de-at'] = "";
+$text['label-days']['de-ch'] = "";
+$text['label-days']['de-de'] = "";
+$text['label-days']['es-cl'] = "";
+$text['label-days']['es-mx'] = "";
+$text['label-days']['fr-ca'] = "";
+$text['label-days']['fr-fr'] = "";
+$text['label-days']['he-il'] = "";
+$text['label-days']['it-it'] = "";
+$text['label-days']['nl-nl'] = "";
+$text['label-days']['pl-pl'] = "";
+$text['label-days']['pt-br'] = "";
+$text['label-days']['pt-pt'] = "";
+$text['label-days']['ro-ro'] = "";
+$text['label-days']['ru-ru'] = "";
+$text['label-days']['sv-se'] = "";
+$text['label-days']['uk-ua'] = "";
+
+$text['label-messages']['en-us'] = "Message(s)";
+$text['label-messages']['ar-eg'] = "";
+$text['label-messages']['de-at'] = "";
+$text['label-messages']['de-ch'] = "";
+$text['label-messages']['de-de'] = "";
+$text['label-messages']['es-cl'] = "";
+$text['label-messages']['es-mx'] = "";
+$text['label-messages']['fr-ca'] = "";
+$text['label-messages']['fr-fr'] = "";
+$text['label-messages']['he-il'] = "";
+$text['label-messages']['it-it'] = "";
+$text['label-messages']['nl-nl'] = "";
+$text['label-messages']['pl-pl'] = "";
+$text['label-messages']['pt-br'] = "";
+$text['label-messages']['pt-pt'] = "";
+$text['label-messages']['ro-ro'] = "";
+$text['label-messages']['ru-ru'] = "";
+$text['label-messages']['sv-se'] = "";
+$text['label-messages']['uk-ua'] = "";
+
+$text['label-image_text']['en-us'] = "Image & Text";
+$text['label-image_text']['ar-eg'] = "";
+$text['label-image_text']['de-at'] = "";
+$text['label-image_text']['de-ch'] = "";
+$text['label-image_text']['de-de'] = "";
+$text['label-image_text']['es-cl'] = "";
+$text['label-image_text']['es-mx'] = "";
+$text['label-image_text']['fr-ca'] = "";
+$text['label-image_text']['fr-fr'] = "";
+$text['label-image_text']['he-il'] = "";
+$text['label-image_text']['it-it'] = "";
+$text['label-image_text']['nl-nl'] = "";
+$text['label-image_text']['pl-pl'] = "";
+$text['label-image_text']['pt-br'] = "";
+$text['label-image_text']['pt-pt'] = "";
+$text['label-image_text']['ro-ro'] = "";
+$text['label-image_text']['ru-ru'] = "";
+$text['label-image_text']['sv-se'] = "";
+$text['label-image_text']['uk-ua'] = "";
+
 $text['header-default_settings']['en-us'] = "Default Settings";
 $text['header-default_settings']['ar-eg'] = "";
 $text['header-default_settings']['de-at'] = "Standard Einstellungen"; //copied from de-de

+ 25 - 6
core/default_settings/default_setting_edit.php

@@ -153,12 +153,12 @@
 
 				//set the message and redirect the user
 				if ($action == "add" && permission_exists('default_setting_add')) {
-					messages::add($text['message-add']);
+					message::add($text['message-add']);
 					header("Location: default_settings.php".(($search != '') ? "?search=".$search : null)."#anchor_".$default_setting_category);
 					return;
 				}
 				if ($action == "update" && permission_exists('default_setting_edit')) {
-					messages::add($text['message-update']);
+					message::add($text['message-update']);
 					header("Location: default_settings.php".(($search != '') ? "?search=".$search : null)."#anchor_".$default_setting_category);
 					return;
 				}
@@ -497,6 +497,18 @@
 		echo "		<option value='7' ".(($default_setting_value == "7") ? "selected='selected'" : null).">MMM DD</option>\n";
 		echo "	</select>\n";
 	}
+	elseif ($category == "message" && $subcategory == "display_last" && $name == "text") {
+		$array = explode(' ',$default_setting_value);
+		if (!is_numeric($array[0])) { $array[1] = $array[0]; $array[0] = ''; }
+		echo "	<input type='text' class='formfld' id='default_setting_value_1' value=\"".$array[0]."\" onchange=\"$('#default_setting_value').val($('#default_setting_value_1').val() + ' ' + $('#default_setting_value_2 option:selected').val());\">\n";
+		echo "	<select class='formfld' id='default_setting_value_2' onchange=\"$('#default_setting_value').val($('#default_setting_value_1').val() + ' ' + $('#default_setting_value_2 option:selected').val());\">\n";
+		echo "		<option value='hours' ".($array[1] == "hours" ? "selected='selected'" : null).">".$text['label-hours']."</option>\n";
+		echo "		<option value='days' ".($array[1] == "days" ? "selected='selected'" : null).">".$text['label-days']."</option>\n";
+		echo "		<option value='messages' ".($array[1] == "messages" ? "selected='selected'" : null).">".$text['label-messages']."</option>\n";
+		echo "	</select>\n";
+		echo "	<input type='hidden' id='default_setting_value' name='default_setting_value' value=\"".$default_setting_value."\">\n";
+		unset($array);
+	}
 	elseif ($category == "theme" && $subcategory == "domain_visible" && $name == "text" ) {
 		echo "    <select class='formfld' id='default_setting_value' name='default_setting_value'>\n";
 		echo "    	<option value='false' ".(($default_setting_value == "false") ? "selected='selected'" : null).">".$text['label-false']."</option>\n";
@@ -522,6 +534,7 @@
 		echo "    <select class='formfld' id='default_setting_value' name='default_setting_value'>\n";
 		echo "    	<option value='image' ".(($default_setting_value == "image") ? "selected='selected'" : null).">".$text['label-image']."</option>\n";
 		echo "    	<option value='text' ".(($default_setting_value == "text") ? "selected='selected'" : null).">".$text['label-text']."</option>\n";
+		echo "    	<option value='image_text' ".(($default_setting_value == "image_text") ? "selected='selected'" : null).">".$text['label-image_text']."</option>\n";
 		echo "    	<option value='none' ".(($default_setting_value == "none") ? "selected='selected'" : null).">".$text['label-none']."</option>\n";
 		echo "    </select>\n";
 	}
@@ -530,6 +543,7 @@
 		echo "    	<option value='fixed' ".(($default_setting_value == "fixed") ? "selected='selected'" : null).">".$text['label-fixed']."</option>\n";
 		echo "    	<option value='static' ".(($default_setting_value == "static") ? "selected='selected'" : null).">".$text['label-static']."</option>\n";
 		echo "    	<option value='inline' ".(($default_setting_value == "inline") ? "selected='selected'" : null).">".$text['label-inline']."</option>\n";
+		echo "    	<option value='side' ".(($default_setting_value == "side") ? "selected='selected'" : null).">".$text['label-side']."</option>\n";
 		echo "    </select>\n";
 	}
 	elseif ($category == "theme" && $subcategory == "menu_position" && $name == "text" ) {
@@ -545,6 +559,9 @@
 		echo "    	<option value='right' ".(($default_setting_value == "right") ? "selected='selected'" : null).">".$text['label-right']."</option>\n";
 		echo "    </select>\n";
 	}
+	elseif ($category == "theme" && $subcategory == "custom_css_code" && $name == "text" ) {
+		echo "	<textarea class='formfld' style='min-width: 100%; height: 300px; font-family: courier, monospace; overflow: auto; resize: vertical' id='default_setting_value' name='default_setting_value' wrap='off'>".$default_setting_value."</textarea>\n";
+	}
 	elseif ($category == "voicemail" && $subcategory == "voicemail_file" && $name == "text" ) {
 		echo "    <select class='formfld' id='default_setting_value' name='default_setting_value'>\n";
 		echo "    	<option value='listen' ".(($default_setting_value == "listen") ? "selected='selected'" : null).">".$text['option-voicemail_file_listen']."</option>\n";
@@ -559,7 +576,7 @@
 		echo "	</select>\n";
 	}
 	elseif (is_json($default_setting_value)) {
-		echo "	<textarea class='formfld' style='width: 100%; height: 80px; font-family: courier; white-space: nowrap; overflow: auto;' id='default_setting_value' name='default_setting_value' wrap='off'>".$default_setting_value."</textarea>\n";
+		echo "	<textarea class='formfld' style='width: 100%; height: 80px; font-family: courier, monospace; overflow: auto;' id='default_setting_value' name='default_setting_value' wrap='off'>".$default_setting_value."</textarea>\n";
 	}
 	else {
 		echo "	<input class='formfld' type='text' id='default_setting_value' name='default_setting_value' value=\"".htmlspecialchars($default_setting_value)."\">\n";
@@ -657,9 +674,11 @@
 
 	echo "<script>\n";
 	//capture enter key to submit form
-		echo "	$(window).keypress(function(event){\n";
-		echo "		if (event.which == 13) { submit_form(); }\n";
-		echo "	});\n";
+		if (!($category == "theme" && $subcategory == "custom_css_code" && $name == "text" )) {
+			echo "	$(window).keypress(function(event){\n";
+			echo "		if (event.which == 13) { submit_form(); }\n";
+			echo "	});\n";
+		}
 	//hide/convert password fields then submit form
 		echo "	function submit_form() {\n";
 		echo "		$('input:password').css('visibility','hidden');\n";

+ 2 - 2
core/default_settings/default_setting_toggle.php

@@ -26,7 +26,7 @@
 require_once "root.php";
 require_once "resources/require.php";
 require_once "resources/check_auth.php";
-if (permission_exists('voicemail_message_view')) {
+if (permission_exists('default_setting_edit')) {
 	//access granted
 }
 else {
@@ -69,4 +69,4 @@ else {
 	}
 	header("Location: default_settings.php".(($search != '') ? '?search='.$search : null));
 
-?>
+?>

+ 10 - 5
core/default_settings/default_settings.php

@@ -57,7 +57,7 @@
 			$db->exec(check_sql($sql));
 			unset($sql);
 
-			messages::add($text['message-update']);
+			message::add($text['message-update']);
 			header("Location: default_settings.php".(($search != '') ? "?search=".escape($search) : null)."#anchor_".escape($category));
 			exit;
 		}
@@ -171,7 +171,7 @@
 			}
 			else {
 				// set message
-				messages::add($text['message-copy_failed']);
+				message::add($text['message-copy_failed']);
 			}
 
 			header("Location: default_settings.php".(($search != '') ? "?search=".escape($search) : null));
@@ -194,7 +194,7 @@
 			}
 			else {
 				// set message
-				messages::add($text['message-delete_failed'], 'negative');
+				message::add($text['message-delete_failed'], 'negative');
 			}
 
 			header("Location: default_settings.php".(($search != '') ? "?search=".escape($search) : null));
@@ -431,7 +431,10 @@
 				) {
 				echo "		".$text['label-'.$row['default_setting_value']];
 			}
-			else if ($subcategory == 'password' || substr_count($subcategory, '_password') > 0 || $category == "login" && $subcategory == "password_reset_key" && $name == "text") {
+			else if ($category == 'theme' && $subcategory == 'custom_css_code' && $name == 'text') {
+				echo "		[...]\n";
+			}
+			else if ($subcategory == 'password' || substr_count($subcategory, '_password') > 0 || $category == "login" && $subcategory == "password_reset_key" && $name == "text" || substr_count($subcategory, '_secret') > 0) {
 				echo "		".str_repeat('*', strlen($row['default_setting_value']));
 			}
 			else {
@@ -469,7 +472,9 @@
 			$array_setting_uuids[] = $row['default_setting_uuid'];
 			$array_setting_subcategories[] = $row['default_setting_subcategory'];
 			$array_setting_types[] = $row['default_setting_name'];
-			$array_setting_values[] = str_replace('"','\"',$row['default_setting_value']);
+			if (!($category == "theme" && $subcategory == "custom_css_code" && $name == "text" )) {
+				$array_setting_values[] = str_replace('"','\"',$row['default_setting_value']);
+			}
 			$array_setting_descriptions[] = str_replace('"','\"',$row['default_setting_description']);
 
 			$previous_category = $row['default_setting_category'];

+ 1 - 1
core/default_settings/default_settings_reload.php

@@ -45,7 +45,7 @@ $domain = new domains();
 $domain->db = $db;
 $domain->set();
 
-messages::add($text['message-settings_reloaded']);
+message::add($text['message-settings_reloaded']);
 header("Location: default_settings.php".(($search != '') ? "?search=".$search : null));
 
 ?>

+ 1 - 1
core/domain_settings/app_config.php

@@ -41,7 +41,7 @@
 		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
 		$y++;
 		$apps[$x]['permissions'][$y]['name'] = "domain_delete";
-		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
+		//$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
 		$y++;
 		$apps[$x]['permissions'][$y]['name'] = "domain_select";
 		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";

+ 124 - 118
core/domain_settings/domain_delete.php

@@ -17,7 +17,7 @@
 
  The Initial Developer of the Original Code is
  Mark J Crane <[email protected]>
- Portions created by the Initial Developer are Copyright (C) 2008-2016
+ Portions created by the Initial Developer are Copyright (C) 2008-2019
  the Initial Developer. All Rights Reserved.
 
  Contributor(s):
@@ -43,159 +43,165 @@
 	$text = $language->get();
 
 //get the id
-	if (count($_GET)>0) {
+	if (is_array($_GET)) {
 		$id = check_str($_GET["id"]);
 	}
 
 //delete domain data and files
-if (strlen($id) > 0) {
-	//get the domain using the id
-		$sql = "select * from v_domains ";
-		$sql .= "where domain_uuid = '$id' ";
-		$prep_statement = $db->prepare(check_sql($sql));
-		$prep_statement->execute();
-		$result = $prep_statement->fetchAll(PDO::FETCH_NAMED);
-		if (isset($result)) foreach ($result as &$row) {
-			$domain_name = $row["domain_name"];
-		}
-		unset ($prep_statement);
-
-	//get the domain settings
-		$sql = "select * from v_domain_settings ";
-		$sql .= "where domain_uuid = '".$id."' ";
-		$sql .= "and domain_setting_enabled = 'true' ";
-		$prep_statement = $db->prepare($sql);
-		$prep_statement->execute();
-		$result = $prep_statement->fetchAll(PDO::FETCH_NAMED);
-		if (isset($result)) foreach($result as $row) {
-			$name = $row['domain_setting_name'];
-			$category = $row['domain_setting_category'];
-			$subcategory = $row['domain_setting_subcategory'];
-			if (strlen($subcategory) == 0) {
-				if ($name == "array") {
-					$_SESSION[$category][] = $row['default_setting_value'];
-				}
-				else {
-					$_SESSION[$category][$name] = $row['default_setting_value'];
-				}
-			} else {
-				if ($name == "array") {
-					$_SESSION[$category][$subcategory][] = $row['default_setting_value'];
-				}
-				else {
-					$_SESSION[$category][$subcategory]['uuid'] = $row['default_setting_uuid'];
-					$_SESSION[$category][$subcategory][$name] = $row['default_setting_value'];
+	if (is_uuid($id)) {
+		//get the domain using the id
+			$sql = "select * from v_domains ";
+			$sql .= "where domain_uuid = '$id' ";
+			$prep_statement = $db->prepare(check_sql($sql));
+			$prep_statement->execute();
+			$result = $prep_statement->fetchAll(PDO::FETCH_NAMED);
+			if (isset($result)) {
+				foreach ($result as &$row) {
+					$domain_name = $row["domain_name"];
 				}
 			}
-		}
-
-	//get the $apps array from the installed apps from the core and mod directories
-		$config_list = glob($_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/*/*/app_config.php");
-		$x=0;
-		if (isset($config_list)) foreach ($config_list as &$config_path) {
-			include($config_path);
-			$x++;
-		}
-
-	//delete the domain data from all tables in the database
-		$db->beginTransaction();
-		if (isset($apps)) foreach ($apps as &$app) {
-			if (isset($app['db'])) foreach ($app['db'] as $row) {
-				if (is_array($row['table'])) {
-					$table_name = $row['table']['name'];
-				}
-				else {
-					$table_name = $row['table'];
-				}
-				if ($table_name !== "v" && isset($row['fields'])) {
-					foreach ($row['fields'] as $field) {
-						if ($field['name'] == "domain_uuid") {
-							$sql = "delete from $table_name where domain_uuid = '$id' ";
-							$db->query($sql);
-						}
+			unset ($prep_statement);
+
+		//get the domain settings
+			$sql = "select * from v_domain_settings ";
+			$sql .= "where domain_uuid = '".$id."' ";
+			$sql .= "and domain_setting_enabled = 'true' ";
+			$prep_statement = $db->prepare($sql);
+			$prep_statement->execute();
+			$result = $prep_statement->fetchAll(PDO::FETCH_NAMED);
+			if (isset($result)) foreach($result as $row) {
+				$name = $row['domain_setting_name'];
+				$category = $row['domain_setting_category'];
+				$subcategory = $row['domain_setting_subcategory'];
+				if (strlen($subcategory) == 0) {
+					if ($name == "array") {
+						$_SESSION[$category][] = $row['default_setting_value'];
+					}
+					else {
+						$_SESSION[$category][$name] = $row['default_setting_value'];
+					}
+				} else {
+					if ($name == "array") {
+						$_SESSION[$category][$subcategory][] = $row['default_setting_value'];
+					}
+					else {
+						$_SESSION[$category][$subcategory]['uuid'] = $row['default_setting_uuid'];
+						$_SESSION[$category][$subcategory][$name] = $row['default_setting_value'];
 					}
 				}
 			}
-		}
-		$db->commit();
-
-	//delete the directories
-		if (strlen($domain_name) > 0) {
-		//set the needle
-			if (count($_SESSION["domains"]) > 1) {
-				$v_needle = 'v_'.$domain_name.'_';
-			}
-			else {
-				$v_needle = 'v_';
-			}
 
-		//delete the dialplan
-			unlink($_SESSION['switch']['dialplan']['dir'].'/'.$domain_name.'.xml');
-			if (strlen($_SESSION['switch']['dialplan']['dir']) > 0) {
-				system('rm -rf '.$_SESSION['switch']['dialplan']['dir'].'/'.$domain_name);
+		//get the $apps array from the installed apps from the core and mod directories
+			$config_list = glob($_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/*/*/app_config.php");
+			$x=0;
+			if (isset($config_list)) foreach ($config_list as &$config_path) {
+				include($config_path);
+				$x++;
 			}
 
-		//delete the dialplan public
-			unlink($_SESSION['switch']['dialplan']['dir'].'/public/'.$domain_name.'.xml');
-			if (strlen($_SESSION['switch']['dialplan']['dir']) > 0) {
-				system('rm -rf '.$_SESSION['switch']['dialplan']['dir'].'/public/'.$domain_name);
+		//delete the domain data from all tables in the database
+			$db->beginTransaction();
+			if (isset($apps)) foreach ($apps as &$app) {
+				if (isset($app['db'])) foreach ($app['db'] as $row) {
+					if (is_array($row['table']['name'])) {
+						$table_name = $row['table']['name']['text'];
+						echo "<pre>";
+						print_r($table_name);
+						echo "<pre>\n";
+					}
+					else {
+						$table_name = $row['table']['name'];
+					}
+					if ($table_name !== "v" && isset($row['fields'])) {
+						foreach ($row['fields'] as $field) {
+							if ($field['name'] == "domain_uuid") {
+								$sql = "delete from $table_name where domain_uuid = '$id'; ";
+								//echo $sql."<br />\n";
+								$db->query($sql);
+							}
+						}
+					}
+				}
 			}
+			$db->commit();
+
+		//delete the directories
+			if (strlen($domain_name) > 0) {
+				//set the needle
+				if (count($_SESSION["domains"]) > 1) {
+					$v_needle = 'v_'.$domain_name.'_';
+				}
+				else {
+					$v_needle = 'v_';
+				}
+
+				//delete the dialplan
+				unlink($_SESSION['switch']['dialplan']['dir'].'/'.$domain_name.'.xml');
+				if (strlen($_SESSION['switch']['dialplan']['dir']) > 0) {
+					system('rm -rf '.$_SESSION['switch']['dialplan']['dir'].'/'.$domain_name);
+				}
+
+				//delete the dialplan public
+				unlink($_SESSION['switch']['dialplan']['dir'].'/public/'.$domain_name.'.xml');
+				if (strlen($_SESSION['switch']['dialplan']['dir']) > 0) {
+					system('rm -rf '.$_SESSION['switch']['dialplan']['dir'].'/public/'.$domain_name);
+				}
 
-		//delete the extension
+				//delete the extension
 				unlink($_SESSION['switch']['extensions']['dir'].'/'.$domain_name.'.xml');
 				if (strlen($_SESSION['switch']['extensions']['dir']) > 0) {
 					system('rm -rf '.$_SESSION['switch']['extensions']['dir'].'/'.$domain_name);
 				}
 
-			//delete fax
+				//delete fax
 				if (strlen($_SESSION['switch']['storage']['dir']) > 0) {
 					system('rm -rf '.$_SESSION['switch']['storage']['dir'].'/fax/'.$domain_name);
-					}
+				}
 
 				//delete the gateways
-					if($dh = opendir($_SESSION['switch']['sip_profiles']['dir'])) {
-						$files = Array();
-						while($file = readdir($dh)) {
-							if($file != "." && $file != ".." && $file[0] != '.') {
-								if(is_dir($dir . "/" . $file)) {
-									//this is a directory do nothing
-								} else {
-									//check if file extension is xml
-									if (strpos($file, $v_needle) !== false && substr($file,-4) == '.xml') {
-										unlink($_SESSION['switch']['sip_profiles']['dir']."/".$file);
-									}
+				if($dh = opendir($_SESSION['switch']['sip_profiles']['dir'])) {
+					$files = Array();
+					while($file = readdir($dh)) {
+						if($file != "." && $file != ".." && $file[0] != '.') {
+							if(is_dir($dir . "/" . $file)) {
+								//this is a directory do nothing
+							} else {
+								//check if file extension is xml
+								if (strpos($file, $v_needle) !== false && substr($file,-4) == '.xml') {
+									unlink($_SESSION['switch']['sip_profiles']['dir']."/".$file);
 								}
 							}
 						}
-						closedir($dh);
 					}
+					closedir($dh);
+				}
 
 				//delete the ivr menu
-					if($dh = opendir($_SESSION['switch']['conf']['dir']."/ivr_menus/")) {
-						$files = Array();
-						while($file = readdir($dh)) {
-							if($file != "." && $file != ".." && $file[0] != '.') {
-								if(is_dir($dir . "/" . $file)) {
-									//this is a directory
-								} else {
-									if (strpos($file, $v_needle) !== false && substr($file,-4) == '.xml') {
-										unlink($_SESSION['switch']['conf']['dir']."/ivr_menus/".$file);
-									}
+				if($dh = opendir($_SESSION['switch']['conf']['dir']."/ivr_menus/")) {
+					$files = Array();
+					while($file = readdir($dh)) {
+						if($file != "." && $file != ".." && $file[0] != '.') {
+							if(is_dir($dir . "/" . $file)) {
+								//this is a directory
+							} else {
+								if (strpos($file, $v_needle) !== false && substr($file,-4) == '.xml') {
+									unlink($_SESSION['switch']['conf']['dir']."/ivr_menus/".$file);
 								}
 							}
 						}
-						closedir($dh);
 					}
+					closedir($dh);
+				}
 
 				//delete the recordings
-					if (strlen($_SESSION['switch'][recordings]['dir']) > 0) {
-						system('rm -rf '.$_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/'.$domain_name);
-					}
+				if (strlen($_SESSION['switch'][recordings]['dir']) > 0) {
+					system('rm -rf '.$_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/'.$domain_name);
+				}
 
 				//delete voicemail
-					if (strlen($_SESSION['switch']['voicemail']['dir']) > 0) {
-						system('rm -rf '.$_SESSION['switch']['voicemail']['dir'].'/'.$domain_name);
-					}
+				if (strlen($_SESSION['switch']['voicemail']['dir']) > 0) {
+					system('rm -rf '.$_SESSION['switch']['voicemail']['dir'].'/'.$domain_name);
+				}
 			}
 
 		//apply settings reminder
@@ -210,7 +216,7 @@ if (strlen($id) > 0) {
 	}
 
 //redirect the browser
-	messages::add($text['message-delete']);
+	message::add($text['message-delete']);
 	header("Location: domains.php");
 	return;
 

+ 54 - 2
core/domain_settings/domain_edit.php

@@ -602,7 +602,7 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 
 		//redirect the browser
 			if ($action == "update") {
-				messages::add($text['message-update']);
+				message::add($text['message-update']);
 				if (!permission_exists('domain_add')) { //admin, updating own domain
 					header("Location: domain_edit.php");
 				}
@@ -611,7 +611,7 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 				}
 			}
 			if ($action == "add") {
-				messages::add($text['message-add']);
+				message::add($text['message-add']);
 				header("Location: domains.php");
 			}
 			return;
@@ -642,6 +642,47 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 		$document['title'] = $text['title-domain-add'];
 	}
 
+//copy settings javascript
+	if (permission_exists("domain_select") && permission_exists("domain_setting_add") && count($_SESSION['domains']) > 1) {
+		echo "<script language='javascript' type='text/javascript'>\n";
+		echo "	var fade_speed = 400;\n";
+		echo "	function show_domains() {\n";
+		echo "		document.getElementById('action').value = 'copy';\n";
+		echo "		$('#button_copy').fadeOut(fade_speed, function() {\n";
+		echo "			$('#button_back').fadeIn(fade_speed);\n";
+		echo "			$('#target_domain_uuid').fadeIn(fade_speed);\n";
+		echo "			$('#button_paste').fadeIn(fade_speed);\n";
+		echo "		});";
+		echo "	}";
+		echo "	function hide_domains() {\n";
+		echo "		document.getElementById('action').value = '';\n";
+		echo "		$('#button_back').fadeOut(fade_speed);\n";
+		echo "		$('#target_domain_uuid').fadeOut(fade_speed);\n";
+		echo "		$('#button_paste').fadeOut(fade_speed, function() {\n";
+		echo "			$('#button_copy').fadeIn(fade_speed);\n";
+		echo "			document.getElementById('target_domain_uuid').selectedIndex = 0;\n";
+		echo "		});\n";
+		echo "	}\n";
+		echo "\n";
+		echo "	$( document ).ready(function() {\n";
+		echo "		$('#domain_setting_search').focus();\n";
+		if ($search == '') {
+			echo "		// scroll to previous category\n";
+			echo "		var category_span_id;\n";
+			echo "		var url = document.location.href;\n";
+			echo "		var hashindex = url.indexOf('#');\n";
+			echo "		if (hashindex == -1) { }\n";
+			echo "		else {\n";
+			echo "			category_span_id = url.substr(hashindex + 1);\n";
+			echo "		}\n";
+			echo "		if (category_span_id) {\n";
+			echo "			$('#page').animate({scrollTop: $('#anchor_'+category_span_id).offset().top - 200}, 'slow');\n";
+			echo "		}\n";
+		}
+		echo "	});\n";
+		echo "</script>";
+	}
+
 //show the content
 	echo "<form method='post' name='frm' action=''>\n";
 	echo "<table width='100%' cellpadding='0' cellspacing='0' border='0'>\n";
@@ -658,6 +699,17 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 	if (permission_exists('domain_add')) { //only for superadmin, not admin editing their own domain
 		echo "	<input type='button' class='btn' name='' alt='".$text['button-back']."' onclick=\"window.location='domains.php'\" value='".$text['button-back']."'>\n";
 	}
+	//if (permission_exists("domain_select") && permission_exists("domain_setting_add") && count($_SESSION['domains']) > 1) {
+	//	echo "		<input type='button' class='btn' id='button_copy' alt='".$text['button-copy']."' onclick='show_domains();' value='".$text['button-copy']."'>";
+	//	echo "		<input type='button' class='btn' style='display: none;' id='button_back' alt='".$text['button-back']."' onclick='hide_domains();' value='".$text['button-back']."'> ";
+	//	echo "		<select class='formfld' style='display: none; width: auto;' name='target_domain_uuid' id='target_domain_uuid'>\n";
+	//	echo "			<option value=''>Select Domain...</option>\n";
+	//	foreach ($_SESSION['domains'] as $domain) {
+	//		echo "		<option value='".escape($domain["domain_uuid"])."'>".escape($domain["domain_name"])."</option>\n";
+	//	}
+	//	echo "		</select>\n";
+	//	echo "		<input type='button' class='btn' id='button_paste' style='display: none;' alt='".$text['button-paste']."' value='".$text['button-paste']."' onclick=\"$('#frm').attr('action', 'domain_settings.php?search='+$('#domain_setting_search').val()).submit();\">";
+	//}
 	if (permission_exists('domain_export')) {
 		echo "	<input type='button' class='btn' name='' alt='".$text['button-export']."' onclick=\"window.location='".PROJECT_PATH."/app/domain_export/index.php?id=".escape($domain_uuid)."'\" value='".$text['button-export']."'>\n";
 	}

+ 1 - 1
core/domain_settings/domain_setting_delete.php

@@ -56,7 +56,7 @@ else {
 	}
 
 //redirect the user
-	messages::add($text['message-delete']);
+	message::add($text['message-delete']);
 	header("Location: domain_edit.php?id=".$domain_uuid);
 	return;
 

+ 23 - 3
core/domain_settings/domain_setting_edit.php

@@ -17,7 +17,7 @@
 
  The Initial Developer of the Original Code is
  Mark J Crane <[email protected]>
- Portions created by the Initial Developer are Copyright (C) 2008-2015
+ Portions created by the Initial Developer are Copyright (C) 2008-2018
  the Initial Developer. All Rights Reserved.
 
  Contributor(s):
@@ -184,6 +184,26 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 						}
 						$db->query($sql);
 						unset($sql);
+
+					//get the dialplan_uuid
+						$sql = "select * from v_domains ";
+						$sql .= "where domain_uuid = '".$domain_uuid."' ";
+						$prep_statement = $db->prepare(check_sql($sql));
+						$prep_statement->execute();
+						$row = $prep_statement->fetch(PDO::FETCH_NAMED);
+						$domain_name = $row["domain_name"];
+						unset ($prep_statement);
+
+					//update the dialplan xml
+						$dialplans = new dialplan;
+						$dialplans->source = "details";
+						$dialplans->destination = "database";
+						$dialplans->uuid = $dialplan_uuid;
+						$dialplans->xml();
+
+					//clear the cache
+						$cache = new cache;
+						$cache->delete("dialplan:".$domain_name);
 				}
 
 			//add the domain
@@ -317,10 +337,10 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 
 			//redirect the browser
 				if ($action == "update") {
-					messages::add($text['message-update']);
+					message::add($text['message-update']);
 				}
 				if ($action == "add") {
-					messages::add($text['message-add']);
+					message::add($text['message-add']);
 				}
 				header("Location: domain_edit.php?id=".$domain_uuid);
 				return;

+ 101 - 2
core/domain_settings/domain_settings.php

@@ -55,11 +55,110 @@
 				$db->exec(check_sql($sql));
 				unset($sql);
 
-				messages::add($text['message-update']);
+				message::add($text['message-update']);
 				header("Location: domain_edit.php?id=".$domain_uuid);
 				exit;
 			}
 
+		//copy domain settings
+			if ($action == 'copy' && permission_exists('domain_setting_add')) {
+				$target_domain_uuid = check_str($_POST["target_domain_uuid"]);
+
+				if ($target_domain_uuid != '' && sizeof($domain_setting_uuids) > 0) {
+					$settings_copied = 0;
+					foreach ($domain_setting_uuids as $domain_setting_uuid) {
+
+						// get default setting from db
+						$sql = "select * from v_domain_settings ";
+						$sql .= "where domain_setting_uuid = '".$domain_setting_uuid."' ";
+						$prep_statement = $db->prepare(check_sql($sql));
+						$prep_statement->execute();
+						$result = $prep_statement->fetchAll(PDO::FETCH_NAMED);
+						foreach ($result as &$row) {
+							$domain_setting_uuid = $row["default_setting_uuid"];
+							$domain_setting_category = $row["default_setting_category"];
+							$domain_setting_subcategory = $row["default_setting_subcategory"];
+							$domain_setting_name = $row["default_setting_name"];
+							$domain_setting_value = $row["default_setting_value"];
+							$domain_setting_order = $row["default_setting_order"];
+							$domain_setting_enabled = $row["default_setting_enabled"];
+							$domain_setting_description = $row["default_setting_description"];
+						}
+						unset ($prep_statement);
+
+						//set a random password for http_auth_password
+						if ($domain_setting_subcategory == "http_auth_password") {
+							$domain_setting_value = generate_password();
+						}
+
+						// check if exists
+						$sql = "select domain_setting_uuid from v_domain_settings ";
+						$sql .= "where domain_uuid = '".$target_domain_uuid."' ";
+						$sql .= "and domain_setting_category = '".$domain_setting_category."' ";
+						$sql .= "and domain_setting_subcategory = '".$domain_setting_subcategory."' ";
+						$sql .= "and domain_setting_name = '".$domain_setting_name."' ";
+						$sql .= "and domain_setting_name <> 'array' ";
+						$prep_statement = $db->prepare(check_sql($sql));
+						$prep_statement->execute();
+						$result = $prep_statement->fetchAll(PDO::FETCH_NAMED);
+						if (sizeof($result) > 0) {
+							foreach ($result as &$row) {
+								$target_domain_setting_uuid = $row["domain_setting_uuid"];
+								break;
+							}
+							$action = "update";
+						}
+						else {
+							$action = "add";
+							$target_domain_setting_uuid = uuid();
+						}
+						unset ($prep_statement);
+
+						// fix null
+						$domain_setting_order = ($domain_setting_order != '') ? $domain_setting_order : 'null';
+
+						//prepare the array
+						$array['domain_settings'][$x]['domain_uuid'] = $target_domain_uuid;
+						$array['domain_settings'][$x]['domain_setting_uuid'] = $target_domain_setting_uuid;
+						$array['domain_settings'][$x]['default_setting_category'] = $default_setting_category;
+						$array['domain_settings'][$x]['domain_setting_uuid'] = $default_setting_subcategory;
+						$array['domain_settings'][$x]['domain_setting_uuid'] = $default_setting_name;
+						$array['domain_settings'][$x]['domain_setting_uuid'] = $default_setting_value;
+						$array['domain_settings'][$x]['domain_setting_uuid'] = $default_setting_order;
+						$array['domain_settings'][$x]['domain_setting_uuid'] = $default_setting_enabled;
+						$array['domain_settings'][$x]['domain_setting_uuid'] = $default_setting_description;
+						$x++;
+
+					} // foreach
+
+					//save to the data
+					$database = new database;
+					$database->app_name = 'domain_settings';
+					$database->app_uuid = 'b31e723a-bf70-670c-a49b-470d2a232f71';
+					//if (strlen($stream_uuid) > 0) {
+					//	$database->uuid($stream_uuid);
+					//}
+					$database->save($array);
+					$message = $database->message;
+
+					//debug info
+					//echo "<pre>";
+					//print_r($message);
+					//echo "</pre>";
+					//exit;
+
+					// set message
+					$_SESSION["message"] = $text['message-copy'].": ".escape($settings_copied);
+				}
+				else {
+					// set message
+					message::add($text['message-copy_failed']);
+				}
+	
+				header("Location: default_settings.php".(($search != '') ? "?search=".escape($search) : null));
+				exit;
+			}
+
 		//delete domain settings
 			if ($action == 'delete' && permission_exists('domain_setting_delete')) {
 				//add multi-lingual support
@@ -79,7 +178,7 @@
 				}
 				else {
 					// set message
-					messages::add($text['message-delete_failed'], 'negative');
+					message::add($text['message-delete_failed'], 'negative');
 				}
 
 				header("Location: domain_edit.php?id=".escape($_REQUEST["domain_uuid"]));

+ 3 - 2
core/domain_settings/domains.php

@@ -143,9 +143,10 @@
 //get the domains
 	$sql = "select * from v_domains ";
 	if (strlen($search) > 0) {
+		$search = strtolower($search);
 		$sql .= "where (";
-		$sql .= "	domain_name like '%".$search."%' ";
-		$sql .= "	or domain_description like '%".$search."%' ";
+		$sql .= "	lower(domain_name) like '%".$search."%' ";
+		$sql .= "	or lower(domain_description) like '%".$search."%' ";
 		$sql .= ") ";
 	}
 	if (strlen($order_by) == 0) {

+ 3 - 76
core/groups/app_config.php

@@ -66,23 +66,6 @@
 		$apps[$x]['permissions'][$y]['name'] = "group_permissions";
 		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
 		$y++;
-		$apps[$x]['permissions'][$y]['name'] = "group_user_view";
-		$apps[$x]['permissions'][$y]['menu']['uuid'] = "3b4acc6d-827b-f537-bf21-0093d94ffec7";
-		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
-		$apps[$x]['permissions'][$y]['groups'][] = "admin";
-		$y++;
-		$apps[$x]['permissions'][$y]['name'] = "group_user_add";
-		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
-		$apps[$x]['permissions'][$y]['groups'][] = "admin";
-		$y++;
-		$apps[$x]['permissions'][$y]['name'] = "group_user_edit";
-		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
-		$apps[$x]['permissions'][$y]['groups'][] = "admin";
-		$y++;
-		$apps[$x]['permissions'][$y]['name'] = "group_user_delete";
-		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
-		$apps[$x]['permissions'][$y]['groups'][] = "admin";
-		$y++;
 		$apps[$x]['permissions'][$y]['name'] = "group_permission_view";
 		$apps[$x]['permissions'][$y]['menu']['uuid'] = "3b4acc6d-827b-f537-bf21-0093d94ffec7";
 		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
@@ -143,64 +126,6 @@
 		$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
 		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
 
-		$y++;
-		$apps[$x]['db'][$y]['table']['name'] = "v_group_users";
-		$apps[$x]['db'][$y]['table']['parent'] = "v_groups";
-		$z=0;
-		$apps[$x]['db'][$y]['fields'][$z]['name'] = "id";
-		$apps[$x]['db'][$y]['fields'][$z]['type']['pgsql'] = "serial";
-		$apps[$x]['db'][$y]['fields'][$z]['type']['sqlite'] = "integer";
-		$apps[$x]['db'][$y]['fields'][$z]['type']['mysql'] = "INT NOT NULL AUTO_INCREMENT";
-		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
-		$apps[$x]['db'][$y]['fields'][$z]['deprecated'] = "true";
-		$z++;
-		$apps[$x]['db'][$y]['fields'][$z]['name'] = "group_user_uuid";
-		$apps[$x]['db'][$y]['fields'][$z]['type']['pgsql'] = "uuid";
-		$apps[$x]['db'][$y]['fields'][$z]['type']['sqlite'] = "text";
-		$apps[$x]['db'][$y]['fields'][$z]['type']['mysql'] = "char(36)";
-		$apps[$x]['db'][$y]['fields'][$z]['key']['type'] = "primary";
-		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
-		$z++;
-		$apps[$x]['db'][$y]['fields'][$z]['name'] = "domain_uuid";
-		$apps[$x]['db'][$y]['fields'][$z]['type']['pgsql'] = "uuid";
-		$apps[$x]['db'][$y]['fields'][$z]['type']['sqlite'] = "text";
-		$apps[$x]['db'][$y]['fields'][$z]['type']['mysql'] = "char(36)";
-		$apps[$x]['db'][$y]['fields'][$z]['key']['type'] = "foreign";
-		$apps[$x]['db'][$y]['fields'][$z]['key']['reference']['table'] = "v_domains";
-		$apps[$x]['db'][$y]['fields'][$z]['key']['reference']['field'] = "domain_uuid";
-		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
-		$z++;
-		$apps[$x]['db'][$y]['fields'][$z]['name'] = "v_id";
-		$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
-		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
-		$apps[$x]['db'][$y]['fields'][$z]['deprecated'] = "true";
-		$z++;
-		$apps[$x]['db'][$y]['fields'][$z]['name']['text'] = "group_name";
-		$apps[$x]['db'][$y]['fields'][$z]['name']['deprecated'] = "groupid";
-		$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
-		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
-		$z++;
-		$apps[$x]['db'][$y]['fields'][$z]['name'] = "group_uuid";
-		$apps[$x]['db'][$y]['fields'][$z]['type']['pgsql'] = "uuid";
-		$apps[$x]['db'][$y]['fields'][$z]['type']['sqlite'] = "text";
-		$apps[$x]['db'][$y]['fields'][$z]['type']['mysql'] = "char(36)";
-		$apps[$x]['db'][$y]['fields'][$z]['key']['type'] = "foreign";
-		$apps[$x]['db'][$y]['fields'][$z]['key']['reference']['table'] = "v_groups";
-		$apps[$x]['db'][$y]['fields'][$z]['key']['reference']['field'] = "group_uuid";
-		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
-		$z++;
-		$apps[$x]['db'][$y]['fields'][$z]['name'] = "username";
-		$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
-		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
-		$apps[$x]['db'][$y]['fields'][$z]['deprecated'] = "true";
-		$z++;
-		$apps[$x]['db'][$y]['fields'][$z]['name'] = "user_uuid";
-		$apps[$x]['db'][$y]['fields'][$z]['type']['pgsql'] = "uuid";
-		$apps[$x]['db'][$y]['fields'][$z]['type']['sqlite'] = "text";
-		$apps[$x]['db'][$y]['fields'][$z]['type']['mysql'] = "char(36)";
-		$apps[$x]['db'][$y]['fields'][$z]['key']['type'] = "foreign";
-		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
-
 		$y++;
 		$apps[$x]['db'][$y]['table']['name'] = "v_group_permissions";
 		$apps[$x]['db'][$y]['table']['parent'] = "v_groups";
@@ -248,6 +173,8 @@
 		$apps[$x]['db'][$y]['fields'][$z]['type']['sqlite'] = "text";
 		$apps[$x]['db'][$y]['fields'][$z]['type']['mysql'] = "char(36)";
 		$apps[$x]['db'][$y]['fields'][$z]['key']['type'] = "foreign";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['reference']['table'] = "v_groups";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['reference']['field'] = "group_uuid";
 		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
 
-?>
+?>

+ 4 - 4
core/groups/app_defaults.php

@@ -31,7 +31,7 @@ if ($domains_processed == 1) {
 		$group->defaults();
 
 	//find rows that have a null group_uuid and set the correct group_uuid
-		$sql = "select * from v_group_users ";
+		$sql = "select * from v_user_groups ";
 		$sql .= "where group_uuid is null; ";
 		$prep_statement = $db->prepare(check_sql($sql));
 		if ($prep_statement) {
@@ -49,9 +49,9 @@ if ($domains_processed == 1) {
 						unset ($prep_statement_sub);
 						$group_uuid = $sub_result['group_uuid'];
 					//set the group_uuid
-						$sql = "update v_group_users set ";
+						$sql = "update v_user_groups set ";
 						$sql .= "group_uuid = '".$group_uuid."' ";
-						$sql .= "where group_user_uuid = '".$row['group_user_uuid']."'; ";
+						$sql .= "where user_group_uuid = '".$row['user_group_uuid']."'; ";
 						$db->exec($sql);
 						unset($sql);
 				}
@@ -62,4 +62,4 @@ if ($domains_processed == 1) {
 
 }
 
-?>
+?>

+ 8 - 8
core/groups/group_permissions.php

@@ -314,7 +314,7 @@
 				}
 			}
 
-		messages::add($text['message-update']);
+		message::add($text['message-update']);
 		header("Location: groups.php");
 		return;
 	}
@@ -328,7 +328,7 @@
 	echo "		if (new_group_name != null) {\n";
 	echo "			new_group_desc = prompt('".$text['message-new_group_description']."');\n";
 	echo "			if (new_group_desc != null) {\n";
-	echo "				window.location = 'permissions_copy.php?group_name=".$group_name."&new_group_name=' + new_group_name + '&new_group_desc=' + new_group_desc;\n";
+	echo "				window.location = 'permissions_copy.php?group_name=".escape($group_name)."&new_group_name=' + new_group_name + '&new_group_desc=' + new_group_desc;\n";
 	echo "			}\n";
 	echo "		}\n";
 	echo "	}\n";
@@ -352,11 +352,11 @@
 
 //show the content
 	echo "<form method='post' name='frm' action=''>\n";
-	echo "<input type='hidden' name='domain_uuid' value='".$domain_uuid."'>\n";
+	echo "<input type='hidden' name='domain_uuid' value='".escape($domain_uuid)."'>\n";
 	echo "<table cellpadding='0' cellspacing='0' width='100%' border='0'>\n";
 	echo "	<tr>\n";
 	echo "		<td width='50%' align=\"left\" nowrap=\"nowrap\" valign='top'>";
-	echo "			<b>".$text['header-group_permissions'].$group_name."</b>";
+	echo "			<b>".$text['header-group_permissions'].escape($group_name)."</b>";
 	echo "			<br><br>";
 	echo "		</td>\n";
 	echo "		<td width='50%' align=\"right\" valign='top'>\n";
@@ -404,9 +404,9 @@
 			foreach ($app['permissions'] as $permission_index => $row) {
 				$checked = ($permissions_db_checklist[$row['name']] == "true") ? "checked='checked'" : null;
 				echo "<tr id='permission_".$row['name']."'>\n";
-				echo "	<td valign='top' class='".$row_style[$c]."' style='text-align: center; padding: 3px 0px 0px 0px;'><input type='checkbox' name='permissions_form[]' id='perm_".$app_index."_".$permission_index."' ".$checked." value='".$row['name']."'></td>\n";
-				echo "	<td valign='top' nowrap='nowrap' class='".$row_style[$c]."' onclick=\"(document.getElementById('perm_".$app_index."_".$permission_index."').checked) ? document.getElementById('perm_".$app_index."_".$permission_index."').checked = false : document.getElementById('perm_".$app_index."_".$permission_index."').checked = true;\">".$row['name']."</td>\n";
-				echo "	<td valign='top' class='row_stylebg' onclick=\"(document.getElementById('perm_".$app_index."_".$permission_index."').checked) ? document.getElementById('perm_".$app_index."_".$permission_index."').checked = false : document.getElementById('perm_".$app_index."_".$permission_index."').checked = true;\">".$row['description']."&nbsp;</td>\n";
+				echo "	<td valign='top' class='".$row_style[$c]."' style='text-align: center; padding: 3px 0px 0px 0px;'><input type='checkbox' name='permissions_form[]' id='perm_".$app_index."_".$permission_index."' ".$checked." value='".escape($row['name'])."'></td>\n";
+				echo "	<td valign='top' nowrap='nowrap' class='".$row_style[$c]."' onclick=\"(document.getElementById('perm_".$app_index."_".$permission_index."').checked) ? document.getElementById('perm_".$app_index."_".$permission_index."').checked = false : document.getElementById('perm_".$app_index."_".$permission_index."').checked = true;\">".escape($row['name'])."</td>\n";
+				echo "	<td valign='top' class='row_stylebg' onclick=\"(document.getElementById('perm_".$app_index."_".$permission_index."').checked) ? document.getElementById('perm_".$app_index."_".$permission_index."').checked = false : document.getElementById('perm_".$app_index."_".$permission_index."').checked = true;\">".escape($row['description'])."&nbsp;</td>\n";
 				echo "</tr>\n";
 				$c = ($c == 0) ? 1 : 0;
 
@@ -487,4 +487,4 @@
 //show the footer
 	require_once "resources/footer.php";
 
-?>
+?>

+ 2 - 2
core/groups/groupadd.php

@@ -95,11 +95,11 @@
 					// $info[2] is the driver specific error string
 				}
 
-				messages::add($text['message-add']);
+				message::add($text['message-add']);
 				header("Location: groups.php");
 			}
 			else {
-				messages::add($text['message-group_exists'], 'negative');
+				message::add($text['message-group_exists'], 'negative');
 				header("Location: groupadd.php");
 			}
 

+ 4 - 4
core/groups/groupdelete.php

@@ -62,8 +62,8 @@
 			}
 			unset ($prep_statement);
 
-		//delete the group users
-			$sql = "delete from v_group_users ";
+		//delete the user groups
+			$sql = "delete from v_user_groups ";
 			$sql .= "where group_uuid = '".$group_uuid."' ";
 			if (!$db->exec($sql)) {
 				$error = $db->errorInfo();
@@ -92,7 +92,7 @@
 	}
 
 //redirect the user
-	messages::add($text['message-delete']);
+	message::add($text['message-delete']);
 	header("Location: groups.php");
 
-?>
+?>

+ 17 - 17
core/groups/groupedit.php

@@ -85,7 +85,7 @@
 				//group changed from global to domain-specific
 				if ($domain_uuid_previous == '' && $domain_uuid != '') {
 					//remove any users assigned to the group from the old domain
-						$sql = "delete from v_group_users where group_uuid = '".$group_uuid."' and domain_uuid <> '".$domain_uuid."' ";
+						$sql = "delete from v_user_groups where group_uuid = '".$group_uuid."' and domain_uuid <> '".$domain_uuid."' ";
 						if (!$db->exec(check_sql($sql))) {
 							$error = $db->errorInfo();
 							//echo "<pre>".print_r($error, true)."</pre>"; exit;
@@ -99,7 +99,7 @@
 					//change group name
 						if ($group_name != $group_name_previous && $group_name != '') {
 							//change group name in group users
-								$sql = "update v_group_users set group_name = '".$group_name."' where group_uuid = '".$group_uuid."' and group_name = '".$group_name_previous."' ";
+								$sql = "update v_user_groups set group_name = '".$group_name."' where group_uuid = '".$group_uuid."' and group_name = '".$group_name_previous."' ";
 								if (!$db->exec(check_sql($sql))) {
 									$error = $db->errorInfo();
 									//echo "<pre>".print_r($error, true)."</pre>"; exit;
@@ -116,7 +116,7 @@
 				//group changed from one domain to another
 				else if ($domain_uuid_previous != '' && $domain_uuid != '' && $domain_uuid_previous != $domain_uuid) {
 					//remove any users assigned to the group from the old domain
-						$sql = "delete from v_group_users where group_uuid = '".$group_uuid."' and domain_uuid = '".$domain_uuid_previous."' ";
+						$sql = "delete from v_user_groups where group_uuid = '".$group_uuid."' and domain_uuid = '".$domain_uuid_previous."' ";
 						if (!$db->exec(check_sql($sql))) {
 							$error = $db->errorInfo();
 							//echo "<pre>".print_r($error, true)."</pre>"; exit;
@@ -130,7 +130,7 @@
 					//change group name
 						if ($group_name != $group_name_previous && $group_name != '') {
 							//change group name in group users
-								$sql = "update v_group_users set group_name = '".$group_name."' where group_uuid = '".$group_uuid."' and group_name = '".$group_name_previous."' ";
+								$sql = "update v_user_groups set group_name = '".$group_name."' where group_uuid = '".$group_uuid."' and group_name = '".$group_name_previous."' ";
 								if (!$db->exec(check_sql($sql))) {
 									$error = $db->errorInfo();
 									//echo "<pre>".print_r($error, true)."</pre>"; exit;
@@ -149,7 +149,7 @@
 					//change group name
 						if ($group_name != $group_name_previous && $group_name != '') {
 							//change group name in group users
-								$sql = "update v_group_users set group_name = '".$group_name."' where group_uuid = '".$group_uuid."' and group_name = '".$group_name_previous."' ";
+								$sql = "update v_user_groups set group_name = '".$group_name."' where group_uuid = '".$group_uuid."' and group_name = '".$group_name_previous."' ";
 								if (!$db->exec(check_sql($sql))) {
 									$error = $db->errorInfo();
 									//echo "<pre>".print_r($error, true)."</pre>"; exit;
@@ -174,7 +174,7 @@
 					//change group name
 						if ($group_name != $group_name_previous && $group_name != '') {
 							//change group name in group users
-								$sql = "update v_group_users set group_name = '".$group_name."' where group_uuid = '".$group_uuid."' and group_name = '".$group_name_previous."' ";
+								$sql = "update v_user_groups set group_name = '".$group_name."' where group_uuid = '".$group_uuid."' and group_name = '".$group_name_previous."' ";
 								if (!$db->exec(check_sql($sql))) {
 									$error = $db->errorInfo();
 									//echo "<pre>".print_r($error, true)."</pre>"; exit;
@@ -188,11 +188,11 @@
 						}
 				}
 
-				messages::add($text['message-update']);
+				message::add($text['message-update']);
 				header("Location: groups.php");
 			}
 			else {
-				messages::add($text['message-group_exists'], 'negative');
+				message::add($text['message-group_exists'], 'negative');
 				header("Location: groupedit.php?id=".$group_uuid);
 			}
 
@@ -228,7 +228,7 @@
 	echo "		if (new_group_name != null) {\n";
 	echo "			new_group_desc = prompt('".$text['message-new_group_description']."');\n";
 	echo "			if (new_group_desc != null) {\n";
-	echo "				window.location = 'permissions_copy.php?group_name=".$group_name."&new_group_name=' + new_group_name + '&new_group_desc=' + new_group_desc;\n";
+	echo "				window.location = 'permissions_copy.php?group_name=".escape($group_name)."&new_group_name=' + new_group_name + '&new_group_desc=' + new_group_desc;\n";
 	echo "			}\n";
 	echo "		}\n";
 	echo "	}\n";
@@ -236,7 +236,7 @@
 
 //show the content
 	echo "<form name='login' method='post' action=''>\n";
-	echo "<input type='hidden' name='group_uuid' value='".$group_uuid."'>\n";
+	echo "<input type='hidden' name='group_uuid' value='".escape($group_uuid)."'>\n";
 
 	echo "<table width='100%' cellpadding='0' cellspacing='0'>\n";
 	echo "	<tr>\n";
@@ -260,8 +260,8 @@
 	echo 	$text['label-group_name']."\n";
 	echo "</td>\n";
 	echo "<td width='70%' align='left' class='vtable'>\n";
-	echo "	<input type='hidden' name='group_name_previous' value=\"".$group_name."\">\n";
-	echo "  <input type='text' class='formfld' name='group_name' value=\"".$group_name."\">\n";
+	echo "	<input type='hidden' name='group_name_previous' value=\"".escape($group_name)."\">\n";
+	echo "  <input type='text' class='formfld' name='group_name' value=\"".escape($group_name)."\">\n";
 	echo "</td>\n";
 	echo "</tr>\n";
 
@@ -271,11 +271,11 @@
 		echo "	".$text['label-domain']."\n";
 		echo "</td>\n";
 		echo "<td class='vtable' align='left'>\n";
-		echo "	<input type='hidden' name='domain_uuid_previous' value='".$domain_uuid."'>\n";
+		echo "	<input type='hidden' name='domain_uuid_previous' value='".escape($domain_uuid)."'>\n";
 		echo "	<select class='formfld' name='domain_uuid'>\n";
 		echo "	<option value='' ".((strlen($domain_uuid) == 0) ? "selected='selected'" : null).">".$text['option-global']."</option>\n";
 		foreach ($_SESSION['domains'] as $row) {
-			echo "<option value='".$row['domain_uuid']."' ".(($row['domain_uuid'] == $domain_uuid) ? "selected='selected'" : null).">".$row['domain_name']."</option>\n";
+			echo "<option value='".escape($row['domain_uuid'])."' ".(($row['domain_uuid'] == $domain_uuid) ? "selected='selected'" : null).">".escape($row['domain_name'])."</option>\n";
 		}
 		echo "	</select>\n";
 		echo "	<br />\n";
@@ -284,7 +284,7 @@
 		echo "</tr>\n";
 	}
 	else {
-		echo "<input type='hidden' name='domain_uuid' value='".$domain_uuid."'>";
+		echo "<input type='hidden' name='domain_uuid' value='".escape($domain_uuid)."'>";
 	}
 
 	echo "<tr>\n";
@@ -292,7 +292,7 @@
 	echo 	$text['label-group_description']."\n";
 	echo "</td>\n";
 	echo "<td align='left' class='vtable' valign='top'>\n";
-	echo "	<textarea name='group_description' class='formfld' style='width: 250px; height: 50px;'>".$group_description."</textarea>\n";
+	echo "	<textarea name='group_description' class='formfld' style='width: 250px; height: 50px;'>".escape($group_description)."</textarea>\n";
 	echo "</td>\n";
 	echo "</tr>\n";
 
@@ -310,4 +310,4 @@
 //include the footer
 	include "resources/footer.php";
 
-?>
+?>

+ 4 - 4
core/groups/groupmemberadd.php

@@ -52,9 +52,9 @@
 
 //add the user to the group
 	if (is_uuid($user_uuid) && is_uuid($group_uuid) && strlen($group_name) > 0) {
-		$sql = "insert into v_group_users ";
+		$sql = "insert into v_user_groups ";
 		$sql .= "(";
-		$sql .= "group_user_uuid, ";
+		$sql .= "user_group_uuid, ";
 		$sql .= "domain_uuid, ";
 		$sql .= "group_uuid, ";
 		$sql .= "group_name, ";
@@ -81,7 +81,7 @@
 	}
 
 //redirect the user
-	messages::add($text['message-update']);
+	message::add($text['message-update']);
 	header("Location: groupmembers.php?group_uuid=".$group_uuid."&group_name=".$group_name);
 
-?>
+?>

+ 3 - 3
core/groups/groupmemberdelete.php

@@ -50,7 +50,7 @@
 	$group_uuid = check_str($_GET["group_uuid"]);
 
 //delete the group membership
-	$sql_delete = "delete from v_group_users ";
+	$sql_delete = "delete from v_user_groups ";
 	$sql_delete .= "where user_uuid = '".$user_uuid."' ";
 	$sql_delete .= "and group_uuid = '".$group_uuid."' ";
 	if (!$db->exec($sql_delete)) {
@@ -64,7 +64,7 @@
 	}
 
 //redirect the user
-	messages::add($text['message-delete']);
+	message::add($text['message-delete']);
 	header("Location: groupmembers.php?group_uuid=".$group_uuid."&group_name=".$group_name);
 
-?>
+?>

+ 12 - 12
core/groups/groupmembers.php

@@ -65,7 +65,7 @@
 //define the if group members function
 	function is_group_member($group_uuid, $user_uuid) {
 		global $db, $domain_uuid;
-		$sql = "select * from v_group_users ";
+		$sql = "select * from v_user_groups ";
 		$sql .= "where user_uuid = '".$user_uuid."' ";
 		$sql .= "and group_uuid = '".$group_uuid."' ";
 		$sql .= "and domain_uuid = '".(($domain_uuid != '') ? $domain_uuid : $_SESSION['domain_uuid'])."' ";
@@ -92,17 +92,17 @@
 	}
 
 //get the groups users
-	$sql = "select u.user_uuid, u.username, gu.group_user_uuid, gu.domain_uuid, gu.group_uuid ";
-	$sql .= "from v_group_users as gu, v_users as u, v_domains as d ";
-	$sql .= "where gu.user_uuid = u.user_uuid ";
-	$sql .= "and gu.domain_uuid = d.domain_uuid ";
+	$sql = "select u.user_uuid, u.username, ug.user_group_uuid, ug.domain_uuid, ug.group_uuid ";
+	$sql .= "from v_user_groups as ug, v_users as u, v_domains as d ";
+	$sql .= "where ug.user_uuid = u.user_uuid ";
+	$sql .= "and ug.domain_uuid = d.domain_uuid ";
 	if ($domain_uuid != '') {
-		$sql .= "and gu.domain_uuid = '".$domain_uuid."' ";
+		$sql .= "and ug.domain_uuid = '".$domain_uuid."' ";
 	}
 	if (!permission_exists('user_all')) {
 		$sql .= "and u.domain_uuid = '".$_SESSION['domain_uuid']."' ";
 	}
-	$sql .= "and gu.group_uuid = '".$group_uuid."' ";
+	$sql .= "and ug.group_uuid = '".$group_uuid."' ";
 	$sql .= "order by d.domain_name asc, u.username asc ";
 	$prep_statement = $db->prepare(check_sql($sql));
 	$prep_statement->execute();
@@ -159,16 +159,15 @@
 
 	$count = 0;
 	foreach ($result as &$row) {
-		$group_user_uuid = $row["group_user_uuid"];
 		$username = $row["username"];
 		$user_uuid = $row["user_uuid"];
 		$domain_uuid = $row["domain_uuid"];
 		$group_uuid = $row["group_uuid"];
 		$echo .= "<tr>";
 		if (permission_exists('user_all')) {
-			$echo .= "<td align='left' class='".$row_style[$c]."' nowrap>".$_SESSION['domains'][$domain_uuid]['domain_name']."</td>\n";
+			$echo .= "<td align='left' class='".$row_style[$c]."' nowrap='nowrap'>".$_SESSION['domains'][$domain_uuid]['domain_name']."</td>\n";
 		}
-		$echo .= "<td align='left' class='".$row_style[$c]."' nowrap>".$username."</td>\n";
+		$echo .= "<td align='left' class='".$row_style[$c]."' nowrap='nowrap'>".$username."</td>\n";
 		$echo .= "<td class='list_control_icons' style='width: 25px;'>";
 		if (permission_exists('group_member_delete')) {
 			$echo .= "<a href='groupmemberdelete.php?user_uuid=".$user_uuid."&group_name=".$group_name."&group_uuid=".$group_uuid."' onclick=\"return confirm('".$text['confirm-delete']."')\" alt='".$text['button-delete']."'>".$v_link_label_delete."</a>";
@@ -178,7 +177,7 @@
 
 		$c = ($c) ? 0 : 1;
 
-		$group_users[] = $row["user_uuid"];
+		$user_groups[] = $row["user_uuid"];
 		$count++;
 	}
 
@@ -188,4 +187,5 @@
 
 //include the footer
 	require_once "resources/footer.php";
-?>
+
+?>

+ 2 - 2
core/groups/groups.php

@@ -62,7 +62,7 @@
 		$db->exec(check_sql($sql));
 		unset($sql);
 
-		messages::add($text['message-update']);
+		message::add($text['message-update']);
 	}
 
 //get the groups
@@ -81,7 +81,7 @@
 
 
 //get group counts
-	$sql = "select group_uuid, count(user_uuid) as group_count from v_group_users ";
+	$sql = "select group_uuid, count(user_uuid) as group_count from v_user_groups ";
 	if (!permission_exists('user_all')) {
 		$sql .= "where domain_uuid = '".$_SESSION['domain_uuid']."' ";
 	}

+ 1 - 1
core/groups/permissions_copy.php

@@ -115,7 +115,7 @@
 			unset ($prep_statement);
 
 		//redirect the user
-			messages::add($text['message-copy']);
+			message::add($text['message-copy']);
 	}
 
 //redirect

+ 1 - 1
core/groups/permissions_default.php

@@ -51,7 +51,7 @@
 //redirect the users
 	if (!$included) {
 		//show a message to the user
-		messages::add($text['message-restore']);
+		message::add($text['message-restore']);
 		header("Location: groups.php");
 		return;
 	}

+ 1 - 1
core/install/install.php

@@ -28,7 +28,7 @@
 	require_once "root.php";
 	require_once "resources/functions.php";
 	require_once "resources/classes/text.php";
-	require_once "resources/classes/messages.php";
+	require_once "resources/classes/message.php";
 
 //start a php session
 	if (!isset($_SESSION)) { session_start(); }

+ 4 - 4
core/install/resources/classes/install_fusionpbx.php

@@ -724,7 +724,7 @@ include "root.php";
 				unset($sql);
 			}
 			$this->write_progress("\tChecking if superuser is in the correct group");
-			$sql = "select count(*) as count from v_group_users ";
+			$sql = "select count(*) as count from v_user_groups ";
 			$sql .= "where domain_uuid = '".$this->global_settings->domain_uuid()."' ";
 			$sql .= "and user_uuid = '".$this->admin_uuid."' ";
 			$sql .= "and group_name = 'superadmin' ";
@@ -735,9 +735,9 @@ include "root.php";
 			$row = $prep_statement->fetch(PDO::FETCH_ASSOC);
 			if ($row['count'] == 0) {
 				//add the user to the superadmin group
-				$sql = "insert into v_group_users ";
+				$sql = "insert into v_user_groups ";
 				$sql .= "(";
-				$sql .= "group_user_uuid, ";
+				$sql .= "user_group_uuid, ";
 				$sql .= "domain_uuid, ";
 				$sql .= "user_uuid, ";
 				$sql .= "group_name ";
@@ -770,7 +770,7 @@ include "root.php";
 				$_SESSION['event_socket_password'] = $this->global_settings->switch_event_password();
 
 			//get the groups assigned to the user and then set the groups in $_SESSION["groups"]
-				$sql = "SELECT * FROM v_group_users ";
+				$sql = "SELECT * FROM v_user_groups ";
 				$sql .= "where domain_uuid=:domain_uuid ";
 				$sql .= "and user_uuid=:user_uuid ";
 				$prep_statement = $this->dbh->prepare(check_sql($sql));

+ 6 - 4
core/menu/app_menu.php

@@ -48,9 +48,10 @@
 	$apps[$x]['menu'][$y]['icon'] = "glyphicon-home";
 	$apps[$x]['menu'][$y]['path'] = "";
 	$apps[$x]['menu'][$y]['order'] = "5";
-	$apps[$x]['menu'][$y]['groups'][] = "user";
-	$apps[$x]['menu'][$y]['groups'][] = "admin";
 	$apps[$x]['menu'][$y]['groups'][] = "superadmin";
+	$apps[$x]['menu'][$y]['groups'][] = "admin";
+	$apps[$x]['menu'][$y]['groups'][] = "user";
+	$apps[$x]['menu'][$y]['groups'][] = "agent";
 	$y++;
 	$apps[$x]['menu'][$y]['title']['en-us'] = "Accounts";
 	$apps[$x]['menu'][$y]['title']['ar-eg'] = "";
@@ -182,8 +183,9 @@
 	$apps[$x]['menu'][$y]['category'] = 'internal';
 	$apps[$x]['menu'][$y]['icon'] = "glyphicon-log-out";
 	$apps[$x]['menu'][$y]['path'] = '/logout.php';
-	$apps[$x]['menu'][$y]['groups'][] = 'user';
-	$apps[$x]['menu'][$y]['groups'][] = 'admin';
 	$apps[$x]['menu'][$y]['groups'][] = 'superadmin';
+	$apps[$x]['menu'][$y]['groups'][] = 'admin';
+	$apps[$x]['menu'][$y]['groups'][] = 'user';
+	$apps[$x]['menu'][$y]['groups'][] = "agent";
 
 ?>

+ 6 - 6
core/menu/menu.php

@@ -110,12 +110,12 @@ else {
 		foreach($result as $row) {
 			$tr_link = "href='menu_edit.php?id=".$row['menu_uuid']."'";
 			echo "<tr ".$tr_link.">\n";
-			echo "	<td valign='top' class='".$row_style[$c]."'><a href='menu_edit.php?id=".$row['menu_uuid']."'>".$row['menu_name']."</a></td>\n";
-			echo "	<td valign='top' class='".$row_style[$c]."'>".$row['menu_language']."</td>\n";
-			echo "	<td valign='top' class='row_stylebg'>".$row['menu_description']."&nbsp;</td>\n";
+			echo "	<td valign='top' class='".$row_style[$c]."'><a href='menu_edit.php?id=".escape($row['menu_uuid'])."'>".escape($row['menu_name'])."</a></td>\n";
+			echo "	<td valign='top' class='".$row_style[$c]."'>".escape($row['menu_language'])."</td>\n";
+			echo "	<td valign='top' class='row_stylebg'>".escape($row['menu_description'])."&nbsp;</td>\n";
 			echo "	<td class='list_control_icons'>";
-			echo 		"<a href='menu_edit.php?id=".$row['menu_uuid']."' alt='".$text['button-edit']."'>$v_link_label_edit</a>";
-			echo 		"<a href='menu_delete.php?id=".$row['menu_uuid']."&menu_uuid=".$row['menu_uuid']."' alt='".$text['button-delete']."' onclick=\"return confirm('".$text['confirm-delete']."')\">$v_link_label_delete</a>";
+			echo 		"<a href='menu_edit.php?id=".escape($row['menu_uuid'])."' alt='".$text['button-edit']."'>$v_link_label_edit</a>";
+			echo 		"<a href='menu_delete.php?id=".escape($row['menu_uuid'])."&menu_uuid=".escape($row['menu_uuid'])."' alt='".$text['button-delete']."' onclick=\"return confirm('".$text['confirm-delete']."')\">$v_link_label_delete</a>";
 			echo "	</td>\n";
 			echo "</tr>\n";
 			if ($c==0) { $c=1; } else { $c=0; }
@@ -143,4 +143,4 @@ else {
 
 //include the footer
 	require_once "resources/footer.php";
-?>
+?>

+ 1 - 1
core/menu/menu_delete.php

@@ -85,7 +85,7 @@ else {
 	}
 
 //redirect the user
-	messages::add($text['message-delete']);
+	message::add($text['message-delete']);
 	header("Location: menu.php");
 	return;
 

+ 6 - 6
core/menu/menu_edit.php

@@ -112,7 +112,7 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 				$menu->restore();
 
 			//redirect the user back to the main menu
-				messages::add($text['message-add']);
+				message::add($text['message-add']);
 				header("Location: menu.php");
 				return;
 		} //if ($action == "add")
@@ -128,7 +128,7 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 				unset($sql);
 
 			//redirect the user back to the main menu
-				messages::add($text['message-update']);
+				message::add($text['message-update']);
 				header("Location: menu.php");
 				return;
 		} //if ($action == "update")
@@ -197,7 +197,7 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 	echo "	".$text['label-name']."\n";
 	echo "</td>\n";
 	echo "<td class='vtable' align='left'>\n";
-	echo "	<input class='formfld' type='text' name='menu_name' maxlength='255' value=\"$menu_name\">\n";
+	echo "	<input class='formfld' type='text' name='menu_name' maxlength='255' value=\"".escape($menu_name)."\">\n";
 	echo "<br />\n";
 	echo "\n";
 	echo $text['description-name']."</td>\n";
@@ -208,7 +208,7 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 	echo "	".$text['label-language']."\n";
 	echo "</td>\n";
 	echo "<td class='vtable' align='left'>\n";
-	echo "	<input class='formfld' type='text' name='menu_language' maxlength='255' value=\"$menu_language\">\n";
+	echo "	<input class='formfld' type='text' name='menu_language' maxlength='255' value=\"".escape($menu_language)."\">\n";
 	echo "<br />\n";
 	echo $text['description-language']."\n";
 	echo "</td>\n";
@@ -219,7 +219,7 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 	echo "	".$text['label-description']."\n";
 	echo "</td>\n";
 	echo "<td class='vtable' align='left'>\n";
-	echo "	<input class='formfld' type='text' name='menu_description' maxlength='255' value=\"$menu_description\">\n";
+	echo "	<input class='formfld' type='text' name='menu_description' maxlength='255' value=\"".escape($menu_description)."\">\n";
 	echo "<br />\n";
 	echo $text['description-description']."\n";
 	echo "</td>\n";
@@ -227,7 +227,7 @@ if (count($_POST)>0 && strlen($_POST["persistformvar"]) == 0) {
 	echo "	<tr>\n";
 	echo "		<td colspan='2' align='right'>\n";
 	if ($action == "update") {
-		echo "		<input type='hidden' name='menu_uuid' value='$menu_uuid'>\n";
+		echo "		<input type='hidden' name='menu_uuid' value='".escape($menu_uuid)."'>\n";
 	}
 	echo "			<br>";
 	echo "			<input type='submit' name='submit' class='btn' value='".$text['button-save']."'>\n";

+ 1 - 1
core/menu/menu_item_delete.php

@@ -68,7 +68,7 @@ if (count($_GET)>0) {
 		unset($sql);
 
 	//redirect the user
-		messages::add($text['message-delete']);
+		message::add($text['message-delete']);
 		header("Location: menu_edit.php?id=".$menu_uuid);
 		return;
 }

+ 17 - 17
core/menu/menu_item_edit.php

@@ -51,7 +51,7 @@ else {
 			$sql .= "where menu_item_group_uuid = '".$menu_item_group_uuid."' ";
 			$db->exec(check_sql($sql));
 		//redirect the browser
-			messages::add($text['message-delete']);
+			message::add($text['message-delete']);
 			header("Location: menu_item_edit.php?id=".$menu_uuid."&menu_item_uuid=".$menu_item_uuid."&menu_uuid=".$menu_uuid);
 			return;
 	}
@@ -280,10 +280,10 @@ else {
 
 			//set response message
 				if ($action == "add") {
-					messages::add($text['message-add']);
+					message::add($text['message-add']);
 				}
 				if ($action == "update") {
-					messages::add($text['message-update']);
+					message::add($text['message-update']);
 				}
 
 			//redirect the user
@@ -394,7 +394,7 @@ else {
 	echo "	</b>\n";
 	echo "</td>\n";
 	echo "<td width='70%' align='right' valign='top'>";
-	echo "	<input type='button' class='btn' name='' alt='".$text['button-back']."' onclick=\"window.location='menu_edit.php?id=".$menu_uuid."'\" value='".$text['button-back']."'>";
+	echo "	<input type='button' class='btn' name='' alt='".$text['button-back']."' onclick=\"window.location='menu_edit.php?id=".escape($menu_uuid)."'\" value='".$text['button-back']."'>";
 	echo "	<input type='submit' class='btn' name='submit' value='".$text['button-save']."'>\n";
 	echo "	<br><br>";
 	echo "</td>\n";
@@ -402,12 +402,12 @@ else {
 
 	echo "	<tr>";
 	echo "		<td class='vncellreq'>".$text['label-title']."</td>";
-	echo "		<td class='vtable'><input type='text' class='formfld' name='menu_item_title' value='$menu_item_title'></td>";
+	echo "		<td class='vtable'><input type='text' class='formfld' name='menu_item_title' value='".escape($menu_item_title)."'></td>";
 	echo "	</tr>";
 
 	echo "	<tr>";
 	echo "		<td class='vncellreq'>".$text['label-link']."</td>";
-	echo "		<td class='vtable'><input type='text' class='formfld' name='menu_item_link' value='$menu_item_link'></td>";
+	echo "		<td class='vtable'><input type='text' class='formfld' name='menu_item_link' value='".escape($menu_item_link)."'></td>";
 	echo "	</tr>";
 
 	echo "	<tr>";
@@ -442,7 +442,7 @@ else {
 			echo "				<option value=''></option>\n";
 			foreach ($glyphicons as $glyphicon_class => $glyphicon_name) {
 				$selected = ($menu_item_icon == $glyphicon_class) ? "selected" : null;
-				echo "			<option value='".$glyphicon_class."' ".$selected.">".$glyphicon_name."</option>\n";
+				echo "			<option value='".escape($glyphicon_class)."' ".$selected.">".escape($glyphicon_name)."</option>\n";
 			}
 			echo "			</select>\n";
 			echo "		</td>\n";
@@ -453,13 +453,13 @@ else {
 			echo "</table>\n";
 			echo "<div id='glyphicons' style='clear: both; display: none; padding-top: 10px; color: #000;'>";
 			foreach ($glyphicons as $glyphicon_class => $glyphicon_name) {
-				echo "<span class='glyphicon ".$glyphicon_class."' style='font-size: 24px; float: left; margin: 0 8px 8px 0; cursor: pointer; opacity: 0.3;' title='".$glyphicon_name."' onclick=\"$('#menu_item_icon').val('".$glyphicon_class."'); $('#glyphicons').slideUp(); $('#grid_icon').fadeIn();\" onmouseover=\"this.style.opacity='1';\" onmouseout=\"this.style.opacity='0.3';\"></span>\n";
+				echo "<span class='glyphicon ".escape($glyphicon_class)."' style='font-size: 24px; float: left; margin: 0 8px 8px 0; cursor: pointer; opacity: 0.3;' title='".escape(glyphicon_name)."' onclick=\"$('#menu_item_icon').val('".escape($glyphicon_class)."'); $('#glyphicons').slideUp(); $('#grid_icon').fadeIn();\" onmouseover=\"this.style.opacity='1';\" onmouseout=\"this.style.opacity='0.3';\"></span>\n";
 			}
 			echo "</div>";
 		}
 	}
 	else {
-		echo "		<input type='text' class='formfld' name='menu_item_icon' value='".$menu_item_icon."'>";
+		echo "		<input type='text' class='formfld' name='menu_item_icon' value='".escape($menu_item_icon)."'>";
 	}
 	echo "		</td>";
 	echo "	</tr>";
@@ -471,10 +471,10 @@ else {
 	echo "<option value=\"\"></option>\n";
 	foreach($menu_items as $field) {
 			if ($menu_item_parent_uuid == $field['menu_item_uuid']) {
-				echo "<option value='".$field['menu_item_uuid']."' selected>".$field['menu_item_title']."</option>\n";
+				echo "<option value='".escape($field['menu_item_uuid'])."' selected>".escape($field['menu_item_title'])."</option>\n";
 			}
 			else {
-				echo "<option value='".$field['menu_item_uuid']."'>".$field['menu_item_title']."</option>\n";
+				echo "<option value='".escape($field['menu_item_uuid'])."'>".escape($field['menu_item_title'])."</option>\n";
 			}
 	}
 	echo "</select>";
@@ -495,7 +495,7 @@ else {
 				echo "	</td>\n";
 				if (permission_exists('group_member_delete') || if_group("superadmin")) {
 					echo "	<td class='list_control_icons' style='width: 25px;'>";
-					echo 		"<a href='menu_item_edit.php?id=".$field['menu_uuid']."&menu_item_group_uuid=".$field['menu_item_group_uuid']."&menu_item_uuid=".$menu_item_uuid."&a=delete' alt='".$text['button-delete']."' onclick=\"return confirm('".$text['confirm-delete']."')\">".$v_link_label_delete."</a>";
+					echo 		"<a href='menu_item_edit.php?id=".escape($field['menu_uuid'])."&menu_item_group_uuid=".escape($field['menu_item_group_uuid'])."&menu_item_uuid=".escape($menu_item_uuid)."&a=delete' alt='".$text['button-delete']."' onclick=\"return confirm('".$text['confirm-delete']."')\">".$v_link_label_delete."</a>";
 					echo "	</td>";
 				}
 				echo "</tr>\n";
@@ -548,14 +548,14 @@ else {
 		if ($menu_item_parent_uuid == "") {
 			echo "	<tr>";
 			echo "		<td class='vncell'>".$text['label-menu_order']."</td>";
-			echo "		<td class='vtable'><input type='text' class='formfld' name='menu_item_order' value='$menu_item_order'></td>";
+			echo "		<td class='vtable'><input type='text' class='formfld' name='menu_item_order' value='".escape($menu_item_order)."'></td>";
 			echo "	</tr>";
 		}
 	}
 
 	echo "	<tr>";
 	echo "		<td class='vncell'>".$text['label-description']."</td>";
-	echo "		<td class='vtable'><input type='text' class='formfld' name='menu_item_description' value='$menu_item_description'></td>";
+	echo "		<td class='vtable'><input type='text' class='formfld' name='menu_item_description' value='".escape($menu_item_description)."'></td>";
 	echo "	</tr>";
 
 	if (permission_exists('menu_add') || permission_exists('menu_edit')) {
@@ -567,10 +567,10 @@ else {
 		echo "			</td>\n";
 		echo "			<td align='right'>";
 		if ($action == "update") {
-			echo "			<input type='hidden' name='menu_item_uuid' value='$menu_item_uuid'>";
+			echo "			<input type='hidden' name='menu_item_uuid' value='".escape($menu_item_uuid)."'>";
 		}
-		echo "				<input type='hidden' name='menu_uuid' value='$menu_uuid'>";
-		echo "				<input type='hidden' name='menu_item_uuid' value='$menu_item_uuid'>";
+		echo "				<input type='hidden' name='menu_uuid' value='".escape($menu_uuid)."'>";
+		echo "				<input type='hidden' name='menu_item_uuid' value='".escape($menu_item_uuid)."'>";
 		echo "				<br>";
 		echo "				<input type='submit' class='btn' name='submit' value='".$text['button-save']."'>\n";
 		echo "			</td>";

+ 1 - 1
core/menu/menu_item_move_down.php

@@ -80,7 +80,7 @@ if (count($_GET)>0) {
 	}
 
 	//redirect the user
-		messages::add($text['message-moved_down']);
+		message::add($text['message-moved_down']);
 		header("Location: menu_list.php?menu_item_id=".$menu_item_id);
 		return;
 }

+ 1 - 1
core/menu/menu_item_move_up.php

@@ -67,7 +67,7 @@ if (count($_GET)>0) {
 	}
 
 	//redirect the user
-		messages::add($text['message-moved_up']);
+		message::add($text['message-moved_up']);
 		header("Location: menu_list.php?menu_item_id=".$menu_item_id);
 		return;
 }

+ 1 - 1
core/menu/menu_restore_default.php

@@ -66,7 +66,7 @@
 //redirect
 	if (!$included) {
 		//show a message to the user
-		messages::add($text['message-restore']);
+		message::add($text['message-restore']);
 		header("Location: ".PROJECT_PATH."/core/menu/menu_edit.php?id=".$menu_uuid);
 		return;
 	}

+ 6 - 6
core/upgrade/index.php

@@ -77,10 +77,10 @@
 			}
 			chdir($cwd);
 			if ($update_failed) {
-				messages::add($text['message-upgrade_source_failed'], 'negative', $message_timeout);
+				message::add($text['message-upgrade_source_failed'], 'negative', $message_timeout);
 			}
 			else {
-				messages::add($text['message-upgrade_source'], null, $message_timeout);
+				message::add($text['message-upgrade_source'], null, $message_timeout);
 			}
 		}
 
@@ -90,7 +90,7 @@
 			require_once "resources/classes/schema.php";
 			$obj = new schema();
 			$_SESSION["response"]["schema"] = $obj->schema("html");
-			messages::add($text['message-upgrade_schema'], null, $message_timeout);
+			message::add($text['message-upgrade_schema'], null, $message_timeout);
 		}
 
 		// process the apps defaults
@@ -98,7 +98,7 @@
 			require_once "resources/classes/domains.php";
 			$domain = new domains;
 			$domain->upgrade();
-			messages::add($text['message-upgrade_apps'], null, $message_timeout);
+			message::add($text['message-upgrade_apps'], null, $message_timeout);
 		}
 
 		// restore defaults of the selected menu
@@ -109,14 +109,14 @@
 			$included = true;
 			require_once("core/menu/menu_restore_default.php");
 			unset($sel_menu);
-			messages::add($text['message-upgrade_menu'], null, $message_timeout);
+			message::add($text['message-upgrade_menu'], null, $message_timeout);
 		}
 
 		// restore default permissions
 		if ($do["permissions"] && permission_exists("group_edit")) {
 			$included = true;
 			require_once("core/groups/permissions_default.php");
-			messages::add($text['message-upgrade_permissions'], null, $message_timeout);
+			message::add($text['message-upgrade_permissions'], null, $message_timeout);
 		}
 
 		header("Location: ".PROJECT_PATH."/core/upgrade/index.php");

+ 0 - 20
core/user_settings/app_languages.php

@@ -761,26 +761,6 @@ $text['label-reset_password']['ru-ru'] = "Сброс пароля";
 $text['label-reset_password']['sv-se'] = "Återställ Lösenord";
 $text['label-reset_password']['uk-ua'] = "Скинути пароль";
 
-$text['label-reset_link']['en-us'] = "Password Reset Link";
-$text['label-reset_link']['ar-eg'] = " رابط اعادة تعيين كلمة السر";
-$text['label-reset_link']['de-at'] = "Link zum Zurücksetzen des Passworts"; //copied from de-de
-$text['label-reset_link']['de-ch'] = "Link zum Zurücksetzen des Passworts"; //copied from de-de
-$text['label-reset_link']['de-de'] = "Link zum Zurücksetzen des Passworts";
-$text['label-reset_link']['es-cl'] = "Password Reset Enlace";
-$text['label-reset_link']['es-mx'] = "Password Reset Enlace"; //copied from es-cl
-$text['label-reset_link']['fr-ca'] = "Lien de réinitialisation du mot de passe"; //copied from fr-fr
-$text['label-reset_link']['fr-fr'] = "Lien de réinitialisation du mot de passe";
-$text['label-reset_link']['he-il'] = "קישור לאיפוס סיסמה";
-$text['label-reset_link']['it-it'] = "Link per il Reset della Password";
-$text['label-reset_link']['nl-nl'] = "";
-$text['label-reset_link']['pl-pl'] = "Link do resetowania hasla";
-$text['label-reset_link']['pt-br'] = "Link para redefinir senha";
-$text['label-reset_link']['pt-pt'] = "Password Reset Link";
-$text['label-reset_link']['ro-ro'] = "Link resetare parolă";
-$text['label-reset_link']['ru-ru'] = "Ссылка для сброса пароля";
-$text['label-reset_link']['sv-se'] = "Länk för Återställning av Lösenord";
-$text['label-reset_link']['uk-ua'] = "Посилання на скидання пароля";
-
 $text['label-repeat_password']['en-us'] = "Repeat Password";
 $text['label-repeat_password']['ar-eg'] = "تاكيد كلمة السر";
 $text['label-repeat_password']['de-at'] = "Passwort wiederholen"; //copied from de-de

+ 4 - 3
core/user_settings/app_menu.php

@@ -23,8 +23,9 @@
 	$apps[$x]['menu'][$y]['parent_uuid'] = "02194288-6d56-6d3e-0b1a-d53a2bc10788";
 	$apps[$x]['menu'][$y]['category'] = "internal";
 	$apps[$x]['menu'][$y]['path'] = "/core/user_settings/user_dashboard.php";
-	$apps[$x]['menu'][$y]['groups'][] = "user";
-	$apps[$x]['menu'][$y]['groups'][] = "admin";
 	$apps[$x]['menu'][$y]['groups'][] = "superadmin";
+	$apps[$x]['menu'][$y]['groups'][] = "admin";
+	$apps[$x]['menu'][$y]['groups'][] = "user";
+	$apps[$x]['menu'][$y]['groups'][] = "agent";
 
-?>
+?>

+ 4 - 2
core/user_settings/user_dashboard.php

@@ -72,7 +72,9 @@
 	echo "			<b>".$text['header-user_dashboard']."</b><br />";
 	echo "		</td>\n";
 	echo "		<td valign='top' style='text-align: right; white-space: nowrap;'>\n";
-	echo "			".$text['label-welcome']." <a href='".PROJECT_PATH."/core/users/user_edit.php?id=user'>".$_SESSION["username"]."</a>";
+	if ($_SESSION['theme']['menu_style']['text'] != 'side') {
+		echo "		".$text['label-welcome']." <a href='".PROJECT_PATH."/core/users/user_edit.php?id=user'>".$_SESSION["username"]."</a>";
+	}
 	echo "		</td>\n";
 	echo "	</tr>\n";
 	echo "	<tr>\n";
@@ -428,7 +430,7 @@
 						direction = 'inbound'
 						or direction = 'local'
 					)
-					and bridge_uuid is null
+					and (missed_call = true or bridge_uuid is null)
 					and destination_number in ('".implode("','",$assigned_extensions)."')
 					and (";
 					$x = 0;

+ 93 - 1
core/users/app_config.php

@@ -47,12 +47,36 @@
 		$apps[$x]['permissions'][$y]['groups'][] = "admin";
 		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
 		$y++;
+		$apps[$x]['permissions'][$y]['name'] = "user_groups";
+		$apps[$x]['permissions'][$y]['groups'][] = "admin";
+		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
+		$y++;
 		$apps[$x]['permissions'][$y]['name'] = "user_domain";
 		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
 		$y++;
 		$apps[$x]['permissions'][$y]['name'] = "user_all";
 		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
 		$y++;
+		$apps[$x]['permissions'][$y]['name'] = "user_import";
+		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
+		$y++;
+		$apps[$x]['permissions'][$y]['name'] = "user_group_view";
+		$apps[$x]['permissions'][$y]['menu']['uuid'] = "3b4acc6d-827b-f537-bf21-0093d94ffec7";
+		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
+		$apps[$x]['permissions'][$y]['groups'][] = "admin";
+		$y++;
+		$apps[$x]['permissions'][$y]['name'] = "user_group_add";
+		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
+		$apps[$x]['permissions'][$y]['groups'][] = "admin";
+		$y++;
+		$apps[$x]['permissions'][$y]['name'] = "user_group_edit";
+		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
+		$apps[$x]['permissions'][$y]['groups'][] = "admin";
+		$y++;
+		$apps[$x]['permissions'][$y]['name'] = "user_group_delete";
+		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
+		$apps[$x]['permissions'][$y]['groups'][] = "admin";
+		$y++;
 		$apps[$x]['permissions'][$y]['name'] = "user_setting_view";
 		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
 		$apps[$x]['permissions'][$y]['groups'][] = "admin";
@@ -71,6 +95,10 @@
 		$y++;
 		$apps[$x]['permissions'][$y]['name'] = "user_setting_category_edit";
 		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
+		$y++;
+		$apps[$x]['permissions'][$y]['name'] = "api_key";
+		$apps[$x]['permissions'][$y]['groups'][] = "superadmin";
+		$apps[$x]['permissions'][$y]['groups'][] = "admin";
 
 	//default settings
 		$y=0;
@@ -219,9 +247,71 @@
 		$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
 		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
 
+		$y++;
+		$apps[$x]['db'][$y]['table']['name']['text'] = "v_user_groups";
+		$apps[$x]['db'][$y]['table']['name']['deprecated'] = "v_group_users";
+		$apps[$x]['db'][$y]['table']['parent'] = "v_users";
+		$z=0;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "id";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['pgsql'] = "serial";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['sqlite'] = "integer";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['mysql'] = "INT NOT NULL AUTO_INCREMENT";
+		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
+		$apps[$x]['db'][$y]['fields'][$z]['deprecated'] = "true";
+		$z++;
+		$apps[$x]['db'][$y]['fields'][$z]['name']['text'] = "user_group_uuid";
+		$apps[$x]['db'][$y]['fields'][$z]['name']['deprecated'] = "group_user_uuid";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['pgsql'] = "uuid";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['sqlite'] = "text";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['mysql'] = "char(36)";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['type'] = "primary";
+		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
+		$z++;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "domain_uuid";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['pgsql'] = "uuid";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['sqlite'] = "text";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['mysql'] = "char(36)";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['type'] = "foreign";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['reference']['table'] = "v_domains";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['reference']['field'] = "domain_uuid";
+		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
+		$z++;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "v_id";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
+		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
+		$apps[$x]['db'][$y]['fields'][$z]['deprecated'] = "true";
+		$z++;
+		$apps[$x]['db'][$y]['fields'][$z]['name']['text'] = "group_name";
+		$apps[$x]['db'][$y]['fields'][$z]['name']['deprecated'] = "groupid";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
+		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
+		$z++;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "group_uuid";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['pgsql'] = "uuid";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['sqlite'] = "text";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['mysql'] = "char(36)";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['type'] = "foreign";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['reference']['table'] = "v_groups";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['reference']['field'] = "group_uuid";
+		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
+		$z++;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "username";
+		$apps[$x]['db'][$y]['fields'][$z]['type'] = "text";
+		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
+		$apps[$x]['db'][$y]['fields'][$z]['deprecated'] = "true";
+		$z++;
+		$apps[$x]['db'][$y]['fields'][$z]['name'] = "user_uuid";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['pgsql'] = "uuid";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['sqlite'] = "text";
+		$apps[$x]['db'][$y]['fields'][$z]['type']['mysql'] = "char(36)";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['type'] = "foreign";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['reference']['table'] = "v_users";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['reference']['field'] = "user_uuid";
+		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
+
 		$y++;
 		$apps[$x]['db'][$y]['table']['name'] = "v_user_settings";
-		$apps[$x]['db'][$y]['table']['parent'] = "";
+		$apps[$x]['db'][$y]['table']['parent'] = "v_users";
 		$z=0;
 		$apps[$x]['db'][$y]['fields'][$z]['name'] = "user_setting_uuid";
 		$apps[$x]['db'][$y]['fields'][$z]['type']['pgsql'] = "uuid";
@@ -234,6 +324,8 @@
 		$apps[$x]['db'][$y]['fields'][$z]['type']['sqlite'] = "text";
 		$apps[$x]['db'][$y]['fields'][$z]['type']['mysql'] = "char(36)";
 		$apps[$x]['db'][$y]['fields'][$z]['key']['type'] = "foreign";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['reference']['table'] = "v_users";
+		$apps[$x]['db'][$y]['fields'][$z]['key']['reference']['field'] = "user_uuid";
 		$apps[$x]['db'][$y]['fields'][$z]['description']['en-us'] = "";
 		$z++;
 		$apps[$x]['db'][$y]['fields'][$z]['name'] = "domain_uuid";

+ 76 - 6
core/users/app_defaults.php

@@ -17,7 +17,7 @@
 
 	The Initial Developer of the Original Code is
 	Mark J Crane <[email protected]>
-	Portions created by the Initial Developer are Copyright (C) 2008-2012
+	Portions created by the Initial Developer are Copyright (C) 2008-2019
 	the Initial Developer. All Rights Reserved.
 
 	Contributor(s):
@@ -30,8 +30,32 @@ if ($domains_processed == 1) {
 		$group = new groups;
 		$group->defaults();
 
+	//create the user view combines username, organization, contact first and last name
+		$db->exec("DROP VIEW view_users;");
+		$sql = "CREATE VIEW view_users AS (\n";
+		$sql .= "	select u.domain_uuid, u.user_uuid, d.domain_name, u.username, u.user_enabled, u.add_date, \n";
+		$sql .= "	c.contact_uuid, c.contact_organization, c.contact_name_given, c.contact_name_family,\n";
+		$sql .= "	(\n";
+		$sql .= "		select\n";
+		$sql .= "		string_agg(g.group_name, ', ')\n";
+		$sql .= "		from\n";
+		$sql .= "		v_user_groups as ug,\n";
+		$sql .= "		v_groups as g\n";
+		$sql .= "		where\n";
+		$sql .= "		ug.group_uuid = g.group_uuid\n";
+		$sql .= "		and u.user_uuid = ug.user_uuid\n";
+		$sql .= "	) AS groups\n";
+		$sql .= "	from v_contacts as c\n";
+		$sql .= "	right join v_users u on u.contact_uuid = c.contact_uuid\n";
+		$sql .= "	inner join v_domains as d on d.domain_uuid = u.domain_uuid\n";
+		$sql .= "	where 1 = 1\n";
+		$sql .= "	order by u.username asc\n";
+		$sql .= ");\n";
+		$db->exec($sql);
+		unset($sql);
+
 	//find rows that have a null group_uuid and set the correct group_uuid
-		$sql = "select * from v_group_users ";
+		$sql = "select * from v_user_groups ";
 		$sql .= "where group_uuid is null; ";
 		$prep_statement = $db->prepare(check_sql($sql));
 		if ($prep_statement) {
@@ -48,10 +72,10 @@ if ($domains_processed == 1) {
 						$sub_result = $prep_statement_sub->fetch(PDO::FETCH_ASSOC);
 						unset ($prep_statement_sub);
 						$group_uuid = $sub_result['group_uuid'];
-					//set the group_uuid
-						$sql = "update v_group_users set ";
+					//set the user_group_uuid
+						$sql = "update v_user_groups set ";
 						$sql .= "group_uuid = '".$group_uuid."' ";
-						$sql .= "where group_user_uuid = '".$row['group_user_uuid']."'; ";
+						$sql .= "where user_group_uuid = '".$row['user_group_uuid']."'; ";
 						$db->exec($sql);
 						unset($sql);
 				}
@@ -60,6 +84,52 @@ if ($domains_processed == 1) {
 			unset ($prep_statement);
 		}
 
+	//insert default password reset email template
+		if (file_exists($_SERVER['DOCUMENT_ROOT'].'/app/email_templates')) {
+			//build the array
+			$x = 0;
+			$array['email_templates'][$x]['email_template_uuid'] = '05b529c4-fba7-4071-bab3-143b076392e7';
+			$array['email_templates'][$x]['template_language'] = 'en-us';
+			$array['email_templates'][$x]['template_category'] = 'password_reset';
+			$array['email_templates'][$x]['template_subcategory'] = 'default';
+			$array['email_templates'][$x]['template_subject'] = 'Password Reset';
+			$array['email_templates'][$x]['template_body'] .= "<html>\n";
+			$array['email_templates'][$x]['template_body'] .= "<body>\n";
+			$array['email_templates'][$x]['template_body'] .= "<center><a href='https://\${domain}'><img src='\${logo_full}' style='width: 200px; height: auto; border: none;'></a></center><br />\n";
+			$array['email_templates'][$x]['template_body'] .= "A password reset was just requested for the FusionPBX user account associated with this email address.<br /><br />\n";
+			$array['email_templates'][$x]['template_body'] .= "<b>If you submitted this request</b>, click the button below to begin the password reset process for your user account.<br /><br />";
+			$array['email_templates'][$x]['template_body'] .= "\${reset_button}<br /><br />\n";
+			$array['email_templates'][$x]['template_body'] .= "If you did not initiate this action, however, please ignore this message and your password will remain unchanged.\n";
+			$array['email_templates'][$x]['template_body'] .= "If you have questions or concerns regarding this email, please contact your system administrator.";
+			$array['email_templates'][$x]['template_body'] .= "<br /><br /><br />\n";
+			$array['email_templates'][$x]['template_body'] .= "<a href='https://\${domain}'><img src='\${logo_shield}' width='31' height='30' border='0' align='left' style='margin-top: 3px; margin-right: 5px;'></a>\n";
+			$array['email_templates'][$x]['template_body'] .= "<i><b>FusionPBX</b></i><br />\n";
+			$array['email_templates'][$x]['template_body'] .= "<a href='https://\${domain}'>\${domain}</a>\n";
+			$array['email_templates'][$x]['template_body'] .= "<br /><br /><br />\n";
+			$array['email_templates'][$x]['template_body'] .= "</body>\n";
+			$array['email_templates'][$x]['template_body'] .= "</html>\n";
+			$array['email_templates'][$x]['template_type'] = 'html';
+			$array['email_templates'][$x]['template_enabled'] = 'true';
+			$array['email_templates'][$x]['template_description'] = 'Default password reset email template.';
+			$x++;
+
+			//add the temporary permission
+			$p = new permissions;
+			$p->add("email_template_add", 'temp');
+			$p->add("email_template_edit", 'temp');
+
+			//save to the data
+			$database = new database;
+			$database->app_name = 'email_templates';
+			$database->app_uuid = '8173e738-2523-46d5-8943-13883befd2fd';
+			$database->save($array);
+			unset($array);
+
+			//remove the temporary permission
+			$p->delete("email_template_add", 'temp');
+			$p->delete("email_template_edit", 'temp');
+		}
+
 }
 
-?>
+?>

+ 222 - 2
core/users/app_languages.php

@@ -271,7 +271,7 @@ $text['message-username_exists']['es-mx'] = "Ya existe Nombre de usuario"; //cop
 $text['message-username_exists']['fr-ca'] = "Le nom d'utilisateur existe déjà"; //copied from fr-fr
 $text['message-username_exists']['fr-fr'] = "Le nom d'utilisateur existe déjà";
 $text['message-username_exists']['he-il'] = "ש� משתמש כבר קיי�";
-$text['message-username_exists']['it-it'] = "Lo username Ãesiste già";
+$text['message-username_exists']['it-it'] = "Lo username Ãesiste giÃ";
 $text['message-username_exists']['nl-nl'] = "";
 $text['message-username_exists']['pl-pl'] = "Nazwa użytkownika już istnieje";
 $text['message-username_exists']['pt-br'] = "Nome de usuário já existe"; //copied from pt-pt
@@ -401,6 +401,66 @@ $text['message-cannot_delete_own_account']['ru-ru'] = "Вы не можете у
 $text['message-cannot_delete_own_account']['sv-se'] = "Du kan inte ta bort ditt egna användarkonto. Logga in som en annan användare och försök igen.";
 $text['message-cannot_delete_own_account']['uk-ua'] = "Ви не можете видалити вла�ний обліковий запи�. Будь ла�ка, увійдіть під іншим кори�тувачем, потім повторіть �пробу.";
 
+$text['message-invalid_user']['en-us'] = "Invalid User";
+$text['message-invalid_user']['ar-eg'] = "Invalid User";
+$text['message-invalid_user']['de-at'] = "Invalid User";
+$text['message-invalid_user']['de-ch'] = "Invalid User";
+$text['message-invalid_user']['de-de'] = "Invalid User";
+$text['message-invalid_user']['es-cl'] = "Invalid User";
+$text['message-invalid_user']['es-mx'] = "Invalid User";
+$text['message-invalid_user']['fr-ca'] = "Invalid User";
+$text['message-invalid_user']['fr-fr'] = "Invalid User";
+$text['message-invalid_user']['he-il'] = "Invalid User";
+$text['message-invalid_user']['it-it'] = "Invalid User";
+$text['message-invalid_user']['nl-nl'] = "Invalid User";
+$text['message-invalid_user']['pl-pl'] = "Invalid User";
+$text['message-invalid_user']['pt-br'] = "Invalid User";
+$text['message-invalid_user']['pt-pt'] = "Invalid User";
+$text['message-invalid_user']['ro-ro'] = "Invalid User";
+$text['message-invalid_user']['ru-ru'] = "Invalid User";
+$text['message-invalid_user']['sv-se'] = "Invalid User";
+$text['message-invalid_user']['uk-ua'] = "Invalid User";
+
+$text['message-unsaved_changes']['en-us'] = "Unsaved Changes";
+$text['message-unsaved_changes']['ar-eg'] = "Unsaved Changes";
+$text['message-unsaved_changes']['de-at'] = "Unsaved Changes";
+$text['message-unsaved_changes']['de-ch'] = "Unsaved Changes";
+$text['message-unsaved_changes']['de-de'] = "Unsaved Changes";
+$text['message-unsaved_changes']['es-cl'] = "Unsaved Changes";
+$text['message-unsaved_changes']['es-mx'] = "Unsaved Changes";
+$text['message-unsaved_changes']['fr-ca'] = "Unsaved Changes";
+$text['message-unsaved_changes']['fr-fr'] = "Unsaved Changes";
+$text['message-unsaved_changes']['he-il'] = "Unsaved Changes";
+$text['message-unsaved_changes']['it-it'] = "Unsaved Changes";
+$text['message-unsaved_changes']['nl-nl'] = "Unsaved Changes";
+$text['message-unsaved_changes']['pl-pl'] = "Unsaved Changes";
+$text['message-unsaved_changes']['pt-br'] = "Unsaved Changes";
+$text['message-unsaved_changes']['pt-pt'] = "Unsaved Changes";
+$text['message-unsaved_changes']['ro-ro'] = "Unsaved Changes";
+$text['message-unsaved_changes']['ru-ru'] = "Unsaved Changes";
+$text['message-unsaved_changes']['sv-se'] = "Unsaved Changes";
+$text['message-unsaved_changes']['uk-ua'] = "Unsaved Changes";
+
+$text['message-green_border_passwords_match']['en-us'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['ar-eg'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['de-at'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['de-ch'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['de-de'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['es-cl'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['es-mx'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['fr-ca'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['fr-fr'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['he-il'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['it-it'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['nl-nl'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['pl-pl'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['pt-br'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['pt-pt'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['ro-ro'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['ru-ru'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['sv-se'] = "Green field borders indicate typed passwords match.";
+$text['message-green_border_passwords_match']['uk-ua'] = "Green field borders indicate typed passwords match.";
+
 $text['label-web_fonts']['en-us'] = "Web Fonts";
 $text['label-web_fonts']['ar-eg'] = "الخطوط على شبكة الإنترنت";
 $text['label-web_fonts']['de-at'] = "Web Fonts"; //copied from de-de
@@ -921,6 +981,26 @@ $text['label-group']['ru-ru'] = "Группа";
 $text['label-group']['sv-se'] = "Grupp";
 $text['label-group']['uk-ua'] = "Група";
 
+$text['label-organization']['en-us'] = "Organization";
+$text['label-organization']['ar-eg'] = "";
+$text['label-organization']['de-at'] = "Organisation"; //copied from de-de
+$text['label-organization']['de-ch'] = "Organisation"; //copied from de-de
+$text['label-organization']['de-de'] = "Organisation";
+$text['label-organization']['es-cl'] = "Organización";
+$text['label-organization']['es-mx'] = "Organización"; //copied from es-cl
+$text['label-organization']['fr-ca'] = "Organisation"; //copied from fr-fr
+$text['label-organization']['fr-fr'] = "Organisation";
+$text['label-organization']['he-il'] = "";
+$text['label-organization']['it-it'] = "Organizzazione";
+$text['label-organization']['nl-nl'] = "";
+$text['label-organization']['pl-pl'] = "";
+$text['label-organization']['pt-br'] = "Organização"; //copied from pt-pt
+$text['label-organization']['pt-pt'] = "Organização";
+$text['label-organization']['ro-ro'] = "";
+$text['label-organization']['ru-ru'] = "Организаци�";
+$text['label-organization']['sv-se'] = "Organisation";
+$text['label-organization']['uk-ua'] = "";
+
 $text['label-global']['en-us'] = "Global";
 $text['label-global']['ar-eg'] = "";
 $text['label-global']['de-at'] = "Global"; //copied from de-de
@@ -1101,6 +1181,106 @@ $text['label-characters']['ru-ru'] = "�имволов";
 $text['label-characters']['sv-se'] = "Tecken";
 $text['label-characters']['uk-ua'] = "пер�онажі";
 
+$text['label-required']['en-us'] = "Required";
+$text['label-required']['ar-eg'] = "Required";
+$text['label-required']['de-at'] = "Required";
+$text['label-required']['de-ch'] = "Required";
+$text['label-required']['de-de'] = "Required";
+$text['label-required']['es-cl'] = "Required";
+$text['label-required']['es-mx'] = "Required";
+$text['label-required']['fr-ca'] = "Required";
+$text['label-required']['fr-fr'] = "Required";
+$text['label-required']['he-il'] = "Required";
+$text['label-required']['it-it'] = "Required";
+$text['label-required']['nl-nl'] = "Required";
+$text['label-required']['pl-pl'] = "Required";
+$text['label-required']['pt-br'] = "Required";
+$text['label-required']['pt-pt'] = "Required";
+$text['label-required']['ro-ro'] = "Required";
+$text['label-required']['ru-ru'] = "Required";
+$text['label-required']['sv-se'] = "Required";
+$text['label-required']['uk-ua'] = "Required";
+
+$text['label-number']['en-us'] = "Number";
+$text['label-number']['ar-eg'] = "Number";
+$text['label-number']['de-at'] = "Number";
+$text['label-number']['de-ch'] = "Number";
+$text['label-number']['de-de'] = "Number";
+$text['label-number']['es-cl'] = "Number";
+$text['label-number']['es-mx'] = "Number";
+$text['label-number']['fr-ca'] = "Number";
+$text['label-number']['fr-fr'] = "Number";
+$text['label-number']['he-il'] = "Number";
+$text['label-number']['it-it'] = "Number";
+$text['label-number']['nl-nl'] = "Number";
+$text['label-number']['pl-pl'] = "Number";
+$text['label-number']['pt-br'] = "Number";
+$text['label-number']['pt-pt'] = "Number";
+$text['label-number']['ro-ro'] = "Number";
+$text['label-number']['ru-ru'] = "Number";
+$text['label-number']['sv-se'] = "Number";
+$text['label-number']['uk-ua'] = "Number";
+
+$text['label-lowercase']['en-us'] = "Lowercase";
+$text['label-lowercase']['ar-eg'] = "Lowercase";
+$text['label-lowercase']['de-at'] = "Lowercase";
+$text['label-lowercase']['de-ch'] = "Lowercase";
+$text['label-lowercase']['de-de'] = "Lowercase";
+$text['label-lowercase']['es-cl'] = "Lowercase";
+$text['label-lowercase']['es-mx'] = "Lowercase";
+$text['label-lowercase']['fr-ca'] = "Lowercase";
+$text['label-lowercase']['fr-fr'] = "Lowercase";
+$text['label-lowercase']['he-il'] = "Lowercase";
+$text['label-lowercase']['it-it'] = "Lowercase";
+$text['label-lowercase']['nl-nl'] = "Lowercase";
+$text['label-lowercase']['pl-pl'] = "Lowercase";
+$text['label-lowercase']['pt-br'] = "Lowercase";
+$text['label-lowercase']['pt-pt'] = "Lowercase";
+$text['label-lowercase']['ro-ro'] = "Lowercase";
+$text['label-lowercase']['ru-ru'] = "Lowercase";
+$text['label-lowercase']['sv-se'] = "Lowercase";
+$text['label-lowercase']['uk-ua'] = "Lowercase";
+
+$text['label-uppercase']['en-us'] = "Uppercase";
+$text['label-uppercase']['ar-eg'] = "Uppercase";
+$text['label-uppercase']['de-at'] = "Uppercase";
+$text['label-uppercase']['de-ch'] = "Uppercase";
+$text['label-uppercase']['de-de'] = "Uppercase";
+$text['label-uppercase']['es-cl'] = "Uppercase";
+$text['label-uppercase']['es-mx'] = "Uppercase";
+$text['label-uppercase']['fr-ca'] = "Uppercase";
+$text['label-uppercase']['fr-fr'] = "Uppercase";
+$text['label-uppercase']['he-il'] = "Uppercase";
+$text['label-uppercase']['it-it'] = "Uppercase";
+$text['label-uppercase']['nl-nl'] = "Uppercase";
+$text['label-uppercase']['pl-pl'] = "Uppercase";
+$text['label-uppercase']['pt-br'] = "Uppercase";
+$text['label-uppercase']['pt-pt'] = "Uppercase";
+$text['label-uppercase']['ro-ro'] = "Uppercase";
+$text['label-uppercase']['ru-ru'] = "Uppercase";
+$text['label-uppercase']['sv-se'] = "Uppercase";
+$text['label-uppercase']['uk-ua'] = "Uppercase";
+
+$text['label-special']['en-us'] = "Special";
+$text['label-special']['ar-eg'] = "Special";
+$text['label-special']['de-at'] = "Special";
+$text['label-special']['de-ch'] = "Special";
+$text['label-special']['de-de'] = "Special";
+$text['label-special']['es-cl'] = "Special";
+$text['label-special']['es-mx'] = "Special";
+$text['label-special']['fr-ca'] = "Special";
+$text['label-special']['fr-fr'] = "Special";
+$text['label-special']['he-il'] = "Special";
+$text['label-special']['it-it'] = "Special";
+$text['label-special']['nl-nl'] = "Special";
+$text['label-special']['pl-pl'] = "Special";
+$text['label-special']['pt-br'] = "Special";
+$text['label-special']['pt-pt'] = "Special";
+$text['label-special']['ro-ro'] = "Special";
+$text['label-special']['ru-ru'] = "Special";
+$text['label-special']['sv-se'] = "Special";
+$text['label-special']['uk-ua'] = "Special";
+
 $text['label-center']['en-us'] = "Center";
 $text['label-center']['ar-eg'] = "مركز";
 $text['label-center']['de-at'] = "Mitte"; //copied from de-de
@@ -1161,6 +1341,26 @@ $text['label-api_key']['ru-ru'] = "Ключ API";
 $text['label-api_key']['sv-se'] = "API Nyckel";
 $text['label-api_key']['uk-ua'] = "Ключ API";
 
+$text['label-message_key']['en-us'] = "Message Key";
+$text['label-message_key']['ar-eg'] = "";
+$text['label-message_key']['de-at'] = "Message Schlüssel"; //copied from de-de
+$text['label-message_key']['de-ch'] = "Message Schlüssel"; //copied from de-de
+$text['label-message_key']['de-de'] = "Message Schlüssel";
+$text['label-message_key']['es-cl'] = "Message Key";
+$text['label-message_key']['es-mx'] = "Message Key"; //copied from es-cl
+$text['label-message_key']['fr-ca'] = "Clé d'Message"; //copied from fr-fr
+$text['label-message_key']['fr-fr'] = "Clé d'Message";
+$text['label-message_key']['he-il'] = "";
+$text['label-message_key']['it-it'] = "Message Key";
+$text['label-message_key']['nl-nl'] = "";
+$text['label-message_key']['pl-pl'] = "Klucz Message";
+$text['label-message_key']['pt-br'] = "Message Key"; //copied from pt-pt
+$text['label-message_key']['pt-pt'] = "Message Key";
+$text['label-message_key']['ro-ro'] = "";
+$text['label-message_key']['ru-ru'] = "Ключ Message";
+$text['label-message_key']['sv-se'] = "Message Nyckel";
+$text['label-message_key']['uk-ua'] = "Ключ Message";
+
 $text['label-additional_info']['en-us'] = "Additional Info";
 $text['label-additional_info']['ar-eg'] = "";
 $text['label-additional_info']['de-at'] = "Zusätzliche Information"; //copied from de-de
@@ -1541,7 +1741,7 @@ $text['description-contact']['ru-ru'] = "�азначить контакт дл
 $text['description-contact']['sv-se'] = "Tilldela en kontakt till detta konto.";
 $text['description-contact']['uk-ua'] = "Призначити контакт в цей обліковий запи� кори�тувача.";
 
-$text['description-api_key']['en-us'] = "Enter the API key is often a UUID. The API key should be 128 bit or greater.";
+$text['description-api_key']['en-us'] = "Use the generate button to create a 128 bit key.";
 $text['description-api_key']['ar-eg'] = "";
 $text['description-api_key']['de-at'] = "Geben Sie den API Schlüssel an. Der API Schlüssel sollte mindestens 128 bit oder länger sein."; //copied from de-de
 $text['description-api_key']['de-ch'] = "Geben Sie den API Schlüssel an. Der API Schlüssel sollte mindestens 128 bit oder länger sein."; //copied from de-de
@@ -1561,6 +1761,26 @@ $text['description-api_key']['ru-ru'] = "Введите ключ API (обычн
 $text['description-api_key']['sv-se'] = "Ange API nyckel (ofta UUID). API nyckeln borde vara 128 bit eller mer.";
 $text['description-api_key']['uk-ua'] = "Введіть ключ API, зазвичай UUID. Ключ API повинен бути 128 біт або більше.";
 
+$text['description-message_key']['en-us'] = "Use the generate button to create a 128 bit key.";
+$text['description-message_key']['ar-eg'] = "";
+$text['description-message_key']['de-at'] = "Geben Sie den API Schlüssel an. Der API Schlüssel sollte mindestens 128 bit oder länger sein."; //copied from de-de
+$text['description-message_key']['de-ch'] = "Geben Sie den API Schlüssel an. Der API Schlüssel sollte mindestens 128 bit oder länger sein."; //copied from de-de
+$text['description-message_key']['de-de'] = "Geben Sie den API Schlüssel an. Der API Schlüssel sollte mindestens 128 bit oder länger sein.";
+$text['description-message_key']['es-cl'] = "Indique la API key.";
+$text['description-message_key']['es-mx'] = "Indique la API key."; //copied from es-cl
+$text['description-message_key']['fr-ca'] = "Entrez la  clé d'API. Il s'agit souvent d'un identifiant universel unique (UUID). La clé devrait faire 128 bits ou plus de longueur."; //copied from fr-fr
+$text['description-message_key']['fr-fr'] = "Entrez la  clé d'API. Il s'agit souvent d'un identifiant universel unique (UUID). La clé devrait faire 128 bits ou plus de longueur.";
+$text['description-message_key']['he-il'] = "";
+$text['description-message_key']['it-it'] = "Inserisci la API key, spesso è un UUID. L'API key dovrebbe essere 128 bit o più.";
+$text['description-message_key']['nl-nl'] = "";
+$text['description-message_key']['pl-pl'] = "Wprowadź klucz API, który jest często UUID. Klucz API powinien być 128 bitowy lub lepszy.";
+$text['description-message_key']['pt-br'] = "";
+$text['description-message_key']['pt-pt'] = "";
+$text['description-message_key']['ro-ro'] = "";
+$text['description-message_key']['ru-ru'] = "Введите ключ API (обычно UUID). Ключ API должен быть 128 бит или больше.";
+$text['description-message_key']['sv-se'] = "Ange API nyckel (ofta UUID). API nyckeln borde vara 128 bit eller mer.";
+$text['description-message_key']['uk-ua'] = "Введіть ключ API, зазвичай UUID. Ключ API повинен бути 128 біт або більше.";
+
 $text['confirm-delete']['en-us'] = "Do you really want to delete this?";
 $text['confirm-delete']['ar-eg'] = "";
 $text['confirm-delete']['de-at'] = "Wollen Sie das wirklich löschen?"; //copied from de-de

+ 3 - 2
core/users/app_menu.php

@@ -48,8 +48,9 @@
 	$apps[$x]['menu'][$y]['parent_uuid'] = "02194288-6d56-6d3e-0b1a-d53a2bc10788";
 	$apps[$x]['menu'][$y]['category'] = "internal";
 	$apps[$x]['menu'][$y]['path'] = "/core/users/user_edit.php?id=user";
-	$apps[$x]['menu'][$y]['groups'][] = "user";
-	$apps[$x]['menu'][$y]['groups'][] = "admin";
 	$apps[$x]['menu'][$y]['groups'][] = "superadmin";
+	$apps[$x]['menu'][$y]['groups'][] = "admin";
+	$apps[$x]['menu'][$y]['groups'][] = "user";
+	$apps[$x]['menu'][$y]['groups'][] = "agent";
 
 ?>

+ 3 - 3
core/users/user_delete.php

@@ -83,7 +83,7 @@
 			}
 
 		//delete the groups the user is assigned to
-			$sql = "delete from v_group_users ";
+			$sql = "delete from v_user_groups ";
 			$sql .= "where user_uuid = '".$user_uuid."' ";
 			$sql .= "and domain_uuid = '".$domain_uuid."' ";
 			if (!$db->exec($sql)) {
@@ -102,7 +102,7 @@
 	}
 
 //redirect the user
-	messages::add($text['message-delete']);
+	message::add($text['message-delete']);
 	header("Location: users.php");
 
-?>
+?>

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 486 - 372
core/users/user_edit.php


+ 501 - 0
core/users/user_imports.php

@@ -0,0 +1,501 @@
+<?php
+/*
+	FusionPBX
+	Version: MPL 1.1
+
+	The contents of this file are subject to the Mozilla Public License Version
+	1.1 (the "License"); you may not use this file except in compliance with
+	the License. You may obtain a copy of the License at
+	http://www.mozilla.org/MPL/
+
+	Software distributed under the License is distributed on an "AS IS" basis,
+	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+	for the specific language governing rights and limitations under the
+	License.
+
+	The Original Code is FusionPBX
+
+	The Initial Developer of the Original Code is
+	Mark J Crane <[email protected]>
+	Portions created by the Initial Developer are Copyright (C) 2008-2018
+	the Initial Developer. All Rights Reserved.
+
+	Contributor(s):
+	Mark J Crane <[email protected]>
+*/
+
+//includes
+	include "root.php";
+	require_once "resources/require.php";
+	require_once "resources/check_auth.php";
+
+//check permissions
+	if (permission_exists('user_import')) {
+		//access granted
+	}
+	else {
+		echo "access denied";
+		exit;
+	}
+
+//add multi-lingual support
+	$language = new text;
+	$text = $language->get();
+
+//built in str_getcsv requires PHP 5.3 or higher, this function can be used to reproduct the functionality but requirs PHP 5.1.0 or higher
+	if(!function_exists('str_getcsv')) {
+		function str_getcsv($input, $delimiter = ",", $enclosure = '"', $escape = "\\") {
+			$fp = fopen("php://memory", 'r+');
+			fputs($fp, $input);
+			rewind($fp);
+			$data = fgetcsv($fp, null, $delimiter, $enclosure); // $escape only got added in 5.3.0
+			fclose($fp);
+			return $data;
+		}
+	}
+
+//set the max php execution time
+	ini_set(max_execution_time,7200);
+
+//get the http get values and set them as php variables
+	$action = check_str($_POST["action"]);
+	$from_row = check_str($_POST["from_row"]);
+	$order_by = check_str($_POST["order_by"]);
+	$order = check_str($_POST["order"]);
+	$delimiter = check_str($_POST["data_delimiter"]);
+	$enclosure = check_str($_POST["data_enclosure"]);
+
+//save the data to the csv file
+	if (isset($_POST['data'])) {
+		$file = $_SESSION['server']['temp']['dir']."/users-".$_SESSION['domain_name'].".csv";
+		file_put_contents($file, $_POST['data']);
+		$_SESSION['file'] = $file;
+	}
+
+//copy the csv file
+	//$_POST['submit'] == "Upload" &&
+	if ( is_uploaded_file($_FILES['ulfile']['tmp_name']) && permission_exists('user_imports')) {
+		if (check_str($_POST['type']) == 'csv') {
+			move_uploaded_file($_FILES['ulfile']['tmp_name'], $_SESSION['server']['temp']['dir'].'/'.$_FILES['ulfile']['name']);
+			$save_msg = "Uploaded file to ".$_SESSION['server']['temp']['dir']."/". htmlentities($_FILES['ulfile']['name']);
+			//system('chmod -R 744 '.$_SESSION['server']['temp']['dir'].'*');
+			unset($_POST['txtCommand']);
+			$file = $_SESSION['server']['temp']['dir'].'/'.$_FILES['ulfile']['name'];
+			$_SESSION['file'] = $file;
+		}
+	}
+
+//get the schema
+	if (strlen($delimiter) > 0) {
+		//get the first line
+			$line = fgets(fopen($_SESSION['file'], 'r'));
+			$line_fields = explode($delimiter, $line);
+
+		//get the schema
+			$x = 0;
+			include ("core/users/app_config.php");
+			$i = 0;
+			foreach($apps[0]['db'] as $table) {
+				//get the table name and parent name
+				$table_name = $table["table"]['name'];
+				$parent_name = $table["table"]['parent'];
+
+				//remove the v_ table prefix
+				if (substr($table_name, 0, 2) == 'v_') {
+						$table_name = substr($table_name, 2);
+				}
+				if (substr($parent_name, 0, 2) == 'v_') {
+						$parent_name = substr($parent_name, 2);
+				}
+
+				//filter for specific tables and build the schema array
+				if ($table_name == "users") {
+					$schema[$i]['table'] = $table_name;
+					$schema[$i]['parent'] = $parent_name;
+					foreach($table['fields'] as $row) {
+						if ($row['deprecated'] !== 'true') {
+							if (is_array($row['name'])) {
+								$field_name = $row['name']['text'];
+							}
+							else {
+								$field_name = $row['name'];
+							}
+							$schema[$i]['fields'][] = $field_name;
+						}
+					}
+					$i++;	
+				}
+			}
+			$schema[$i]['table'] = 'user_groups';
+			$schema[$i]['parent'] = 'users';
+			$schema[$i]['fields'][] = 'group_name';
+
+		//debug info
+			//echo "<pre>\n";
+			//print_r($schema);
+			//echo "</pre>\n";
+			//exit;
+	}
+
+//match the column names to the field names
+	if (strlen($delimiter) > 0 && file_exists($_SESSION['file']) && $action != 'import') {
+
+		//form to match the fields to the column names
+			require_once "resources/header.php";
+
+			echo "<form action='user_imports.php' method='POST' enctype='multipart/form-data' name='frmUpload' onSubmit=''>\n";
+			echo "<table width='100%' border='0' cellpadding='0' cellspacing='0'>\n";
+
+			echo "	<tr>\n";
+			echo "	<td valign='top' align='left' nowrap='nowrap'>\n";
+			echo "		<b>".$text['header-import']."</b><br />\n";
+			echo "	</td>\n";
+			echo "	<td valign='top' align='right'>\n";
+			echo "		<input type='button' class='btn' name='' alt='".$text['button-back']."' onclick=\"window.location='users.php'\" value='".$text['button-back']."'>\n";
+			echo "		<input name='submit' type='submit' class='btn' id='import' value=\"".$text['button-import']."\">\n";
+			echo "	</td>\n";
+			echo "	</tr>\n";
+			echo "	<tr>\n";
+			echo "	<td colspan='2' align='left'>\n";
+			echo "		".$text['description-import']."\n";
+			echo "	</td>\n";
+			echo "	</tr>\n";
+
+			//echo "<tr>\n";
+			//echo "<td align='left' width='30%' nowrap='nowrap'><b>".$text['header-import']."</b></td>\n";
+			//echo "<td width='70%' align='right'>\n";
+			//echo "	<input type='button' class='btn' name='' alt='".$text['button-back']."' onclick=\"window.location='users.php'\" value='".$text['button-back']."'>\n";
+			//echo "</td>\n";
+			//echo "</tr>\n";
+
+			//loop through user columns
+			$x = 0;
+			foreach ($line_fields as $line_field) {
+				$line_field = trim(trim($line_field), $enclosure);
+				echo "<tr>\n";
+				echo "<td class='vncell' valign='top' align='left' nowrap='nowrap'>\n";
+				//echo "    ".$text['label-zzz']."\n";
+				echo $line_field;
+				echo "</td>\n";
+				echo "<td class='vtable' align='left'>\n";
+				echo "    			<select class='formfld' style='' name='fields[$x]'>\n";
+				echo "    			<option value=''></option>\n";
+				foreach($schema as $row) {
+					echo "			<optgroup label='".$row['table']."'>\n";
+					foreach($row['fields'] as $field) {
+						$selected = '';
+						if ($field == $line_field) {
+							$selected = "selected='selected'";
+						}
+						if ($field !== 'domain_uuid') {
+							echo "    			<option value='".$row['table'].".".$field."' ".$selected.">".$field."</option>\n";
+						}
+					}
+					echo "			</optgroup>\n";
+				}
+				echo "    			</select>\n";
+				//echo "<br />\n";
+				//echo $text['description-zzz']."\n";
+				echo "			</td>\n";
+				echo "		</tr>\n";
+				$x++;
+			}
+
+			echo "		<tr>\n";
+			echo "			<td colspan='2' valign='top' align='right' nowrap='nowrap'>\n";
+			echo "				<input name='action' type='hidden' value='import'>\n";
+			echo "				<input name='from_row' type='hidden' value='$from_row'>\n";
+			echo "				<input name='data_delimiter' type='hidden' value='$delimiter'>\n";
+			echo "				<input name='data_enclosure' type='hidden' value='$enclosure'>\n";
+			echo "				<input type='submit' class='btn' id='import' value=\"".$text['button-import']."\">\n";
+			echo "			</td>\n";
+			echo "		</tr>\n";
+
+			echo "	</table>\n";
+			echo "</form>\n";
+			require_once "resources/footer.php";
+
+		//normalize the column names
+			//$line = strtolower($line);
+			//$line = str_replace("-", "_", $line);
+			//$line = str_replace($delimiter."title".$delimiter, $delimiter."contact_title".$delimiter, $line);
+			//$line = str_replace("firstname", "name_given", $line);
+			//$line = str_replace("lastname", "name_family", $line);
+			//$line = str_replace("company", "organization", $line);
+			//$line = str_replace("company", "contact_email", $line);
+
+		//end the script
+			exit;
+	}
+
+//get the parent table
+	function get_parent($schema,$table_name) {
+		foreach ($schema as $row) {
+			if ($row['table'] == $table_name) {
+				return $row['parent'];
+			}
+		}
+	}
+
+//upload the csv
+	if (file_exists($_SESSION['file']) && $action == 'import') {
+
+		//form to match the fields to the column names
+			//require_once "resources/header.php";
+
+		//user selected fields
+			$fields = $_POST['fields'];
+
+		//set the domain_uuid
+			$domain_uuid = $_SESSION['domain_uuid'];
+
+
+		//get the groups
+			$sql = "select * from v_groups where domain_uuid is null ";
+			$prep_statement = $db->prepare($sql);
+			$prep_statement->execute();
+			$groups = $prep_statement->fetchAll(PDO::FETCH_ASSOC);
+
+		//get the contents of the csv file and convert them into an array
+			$handle = @fopen($_SESSION['file'], "r");
+			if ($handle) {
+				//set the starting identifiers
+					$row_id = 0;
+					$row_number = 1;
+
+				//loop through the array
+					while (($line = fgets($handle, 4096)) !== false) {
+						if ($from_row <= $row_number) {
+							//get the user_uuid
+								$user_uuid = uuid();
+
+							//format the data
+								$y = 0;
+								foreach ($fields as $key => $value) {
+
+									//get the line
+									$result = str_getcsv($line, $delimiter, $enclosure);
+									
+									//get the table and field name
+									$field_array = explode(".",$value);
+									$table_name = $field_array[0];
+									$field_name = $field_array[1];
+									//echo "value: $value<br />\n";
+									//echo "table_name: $table_name<br />\n";
+									//echo "field_name: $field_name<br />\n";
+
+									//get the parent table name
+									$parent = get_parent($schema, $table_name);
+
+									//clean the phone number
+									//if ($field_name == "phone") {
+									//	$result[$key] = preg_replace('{\D}', '', $result[$key]);
+									//}
+
+									//build the data array
+									if (strlen($table_name) > 0) {
+										if (strlen($parent) == 0) {
+											$array[$table_name][$row_id]['domain_uuid'] = $domain_uuid;
+											$array[$table_name][$row_id][$field_name] = $result[$key];
+										}
+										else {
+											if ($field_name != "group_name") {
+												$array[$parent][$row_id][$table_name][$y]['domain_uuid'] = $domain_uuid;
+												$array[$parent][$row_id][$table_name][$y][$field_name] = $result[$key];
+											}
+										}
+
+										if ($field_name == "group_name") {
+												$group_name = '';
+												foreach ($groups as $field) {
+													if ($field['group_name'] == $result[$key]) {
+														$group_name = $field['group_name'];
+														$array['user_groups'][$row_id]['user_group_uuid'] = uuid();
+														$array['user_groups'][$row_id]['domain_uuid'] = $domain_uuid;
+														$array['user_groups'][$row_id]['group_name'] = $field['group_name'];
+														$array['user_groups'][$row_id]['group_uuid'] = $field['group_uuid'];
+														$array['user_groups'][$row_id]['user_uuid'] = $user_uuid;
+													}
+												}
+	
+												//remove superadmin if not the correct permission
+												if ($group_name == 'superadmin') {
+													if (!permission_exists('group_domain')) {
+														unset($array['user_groups'][$row_id]);
+													}
+												}
+										}
+									}
+								}
+
+							//get the password, salt and hash the user password
+								$password = $array['users'][$row_id]['password'];
+								if (isset($array['users'][$row_id]['salt'])) {
+									$salt = $array['users'][$row_id]['salt'];
+								}
+								else {
+									$salt = uuid();
+									$array['users'][$row_id]['salt'] = $salt;
+								}
+								$array['users'][$row_id]['password'] = md5($salt.$password);
+
+							//set the user_uuid
+								$array['users'][$row_id]['user_uuid'] = $user_uuid;
+
+							//debug
+								//echo "<pre>\n";
+								//print_r($array);
+								//echo "</pre>\n";
+								//exit;
+
+							//process a chunk of the array
+								if ($row_id === 1000) {
+
+									//save to the data
+										$database = new database;
+										$database->app_name = 'users';
+										$database->app_uuid = '4efa1a1a-32e7-bf83-534b-6c8299958a8e';
+										$database->save($array);
+										//$message = $database->message;
+
+									//clear the array
+										unset($array);
+
+									//set the row id back to 0
+										$row_id = 0;
+								}
+
+						} //if ($from_row <= $row_id)
+						$row_number++;
+						$row_id++;
+					} //end while
+					fclose($handle);
+
+				//debug info
+					//echo "<pre>\n";
+					//print_r($array);
+					//echo "</pre>\n";
+					//exit;
+
+				//save to the data
+					if (is_array($array)) {
+						$database = new database;
+						$database->app_name = 'users';
+						$database->app_uuid = '4efa1a1a-32e7-bf83-534b-6c8299958a8e';
+						$database->save($array);
+						//$message = $database->message;
+					}
+
+				//send the redirect header
+					header("Location: users.php");
+					return;
+			}
+	}
+
+//include the header
+	require_once "resources/header.php";
+
+//begin the content
+	echo "<table width='100%' border='0' cellpadding='0' cellspacing='0'>\n";
+	echo "	<tr>\n";
+	echo "	<td valign='top' align='left' width='30%' nowrap='nowrap'>\n";
+	echo "		<b>".$text['header-import']."</b><br />\n";
+	echo "		".$text['description-import']."\n";
+	echo "	</td>\n";
+	echo "	<td valign='top' width='70%' align='right'>\n";
+	echo "		<input type='button' class='btn' name='' alt='".$text['button-back']."' onclick=\"window.location='users.php?".$_GET["query_string"]."'\" value='".$text['button-back']."'>\n";
+	//echo "		<input name='submit' type='submit' class='btn' id='import' value=\"".$text['button-import']."\">\n";
+	echo "	</td>\n";
+	echo "	</tr>\n";
+	echo "</table>";
+
+	echo "<br />\n";
+
+	echo "<form action='' method='POST' enctype='multipart/form-data' name='frmUpload' onSubmit=''>\n";
+	echo "	<table border='0' cellpadding='0' cellspacing='0' width='100%'>\n";
+
+	echo "<tr>\n";
+	echo "<td class='vncell' valign='top' align='left' nowrap='nowrap'>\n";
+	echo "    ".$text['label-import_data']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo "    <textarea name='data' id='data' rows='7' class='formfld' style='width: 100%;' wrap='off'>$data</textarea>\n";
+	echo "<br />\n";
+	echo $text['description-import_data']."\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	echo "<tr>\n";
+	echo "<td class='vncell' valign='top' align='left' nowrap='nowrap'>\n";
+	echo "    ".$text['label-from_row']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo "		<select class='formfld' name='from_row'>\n";
+	$i=1;
+	while($i<=99) {
+		$selected = ($i == $from_row) ? "selected" : null;
+		echo "			<option value='$i' ".$selected.">$i</option>\n";
+		$i++;
+	}
+	echo "		</select>\n";
+	echo "<br />\n";
+	echo $text['description-from_row']."\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	echo "<tr>\n";
+	echo "<td class='vncell' valign='top' align='left' nowrap='nowrap'>\n";
+	echo "    ".$text['label-import_delimiter']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo "    <select class='formfld' style='width:40px;' name='data_delimiter'>\n";
+	echo "    <option value=','>,</option>\n";
+	echo "    <option value='|'>|</option>\n";
+	echo "    </select>\n";
+	echo "<br />\n";
+	echo $text['description-import_delimiter']."\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	echo "<tr>\n";
+	echo "<td class='vncell' valign='top' align='left' nowrap='nowrap'>\n";
+	echo "    ".$text['label-import_enclosure']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo "    <select class='formfld' style='width:40px;' name='data_enclosure'>\n";
+	echo "    <option value='\"'>\"</option>\n";
+	echo "    <option value=''></option>\n";
+	echo "    </select>\n";
+	echo "<br />\n";
+	echo $text['description-import_enclosure']."\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	echo "<tr>\n";
+	echo "<td class='vncell' valign='top' align='left' nowrap='nowrap'>\n";
+	echo "			".$text['label-import_file_upload']."\n";
+	echo "</td>\n";
+	echo "<td class='vtable' align='left'>\n";
+	echo "			<input name='ulfile' type='file' class='formfld fileinput' id='ulfile'>\n";
+	echo "<br />\n";
+	echo "</td>\n";
+	echo "</tr>\n";
+
+	echo "	<tr>\n";
+	echo "		<td valign='bottom'>\n";
+	echo "			&nbsp;\n";
+	echo "		</td>\n";
+	echo "		<td valign='bottom' align='right' nowrap>\n";
+	echo "			<input name='type' type='hidden' value='csv'>\n";
+	echo "			<br />\n";
+	echo "			<input name='submit' type='submit' class='btn' id='import' value=\"".$text['button-import']."\">\n";
+	echo "		</td>\n";
+	echo "	</tr>\n";
+	echo "	</table>\n";
+	echo "<br><br>";
+	echo "</form>";
+
+//include the footer
+	require_once "resources/footer.php";
+
+?>

+ 1 - 1
core/users/user_setting_delete.php

@@ -60,7 +60,7 @@
 	}
 	else {
 		// set message
-		messages::add($text['message-delete_failed'], 'negative');
+		message::add($text['message-delete_failed'], 'negative');
 	}
 
 	header("Location: user_edit.php?id=".check_str($_REQUEST["user_uuid"]));

+ 19 - 19
core/users/user_setting_edit.php

@@ -319,10 +319,10 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 
 			//redirect the browser
 				if ($action == "update") {
-					messages::add($text['message-update']);
+					message::add($text['message-update']);
 				}
 				if ($action == "add") {
-					messages::add($text['message-add']);
+					message::add($text['message-add']);
 				}
 				header("Location: user_edit.php?id=".$user_uuid);
 				return;
@@ -373,7 +373,7 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 	}
 	echo "</b></td>\n";
 	echo "<td width='70%' align='right' valign='top'>";
-	echo "	<input type='button' class='btn' name='' alt='".$text['button-back']."' onclick=\"window.location='user_edit.php?id=$user_uuid'\" value='".$text['button-back']."'>";
+	echo "	<input type='button' class='btn' name='' alt='".$text['button-back']."' onclick=\"window.location='user_edit.php?id=".escape($user_uuid)."'\" value='".$text['button-back']."'>";
 	echo "	<input type='button' class='btn' value='".$text['button-save']."' onclick='submit_form();'>\n";
 	echo "</td>\n";
 	echo "</tr>\n";
@@ -395,7 +395,7 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 	echo "</td>\n";
 	echo "<td class='vtable' align='left'>\n";
 	if (permission_exists('user_setting_category_edit')) {
-		echo "	<input type='text' class='formfld' name='user_setting_category' id='user_setting_category' maxlength='255' value=\"".$user_setting_category."\">\n";
+		echo "	<input type='text' class='formfld' name='user_setting_category' id='user_setting_category' maxlength='255' value=\"".escape($user_setting_category)."\">\n";
 	}
 	else {
 		echo "	<select class='formfld' name='user_setting_category' id='user_setting_category' onchange=\"$('#user_setting_subcategory').focus();\">\n";
@@ -418,7 +418,7 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 	echo "	".$text['label-subcategory']."\n";
 	echo "</td>\n";
 	echo "<td class='vtable' align='left'>\n";
-	echo "	<input class='formfld lowercase' type='text' name='user_setting_subcategory' id='user_setting_subcategory' maxlength='255' value=\"$user_setting_subcategory\">\n";
+	echo "	<input class='formfld lowercase' type='text' name='user_setting_subcategory' id='user_setting_subcategory' maxlength='255' value=\"".escape($user_setting_subcategory)."\">\n";
 	echo "<br />\n";
 	echo $text['description-subcategory']."\n";
 	echo "</td>\n";
@@ -429,7 +429,7 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 	echo "	".$text['label-type']."\n";
 	echo "</td>\n";
 	echo "<td class='vtable' align='left'>\n";
-	echo "	<input class='formfld lowercase' type='text' name='user_setting_name' id='user_setting_name' maxlength='255' value=\"$user_setting_name\">\n";
+	echo "	<input class='formfld lowercase' type='text' name='user_setting_name' id='user_setting_name' maxlength='255' value=\"".escape($user_setting_name)."\">\n";
 	echo "<br />\n";
 	echo $text['description-type']."\n";
 	echo "</td>\n";
@@ -454,10 +454,10 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 		$sub_result = $sub_prep_statement->fetchAll(PDO::FETCH_NAMED);
 		foreach ($sub_result as $sub_row) {
 			if (strtolower($row['user_setting_value']) == strtolower($sub_row["menu_uuid"])) {
-				echo "		<option value='".strtolower($sub_row["menu_uuid"])."' selected='selected'>".$sub_row["menu_language"]." - ".$sub_row["menu_name"]."\n";
+				echo "		<option value='".strtolower($sub_row["menu_uuid"])."' selected='selected'>".escape($sub_row["menu_language"])." - ".escape($sub_row["menu_name"])."\n";
 			}
 			else {
-				echo "		<option value='".strtolower($sub_row["menu_uuid"])."'>".$sub_row["menu_language"]." - ".$sub_row["menu_name"]."</option>\n";
+				echo "		<option value='".strtolower($sub_row["menu_uuid"])."'>".escape($sub_row["menu_language"])." - ".escape($sub_row["menu_name"])."</option>\n";
 			}
 		}
 		unset ($sub_prep_statement);
@@ -474,10 +474,10 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 					$dir_label = str_replace('_', ' ', $dir_name);
 					$dir_label = str_replace('-', ' ', $dir_label);
 					if ($dir_name == $row['user_setting_value']) {
-						echo "		<option value='$dir_name' selected='selected'>".ucwords($dir_label)."</option>\n";
+						echo "		<option value='".escape($dir_name)."' selected='selected'>".ucwords($dir_label)."</option>\n";
 					}
 					else {
-						echo "		<option value='$dir_name'>".ucwords($dir_label)."</option>\n";
+						echo "		<option value='".escape($dir_name)."'>".ucwords($dir_label)."</option>\n";
 					}
 				}
 			}
@@ -532,7 +532,7 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 				echo "			<option value='".$val."' selected='selected'>(UTC ".$time_zone_offset_hours.":".$time_zone_offset_minutes.") ".$val."</option>\n";
 			}
 			else {
-				echo "			<option value='".$val."'>(UTC ".$time_zone_offset_hours.":".$time_zone_offset_minutes.") ".$val."</option>\n";
+				echo "			<option value='".$val."'>(UTC ".escape($time_zone_offset_hours).":".escape($time_zone_offset_minutes).") ".$val."</option>\n";
 			}
 			$previous_category = $category;
 			$x++;
@@ -546,7 +546,7 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 		echo "	</select>\n";
 	}
 	elseif ($subcategory == 'password' || substr_count($subcategory, '_password') > 0 || $category == "login" && $subcategory == "password_reset_key" && $name == "text") {
-		echo "	<input class='formfld' type='password' id='user_setting_value' name='user_setting_value' maxlength='255' onmouseover=\"this.type='text';\" onfocus=\"this.type='text';\" onmouseout=\"if (!$(this).is(':focus')) { this.type='password'; }\" onblur=\"this.type='password';\" value=\"".$row['user_setting_value']."\">\n";
+		echo "	<input class='formfld' type='password' id='user_setting_value' name='user_setting_value' maxlength='255' onmouseover=\"this.type='text';\" onfocus=\"this.type='text';\" onmouseout=\"if (!$(this).is(':focus')) { this.type='password'; }\" onblur=\"this.type='password';\" value=\"".escape($row['user_setting_value'])."\">\n";
 	}
 	elseif ($category == "theme" && substr_count($subcategory, "_color") > 0 && ($name == "text" || $name == 'array')) {
 		echo "	<input type='text' class='formfld colorpicker' id='user_setting_value' name='user_setting_value' value=\"".$row['user_setting_value']."\">\n";
@@ -572,10 +572,10 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 			echo "		<option value='' disabled='disabled'></option>\n";
 			echo "		<option value='' ".(($row['user_setting_value'] != '' && $option_found == false) ? 'selected' : null).">".$text['label-other']."...</option>\n";
 			echo "	</select>";
-			echo "	<input type='text' class='formfld' ".(($row['user_setting_value'] == '' || $option_found) ? "style='display: none;'" : null)." id='txt_user_setting_value' name='user_setting_value' value=\"".$row['user_setting_value']."\">\n";
+			echo "	<input type='text' class='formfld' ".(($row['user_setting_value'] == '' || $option_found) ? "style='display: none;'" : null)." id='txt_user_setting_value' name='user_setting_value' value=\"".escape($row['user_setting_value'])."\">\n";
 		}
 		else {
-			echo "	<input type='text' class='formfld' id='user_setting_value' name='user_setting_value' value=\"".$row['user_setting_value']."\">\n";
+			echo "	<input type='text' class='formfld' id='user_setting_value' name='user_setting_value' value=\"".escape($row['user_setting_value'])."\">\n";
 		}
 	}
 	elseif ($category == "fax" && $subcategory == "page_size" && $name == "text" ) {
@@ -641,7 +641,7 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 		echo "    </select>\n";
 	}
 	else {
-		echo "	<input class='formfld' type='text' id='user_setting_value' name='user_setting_value' maxlength='255' value=\"".$row['user_setting_value']."\">\n";
+		echo "	<input class='formfld' type='text' id='user_setting_value' name='user_setting_value' maxlength='255' value=\"".escape($row['user_setting_value'])."\">\n";
 	}
 	echo "<br />\n";
 	echo $text['description-value']."\n";
@@ -712,7 +712,7 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 	echo "	".$text['label-description']."\n";
 	echo "</td>\n";
 	echo "<td class='vtable' align='left'>\n";
-	echo "	<input class='formfld' type='text' name='user_setting_description' maxlength='255' value=\"".$user_setting_description."\">\n";
+	echo "	<input class='formfld' type='text' name='user_setting_description' maxlength='255' value=\"".escape($user_setting_description)."\">\n";
 	echo "<br />\n";
 	echo $text['description-description']."\n";
 	echo "</td>\n";
@@ -720,9 +720,9 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 
 	echo "	<tr>\n";
 	echo "		<td colspan='2' align='right'>\n";
-	echo "			<input type='hidden' name='user_uuid' value='$user_uuid'>\n";
+	echo "			<input type='hidden' name='user_uuid' value='".escape($user_uuid)."'>\n";
 	if ($action == "update") {
-		echo "		<input type='hidden' name='user_setting_uuid' value='$user_setting_uuid'>\n";
+		echo "		<input type='hidden' name='user_setting_uuid' value='".escape($user_setting_uuid)."'>\n";
 	}
 	echo "			<br />";
 	echo "			<input type='button' class='btn' value='".$text['button-save']."' onclick='submit_form();'>\n";
@@ -753,4 +753,4 @@ if (count($_POST) > 0 && strlen($_POST["persistformvar"]) == 0) {
 
 //include the footer
 	require_once "resources/footer.php";
-?>
+?>

+ 10 - 10
core/users/user_settings.php

@@ -52,7 +52,7 @@
 			$db->exec(check_sql($sql));
 			unset($sql);
 
-			messages::add($text['message-update']);
+			message::add($text['message-update']);
 			header("Location: user_edit.php?id=".$user_uuid);
 			exit;
 		}
@@ -99,6 +99,7 @@
 	$sql .= "and not ( ";
 	$sql .= "(user_setting_category = 'domain' and user_setting_subcategory = 'language') ";
 	$sql .= "or (user_setting_category = 'domain' and user_setting_subcategory = 'time_zone') ";
+	$sql .= "or (user_setting_category = 'message' and user_setting_subcategory = 'key') ";
 	$sql .= ") ";
 	if (strlen($order_by) == 0) {
 		$sql .= "order by user_setting_category, user_setting_subcategory, user_setting_order asc ";
@@ -109,8 +110,7 @@
 	$sql .= "limit $rows_per_page offset $offset ";
 	$prep_statement = $db->prepare(check_sql($sql));
 	$prep_statement->execute();
-	$result = $prep_statement->fetchAll(PDO::FETCH_NAMED);
-	$result_count = count($result);
+	$user_settings = $prep_statement->fetchAll(PDO::FETCH_NAMED);
 	unset ($prep_statement, $sql);
 
 	$c = 0;
@@ -120,9 +120,9 @@
 //show the content
 	echo "<table class='tr_hover' width='100%' border='0' cellpadding='0' cellspacing='0'>\n";
 
-	if ($result_count > 0) {
+	if (is_array($user_settings)) {
 		$previous_category = '';
-		foreach($result as $row) {
+		foreach($user_settings as $row) {
 			if ($previous_category != $row['user_setting_category']) {
 				$c = 0;
 				echo "<tr>\n";
@@ -234,20 +234,20 @@
 			echo "	<td valign='top' class='".$row_style[$c]." tr_link_void' style='text-align: center;'>\n";
 			echo "		<a href='?user_id=".$row['user_uuid']."&id[]=".$row['user_setting_uuid']."&enabled=".(($row['user_setting_enabled'] == 'true') ? 'false' : 'true')."'>".$text['label-'.$row['user_setting_enabled']]."</a>\n";
 			echo "	</td>\n";
-			echo "	<td valign='top' class='row_stylebg'>".$row['user_setting_description']."&nbsp;</td>\n";
+			echo "	<td valign='top' class='row_stylebg'>".escape($row['user_setting_description'])."&nbsp;</td>\n";
 			echo "	<td class='list_control_icons'>";
 			if (permission_exists('user_setting_edit')) {
-				echo "<a href='user_setting_edit.php?user_uuid=".$row['user_uuid']."&id=".$row['user_setting_uuid']."' alt='".$text['button-edit']."'>$v_link_label_edit</a>";
+				echo "<a href='user_setting_edit.php?user_uuid=".escape($row['user_uuid'])."&id=".escape($row['user_setting_uuid'])."' alt='".$text['button-edit']."'>$v_link_label_edit</a>";
 			}
 			if (permission_exists('user_setting_delete')) {
-				echo "<a href='user_setting_delete.php?user_uuid=".$row['user_uuid']."&id[]=".$row['user_setting_uuid']."' alt='".$text['button-delete']."' onclick=\"return confirm('".$text['confirm-delete']."')\">$v_link_label_delete</a>";
+				echo "<a href='user_setting_delete.php?user_uuid=".escape($row['user_uuid'])."&id[]=".escape($row['user_setting_uuid'])."' alt='".$text['button-delete']."' onclick=\"return confirm('".$text['confirm-delete']."')\">$v_link_label_delete</a>";
 			}
 			echo "	</td>\n";
 			echo "</tr>\n";
 			$previous_category = $row['user_setting_category'];
 			if ($c==0) { $c=1; } else { $c=0; }
 		} //end foreach
-		unset($sql, $result, $row_count);
+		unset($sql, $user_settings);
 	} //end if results
 
 	echo "<tr>\n";
@@ -260,7 +260,7 @@
 	if (permission_exists('user_setting_add')) {
 		echo 		"<a href='user_setting_edit.php?user_uuid=".check_str($_GET['id'])."' alt='".$text['button-add']."'>$v_link_label_add</a>";
 	}
-	if (permission_exists('user_setting_delete') && $result_count > 0) {
+	if (permission_exists('user_setting_delete') && is_array($user_settings)) {
 		echo "<a href='javascript:void(0);' onclick=\"if (confirm('".$text['confirm-delete']."')) { document.getElementById('frm_settings').submit(); }\" alt='".$text['button-delete']."'>".$v_link_label_delete."</a>";
 	}
 	echo "		</td>\n";

+ 61 - 63
core/users/users.php

@@ -17,7 +17,7 @@
 
 	The Initial Developer of the Original Code is
 	Mark J Crane <[email protected]>
-	Portions created by the Initial Developer are Copyright (C) 2008-2016
+	Portions created by the Initial Developer are Copyright (C) 2008-2019
 	the Initial Developer. All Rights Reserved.
 
 	Contributor(s):
@@ -50,57 +50,26 @@
 //set the variables
 	$order_by = check_str($_GET["order_by"]);
 	$order = check_str($_GET["order"]);
-	$search_value = check_str($_REQUEST["search_value"]);
+	$search = check_str($_REQUEST["search"]);
+	if (strlen($search) > 0) {
+		$search = strtolower($search);
+	}
 
 //get the list of superadmins
 	$superadmins = superadmin_list($db);
 
-//get the users' group(s) from the database
-	$sql = "select ";
-	$sql .= "	gu.*, g.domain_uuid as group_domain_uuid ";
-	$sql .= "from ";
-	$sql .= "	v_group_users as gu, ";
-	$sql .= "	v_groups as g ";
-	$sql .= "where ";
-	$sql .= "	gu.group_uuid = g.group_uuid ";
-	if (!(permission_exists('user_all') && $_GET['show'] == 'all')) {
-		$sql .= "	and (";
-		$sql .= "		g.domain_uuid = '".$domain_uuid."' ";
-		$sql .= "		or g.domain_uuid is null ";
-		$sql .= "	) ";
-		$sql .= "	and gu.domain_uuid = '".$domain_uuid."' ";
-	}
-	$sql .= "order by ";
-	$sql .= "	g.domain_uuid desc, ";
-	$sql .= "	g.group_name asc ";
-	$prep_statement = $db->prepare(check_sql($sql));
-	$prep_statement->execute();
-	$result = $prep_statement->fetchAll(PDO::FETCH_NAMED);
-	if (count($result) > 0) {
-		foreach($result as $row) {
-			$user_groups[$row['user_uuid']][] = $row['group_name'].(($row['group_domain_uuid'] != '') ? "@".$_SESSION['domains'][$row['group_domain_uuid']]['domain_name'] : null);
-		}
-	}
-	unset ($sql, $prep_statement);
-
-//get total user count from the database
-	$sql = "select count(*) as num_rows from v_users where 1 = 1 ";
+//get the user count from the database
+	$sql = "select count(*) as num_rows from view_users where 1 = 1 ";
 	if (!(permission_exists('user_all') && $_GET['show'] == 'all')) {
 		$sql .= "and domain_uuid = '".$_SESSION['domain_uuid']."' ";
 	}
-	$prep_statement = $db->prepare($sql);
-	if ($prep_statement) {
-		$prep_statement->execute();
-		$row = $prep_statement->fetch(PDO::FETCH_ASSOC);
-		$total_users = $row['num_rows'];
+	if (strlen($search) > 0) {
+		$sql .= "and (lower(username) like '%".$search."%' \n";
+		$sql .= "or lower(groups) like '%".$search."%' \n";
+		$sql .= "or lower(contact_organization) like '%".$search."%' \n";
+		$sql .= "or lower(contact_name_given) like '%".$search."%' \n";
+		$sql .= "or lower(contact_name_family) like '%".$search."%') \n";
 	}
-	unset($prep_statement, $row);
-
-//get the users from the database (reuse $sql from above)
-	if (strlen($search_value) > 0) {
-		$sql .= "and username = '".$search_value."' ";
-	}
-	if (strlen($order_by) > 0) { $sql .= "order by ".$order_by." ".$order." "; }
 	$prep_statement = $db->prepare($sql);
 	if ($prep_statement) {
 		$prep_statement->execute();
@@ -113,8 +82,10 @@
 		}
 	}
 	unset ($prep_statement, $result, $sql);
+
+//prepare for paging
 	$rows_per_page = ($_SESSION['domain']['paging']['numeric'] != '') ? $_SESSION['domain']['paging']['numeric'] : 50;
-	$param = "search=".escape($search_value);
+	$param = "search=".escape($search);
 	if (permission_exists('user_all') && $_GET['show'] == 'all') {
 		$param .= "&show=all";
 	}
@@ -123,24 +94,36 @@
 	list($paging_controls, $rows_per_page, $var_3) = paging($num_rows, $param, $rows_per_page);
 	$offset = $rows_per_page * $page;
 
-	$sql = "select * from v_users where 1 = 1 ";
+//get the users from the database
+	$sql = "select u.domain_uuid, u.user_uuid, u.contact_uuid, u.domain_name, u.username, u.user_enabled, u.contact_organization, u.contact_name_given, u.contact_name_family, u.groups \n";
+	$sql .= "from view_users as u \n";
+	$sql .= "where 1 = 1 \n";
 	if (!(permission_exists('user_all') && $_GET['show'] == 'all')) {
-		$sql .= "and domain_uuid = '".$_SESSION['domain_uuid']."' ";
+		$sql .= "and u.domain_uuid = '".$_SESSION['domain_uuid']."' \n";
 	}
-	if (strlen($search_value) > 0) {
-		$sql .= "and username like '%".$search_value."%' ";
+	if (strlen($search) > 0) {
+		$sql .= "and (lower(username) like '%".$search."%' \n";
+		$sql .= "or lower(groups) like '%".$search."%' \n";
+		$sql .= "or lower(contact_organization) like '%".$search."%' \n";
+		$sql .= "or lower(contact_name_given) like '%".$search."%' \n";
+		$sql .= "or lower(contact_name_family) like '%".$search."%') \n";
 	}
 	if (strlen($order_by)> 0) {
-		$sql .= "order by ".$order_by." ".$order." ";
+		$sql .= "order by ".$order_by." ".$order." \n";
 	}
 	else {
-		$sql .= "order by username asc ";
+		$sql .= "order by u.username asc \n";
 	}
-	$sql .= " limit ".$rows_per_page." offset ".$offset." ";
+	$sql .= "limit ".$rows_per_page." offset ".$offset." ";
 	$prep_statement = $db->prepare(check_sql($sql));
 	$prep_statement->execute();
 	$users = $prep_statement->fetchAll(PDO::FETCH_NAMED);
-	$user_count = count($users);
+	//if (!$users) {
+	//	echo "<pre>\n";
+	//	print_r($prep_statement->errorInfo());
+	//	echo "</pre>\n";
+	//	exit;
+	//}
 	unset ($prep_statement, $sql);
 
 //page title and description
@@ -159,9 +142,9 @@
 		}
 	}
 	if (permission_exists('user_import')) {
-		echo 				"<input type='button' class='btn' alt='".$text['button-import']."' onclick=\"window.location='/app/user_imports/user_imports.php'\" value='".$text['button-import']."'>\n";
+		echo 				"<input type='button' class='btn' alt='".$text['button-import']."' onclick=\"window.location='user_imports.php'\" value='".$text['button-import']."'>\n";
 	}
-	echo 	"<input type='text' class='txt' style='width: 150px; margin-left: 15px; margin-right: 3px;' name='search_value' value=\"".escape($search_value)."\">";
+	echo 	"<input type='text' class='txt' style='width: 150px; margin-left: 15px; margin-right: 3px;' name='search' value=\"".escape($search)."\">";
 	echo 	"<input type='submit' class='btn' name='submit' value='".$text['button-search']."'>";
 	echo "</td>";
 	echo "</tr>\n";
@@ -180,7 +163,7 @@
 	$row_style["0"] = "row_style0";
 	$row_style["1"] = "row_style1";
 
-//show the data
+//show the users
 	echo "<table class='tr_hover' width='100%' border='0' cellpadding='0' cellspacing='0'>\n";
 
 	echo "<tr>\n";
@@ -188,7 +171,15 @@
 		echo th_order_by('domain_name', $text['label-domain'], $order_by, $order, '', '', $param);
 	}
 	echo th_order_by('username', $text['label-username'], $order_by, $order);
-	echo "<th>".$text['label-groups']."</th>\n";
+	echo th_order_by('groups', $text['label-groups'], $order_by, $order, '', '', $param);
+	echo th_order_by('contact_organization', $text['label-organization'], $order_by, $order, '', '', $param);
+	echo th_order_by('contact_name_given', $text['label-name'], $order_by, $order, '', '', $param);
+	if (permission_exists('ticket_edit')) {
+		echo "<th>".$text['label-tools']."</th>\n";
+	}
+	else {
+		echo "<th>&nbsp;</th>\n";
+	}
 	echo th_order_by('user_enabled', $text['label-enabled'], $order_by, $order, '', '', $param);
 	echo "<td class='list_control_icons'>";
 	if (permission_exists('user_add')) {
@@ -207,7 +198,7 @@
 				$tr_link = (permission_exists('user_edit')) ? "href='user_edit.php?id=".escape($row['user_uuid'])."'" : null;
 				echo "<tr ".$tr_link.">\n";
 				if (permission_exists('user_all') && $_GET['show'] == 'all') {
-					echo "	<td valign='top' class='".$row_style[$c]."'>".escape($_SESSION['domains'][$row['domain_uuid']]['domain_name'])."</td>\n";
+					echo "	<td valign='top' class='".$row_style[$c]."'>".escape($row['domain_name'])."</td>\n";
 				}
 				echo "	<td valign='top' class='".$row_style[$c]."'>";
 				if (permission_exists('user_edit')) {
@@ -217,11 +208,18 @@
 					echo escape($row['username']);
 				}
 				echo "	</td>\n";
-				echo "	<td valign='top' class='".$row_style[$c]."'>";
-				if (sizeof($user_groups[$row['user_uuid']]) > 0) {
-					echo escape(implode(', ', $user_groups[$row['user_uuid']]));
+				echo "	<td valign='top' class='".$row_style[$c]."'>\n";
+				echo "		".$row['groups']."&nbsp;\n";
+				echo "	</td>\n";
+
+				echo "	<td class='".$row_style[$c]."'><a href='/app/contacts/contact_edit.php?id=".$row['contact_uuid']."'>".$row['contact_organization']."</a> &nbsp;</td>\n";
+				echo "	<td class='".$row_style[$c]."'><a href='/app/contacts/contact_edit.php?id=".$row['contact_uuid']."'>".$row['contact_name_given']." ".$row['contact_name_family']."</a> &nbsp;</td>\n";
+
+				echo "	<td class='".$row_style[$c]."'>\n";
+				if (permission_exists('ticket_edit')) {
+					echo "		<a href='/app/tickets/tickets.php?user_uuid=".$row['user_uuid']."'><span class='glyphicon glyphicon-tags' title='".$text['label-tickets']."'></span></a>\n";
 				}
-				echo "&nbsp;</td>\n";
+				echo "	</td>\n";
 				echo "	<td valign='top' class='".$row_style[$c]."'>";
 				if ($row['user_enabled'] == 'true') {
 					echo $text['option-true'];
@@ -247,7 +245,7 @@
 				if ($c==0) { $c=1; } else { $c=0; }
 			}
 		} //end foreach
-		unset($sql, $users, $user_count);
+		unset($sql, $users);
 	} //end if results
 
 	echo "<tr>\n";

+ 568 - 80
resources/app_languages.php

@@ -441,6 +441,27 @@ $text['button-save']['sv-se'] = "Spara";
 $text['button-save']['uk-ua'] = "Зберегти";
 $text['button-save']['tr-tr'] = "Kaydet";
 
+$text['button-send']['en-us'] = "Send";
+$text['button-send']['ar-eg'] = "";
+$text['button-send']['de-at'] = "";
+$text['button-send']['de-ch'] = "";
+$text['button-send']['de-de'] = "";
+$text['button-send']['es-cl'] = "";
+$text['button-send']['es-mx'] = "";
+$text['button-send']['fr-ca'] = "";
+$text['button-send']['fr-fr'] = "";
+$text['button-send']['he-il'] = "";
+$text['button-send']['it-it'] = "";
+$text['button-send']['nl-nl'] = "";
+$text['button-send']['pl-pl'] = "";
+$text['button-send']['pt-br'] = "";
+$text['button-send']['pt-pt'] = "";
+$text['button-send']['ro-ro'] = "";
+$text['button-send']['ru-ru'] = "";
+$text['button-send']['sv-se'] = "";
+$text['button-send']['uk-ua'] = "";
+$text['button-send']['tr-tr'] = "";
+
 $text['button-search']['en-us'] = "Search";
 $text['button-search']['ar-eg'] = "";
 $text['button-search']['de-at'] = "Suchen"; //copied from de-de
@@ -1175,6 +1196,47 @@ $text['label-summary']['sv-se'] = "";
 $text['label-summary']['uk-ua'] = "";
 $text['label-summary']['tr-tr'] = "Özet";
 
+$text['header-import']['en-us'] = "Import";
+$text['header-import']['ar-eg'] = "";
+$text['header-import']['de-at'] = "Importieren"; //copied from de-de
+$text['header-import']['de-ch'] = "Importieren"; //copied from de-de
+$text['header-import']['de-de'] = "Importieren";
+$text['header-import']['es-cl'] = "Importar";
+$text['header-import']['es-mx'] = "Importar"; //copied from es-cl
+$text['header-import']['fr-ca'] = "Importer"; //copied from fr-fr
+$text['header-import']['fr-fr'] = "Importer";
+$text['header-import']['he-il'] = "";
+$text['header-import']['it-it'] = "";
+$text['header-import']['nl-nl'] = "";
+$text['header-import']['pl-pl'] = "Importuj";
+$text['header-import']['pt-br'] = "Importar";
+$text['header-import']['pt-pt'] = "Importat";
+$text['header-import']['ro-ro'] = "";
+$text['header-import']['ru-ru'] = "Импорт";
+$text['header-import']['sv-se'] = "Importera";
+$text['header-import']['uk-ua'] = "";
+$text['header-import']['tr-tr'] = "İçe Aktar";
+
+$text['description-import']['en-us'] = "Upload delimitted data to add multiple records.";
+$text['description-import']['ar-eg'] = "";
+$text['description-import']['de-at'] = "";
+$text['description-import']['de-ch'] = "";
+$text['description-import']['de-de'] = "";
+$text['description-import']['es-cl'] = "";
+$text['description-import']['es-mx'] = "";
+$text['description-import']['fr-ca'] = "";
+$text['description-import']['fr-fr'] = "";
+$text['description-import']['he-il'] = "";
+$text['description-import']['it-it'] = "";
+$text['description-import']['nl-nl'] = "";
+$text['description-import']['pl-pl'] = "";
+$text['description-import']['pt-br'] = "";
+$text['description-import']['pt-pt'] = "";
+$text['description-import']['ro-ro'] = "";
+$text['description-import']['ru-ru'] = "";
+$text['description-import']['sv-se'] = "";
+$text['description-import']['uk-ua'] = "";
+
 $text['label-import_data']['en-us'] = "Data";
 $text['label-import_data']['ar-eg'] = "";
 $text['label-import_data']['de-at'] = "Daten"; //copied from de-de
@@ -1259,6 +1321,46 @@ $text['label-import_file_upload']['sv-se'] = "Fil att ladda upp";
 $text['label-import_file_upload']['uk-ua'] = "Файл для завантаження";
 $text['label-import_file_upload']['tr-tr'] = "Yüklenecek Dosya";
 
+$text['label-from_row']['en-us'] = "From Row";
+$text['label-from_row']['ar-eg'] = "";
+$text['label-from_row']['de-at'] = "";
+$text['label-from_row']['de-ch'] = "";
+$text['label-from_row']['de-de'] = "";
+$text['label-from_row']['es-cl'] = "";
+$text['label-from_row']['es-mx'] = "";
+$text['label-from_row']['fr-ca'] = "";
+$text['label-from_row']['fr-fr'] = "";
+$text['label-from_row']['he-il'] = "";
+$text['label-from_row']['it-it'] = "";
+$text['label-from_row']['nl-nl'] = "";
+$text['label-from_row']['pl-pl'] = "";
+$text['label-from_row']['pt-br'] = "";
+$text['label-from_row']['pt-pt'] = "";
+$text['label-from_row']['ro-ro'] = "";
+$text['label-from_row']['ru-ru'] = "";
+$text['label-from_row']['sv-se'] = "";
+$text['label-from_row']['uk-ua'] = "";
+
+$text['description-from_row']['en-us'] = "Start importing the data from this row.";
+$text['description-from_row']['ar-eg'] = "";
+$text['description-from_row']['de-at'] = "";
+$text['description-from_row']['de-ch'] = "";
+$text['description-from_row']['de-de'] = "";
+$text['description-from_row']['es-cl'] = "";
+$text['description-from_row']['es-mx'] = "";
+$text['description-from_row']['fr-ca'] = "";
+$text['description-from_row']['fr-fr'] = "";
+$text['description-from_row']['he-il'] = "";
+$text['description-from_row']['it-it'] = "";
+$text['description-from_row']['nl-nl'] = "";
+$text['description-from_row']['pl-pl'] = "";
+$text['description-from_row']['pt-br'] = "";
+$text['description-from_row']['pt-pt'] = "";
+$text['description-from_row']['ro-ro'] = "";
+$text['description-from_row']['ru-ru'] = "";
+$text['description-from_row']['sv-se'] = "";
+$text['description-from_row']['uk-ua'] = "";
+
 $text['description-import_data']['en-us'] = "Copy and paste the comma delimitted data into the text area to begin the import.";
 $text['description-import_data']['ar-eg'] = "";
 $text['description-import_data']['de-at'] = "Kopieren Sie die komma-getrennten Daten in den Textbereich um den Import zu starten."; //copied from de-de
@@ -1322,26 +1424,26 @@ $text['description-import_enclosure']['sv-se'] = "Välj inkapsling av text (dubb
 $text['description-import_enclosure']['uk-ua'] = "";
 $text['description-import_enclosure']['tr-tr'] = "Metin sonlandırmasını seçin (çift tırnak ya da hiçbir şey).";
 
-$text['option-yesterday']['en-us'] = "Yesterday";
-$text['option-yesterday']['ar-eg'] = "";
-$text['option-yesterday']['de-at'] = "Gestern"; //copied from de-de
-$text['option-yesterday']['de-ch'] = "Gestern"; //copied from de-de
-$text['option-yesterday']['de-de'] = "Gestern";
-$text['option-yesterday']['es-cl'] = "Ayer";
-$text['option-yesterday']['es-mx'] = "Ayer"; //copied from es-cl
-$text['option-yesterday']['fr-ca'] = "Hier"; //copied from fr-fr
-$text['option-yesterday']['fr-fr'] = "Hier";
-$text['option-yesterday']['he-il'] = "";
-$text['option-yesterday']['it-it'] = "";
-$text['option-yesterday']['nl-nl'] = "";
-$text['option-yesterday']['pl-pl'] = "Wczoraj";
-$text['option-yesterday']['pt-br'] = "Ontem"; //copied from pt-pt
-$text['option-yesterday']['pt-pt'] = "Ontem";
-$text['option-yesterday']['ro-ro'] = "";
-$text['option-yesterday']['ru-ru'] = "Вчера";
-$text['option-yesterday']['sv-se'] = "Igår";
-$text['option-yesterday']['uk-ua'] = "Вчора";
-$text['option-yesterday']['tr-tr'] = "Dün";
+$text['option-last_hour']['en-us'] = "Last Hour";
+$text['option-last_hour']['ar-eg'] = "";
+$text['option-last_hour']['de-at'] = "Letzte Stunde"; //copied from de-de
+$text['option-last_hour']['de-ch'] = "Letzte Stunde"; //copied from de-de
+$text['option-last_hour']['de-de'] = "Letzte Stunde";
+$text['option-last_hour']['es-cl'] = "Ultima Hora";
+$text['option-last_hour']['es-mx'] = "Ultima Hora"; //copied from es-cl
+$text['option-last_hour']['fr-ca'] = "Dernière Heure"; //copied from fr-fr
+$text['option-last_hour']['fr-fr'] = "Dernière Heure";
+$text['option-last_hour']['he-il'] = "";
+$text['option-last_hour']['it-it'] = "";
+$text['option-last_hour']['nl-nl'] = "";
+$text['option-last_hour']['pl-pl'] = "W ostatniej godzinie";
+$text['option-last_hour']['pt-br'] = "Próxima hora";
+$text['option-last_hour']['pt-pt'] = "Última Hora";
+$text['option-last_hour']['ro-ro'] = "";
+$text['option-last_hour']['ru-ru'] = "За последний час";
+$text['option-last_hour']['sv-se'] = "Senaste Timman";
+$text['option-last_hour']['uk-ua'] = "За останню годину";
+$text['option-last_hour']['tr-tr'] = "Geçtiğimiz Saat";
 
 $text['option-today']['en-us'] = "Today";
 $text['option-today']['ar-eg'] = "";
@@ -1364,26 +1466,26 @@ $text['option-today']['sv-se'] = "Idag";
 $text['option-today']['uk-ua'] = "Сьогодні";
 $text['option-today']['tr-tr'] = "Bugün";
 
-$text['option-this_year']['en-us'] = "This Year";
-$text['option-this_year']['ar-eg'] = "";
-$text['option-this_year']['de-at'] = "Dieses Jahr"; //copied from de-de
-$text['option-this_year']['de-ch'] = "Dieses Jahr"; //copied from de-de
-$text['option-this_year']['de-de'] = "Dieses Jahr";
-$text['option-this_year']['es-cl'] = "Este Año";
-$text['option-this_year']['es-mx'] = "Este Año"; //copied from es-cl
-$text['option-this_year']['fr-ca'] = "Cette Année"; //copied from fr-fr
-$text['option-this_year']['fr-fr'] = "Cette Année";
-$text['option-this_year']['he-il'] = "";
-$text['option-this_year']['it-it'] = "";
-$text['option-this_year']['nl-nl'] = "";
-$text['option-this_year']['pl-pl'] = "W tym roku";
-$text['option-this_year']['pt-br'] = "Este ano";
-$text['option-this_year']['pt-pt'] = "Este Ano";
-$text['option-this_year']['ro-ro'] = "";
-$text['option-this_year']['ru-ru'] = "В этом году";
-$text['option-this_year']['sv-se'] = "Detta Året";
-$text['option-this_year']['uk-ua'] = "Цього року";
-$text['option-this_year']['tr-tr'] = "Bu Yıl";
+$text['option-yesterday']['en-us'] = "Yesterday";
+$text['option-yesterday']['ar-eg'] = "";
+$text['option-yesterday']['de-at'] = "Gestern"; //copied from de-de
+$text['option-yesterday']['de-ch'] = "Gestern"; //copied from de-de
+$text['option-yesterday']['de-de'] = "Gestern";
+$text['option-yesterday']['es-cl'] = "Ayer";
+$text['option-yesterday']['es-mx'] = "Ayer"; //copied from es-cl
+$text['option-yesterday']['fr-ca'] = "Hier"; //copied from fr-fr
+$text['option-yesterday']['fr-fr'] = "Hier";
+$text['option-yesterday']['he-il'] = "";
+$text['option-yesterday']['it-it'] = "";
+$text['option-yesterday']['nl-nl'] = "";
+$text['option-yesterday']['pl-pl'] = "Wczoraj";
+$text['option-yesterday']['pt-br'] = "Ontem"; //copied from pt-pt
+$text['option-yesterday']['pt-pt'] = "Ontem";
+$text['option-yesterday']['ro-ro'] = "";
+$text['option-yesterday']['ru-ru'] = "Вчера";
+$text['option-yesterday']['sv-se'] = "Igår";
+$text['option-yesterday']['uk-ua'] = "Вчора";
+$text['option-yesterday']['tr-tr'] = "Dün";
 
 $text['option-this_week']['en-us'] = "This Week";
 $text['option-this_week']['ar-eg'] = "";
@@ -1406,6 +1508,27 @@ $text['option-this_week']['sv-se'] = "Denna Månaden";
 $text['option-this_week']['uk-ua'] = "Цього тижня";
 $text['option-this_week']['tr-tr'] = "Bu Hafta";
 
+$text['option-last_seven_days']['en-us'] = "Last 7 Days";
+$text['option-last_seven_days']['ar-eg'] = "";
+$text['option-last_seven_days']['de-at'] = "Letzte 7 Tage"; //copied from de-de
+$text['option-last_seven_days']['de-ch'] = "Letzte 7 Tage"; //copied from de-de
+$text['option-last_seven_days']['de-de'] = "Letzte 7 Tage";
+$text['option-last_seven_days']['es-cl'] = "Últimos 7 días";
+$text['option-last_seven_days']['es-mx'] = "Últimos 7 días"; //copied from es-cl
+$text['option-last_seven_days']['fr-ca'] = "Les 7 Derniers Jours"; //copied from fr-fr
+$text['option-last_seven_days']['fr-fr'] = "Les 7 Derniers Jours";
+$text['option-last_seven_days']['he-il'] = "";
+$text['option-last_seven_days']['it-it'] = "";
+$text['option-last_seven_days']['nl-nl'] = "";
+$text['option-last_seven_days']['pl-pl'] = "Ostatnie 7 Dni";
+$text['option-last_seven_days']['pt-br'] = "Nos últimos 7 Dias"; //copied from pt-pt
+$text['option-last_seven_days']['pt-pt'] = "Nos últimos 7 Dias";
+$text['option-last_seven_days']['ro-ro'] = "";
+$text['option-last_seven_days']['ru-ru'] = "За последние 7 дней";
+$text['option-last_seven_days']['sv-se'] = "Senaste 7 Dagarna";
+$text['option-last_seven_days']['uk-ua'] = "За останні 7 днів";
+$text['option-last_seven_days']['tr-tr'] = "Geçtiğimiz 7 Gün";
+
 $text['option-this_month']['en-us'] = "This Month";
 $text['option-this_month']['ar-eg'] = "";
 $text['option-this_month']['de-at'] = "Diesen Monat"; //copied from de-de
@@ -1427,47 +1550,131 @@ $text['option-this_month']['sv-se'] = "Denna Månaden";
 $text['option-this_month']['uk-ua'] = "Цього місяця";
 $text['option-this_month']['tr-tr'] = "Bu Ay";
 
-$text['option-last_seven_days']['en-us'] = "Last 7 Days";
-$text['option-last_seven_days']['ar-eg'] = "";
-$text['option-last_seven_days']['de-at'] = "Letzte 7 Tage"; //copied from de-de
-$text['option-last_seven_days']['de-ch'] = "Letzte 7 Tage"; //copied from de-de
-$text['option-last_seven_days']['de-de'] = "Letzte 7 Tage";
-$text['option-last_seven_days']['es-cl'] = "Últimos 7 días";
-$text['option-last_seven_days']['es-mx'] = "Últimos 7 días"; //copied from es-cl
-$text['option-last_seven_days']['fr-ca'] = "Les 7 Derniers Jours"; //copied from fr-fr
-$text['option-last_seven_days']['fr-fr'] = "Les 7 Derniers Jours";
-$text['option-last_seven_days']['he-il'] = "";
-$text['option-last_seven_days']['it-it'] = "";
-$text['option-last_seven_days']['nl-nl'] = "";
-$text['option-last_seven_days']['pl-pl'] = "Ostatnie 7 Dni";
-$text['option-last_seven_days']['pt-br'] = "Nos últimos 7 Dias"; //copied from pt-pt
-$text['option-last_seven_days']['pt-pt'] = "Nos últimos 7 Dias";
-$text['option-last_seven_days']['ro-ro'] = "";
-$text['option-last_seven_days']['ru-ru'] = "За последние 7 дней";
-$text['option-last_seven_days']['sv-se'] = "Senaste 7 Dagarna";
-$text['option-last_seven_days']['uk-ua'] = "За останні 7 днів";
-$text['option-last_seven_days']['tr-tr'] = "Geçtiğimiz 7 Gün";
+$text['option-this_year']['en-us'] = "This Year";
+$text['option-this_year']['ar-eg'] = "";
+$text['option-this_year']['de-at'] = "Dieses Jahr"; //copied from de-de
+$text['option-this_year']['de-ch'] = "Dieses Jahr"; //copied from de-de
+$text['option-this_year']['de-de'] = "Dieses Jahr";
+$text['option-this_year']['es-cl'] = "Este Año";
+$text['option-this_year']['es-mx'] = "Este Año"; //copied from es-cl
+$text['option-this_year']['fr-ca'] = "Cette Année"; //copied from fr-fr
+$text['option-this_year']['fr-fr'] = "Cette Année";
+$text['option-this_year']['he-il'] = "";
+$text['option-this_year']['it-it'] = "";
+$text['option-this_year']['nl-nl'] = "";
+$text['option-this_year']['pl-pl'] = "W tym roku";
+$text['option-this_year']['pt-br'] = "Este ano";
+$text['option-this_year']['pt-pt'] = "Este Ano";
+$text['option-this_year']['ro-ro'] = "";
+$text['option-this_year']['ru-ru'] = "В этом году";
+$text['option-this_year']['sv-se'] = "Detta Året";
+$text['option-this_year']['uk-ua'] = "Цього року";
+$text['option-this_year']['tr-tr'] = "Bu Yıl";
 
-$text['option-last_hour']['en-us'] = "Last Hour";
-$text['option-last_hour']['ar-eg'] = "";
-$text['option-last_hour']['de-at'] = "Letzte Stunde"; //copied from de-de
-$text['option-last_hour']['de-ch'] = "Letzte Stunde"; //copied from de-de
-$text['option-last_hour']['de-de'] = "Letzte Stunde";
-$text['option-last_hour']['es-cl'] = "Ultima Hora";
-$text['option-last_hour']['es-mx'] = "Ultima Hora"; //copied from es-cl
-$text['option-last_hour']['fr-ca'] = "Dernière Heure"; //copied from fr-fr
-$text['option-last_hour']['fr-fr'] = "Dernière Heure";
-$text['option-last_hour']['he-il'] = "";
-$text['option-last_hour']['it-it'] = "";
-$text['option-last_hour']['nl-nl'] = "";
-$text['option-last_hour']['pl-pl'] = "W ostatniej godzinie";
-$text['option-last_hour']['pt-br'] = "Próxima hora";
-$text['option-last_hour']['pt-pt'] = "Última Hora";
-$text['option-last_hour']['ro-ro'] = "";
-$text['option-last_hour']['ru-ru'] = "За последний час";
-$text['option-last_hour']['sv-se'] = "Senaste Timman";
-$text['option-last_hour']['uk-ua'] = "За останню годину";
-$text['option-last_hour']['tr-tr'] = "Geçtiğimiz Saat";
+$text['option-hour']['en-us'] = "Hour";
+$text['option-hour']['ar-eg'] = "";
+$text['option-hour']['de-at'] = ""; //copied from de-de
+$text['option-hour']['de-ch'] = ""; //copied from de-de
+$text['option-hour']['de-de'] = "";
+$text['option-hour']['es-cl'] = "";
+$text['option-hour']['es-mx'] = ""; //copied from es-cl
+$text['option-hour']['fr-ca'] = ""; //copied from fr-fr
+$text['option-hour']['fr-fr'] = "";
+$text['option-hour']['he-il'] = "";
+$text['option-hour']['it-it'] = "";
+$text['option-hour']['nl-nl'] = "";
+$text['option-hour']['pl-pl'] = "";
+$text['option-hour']['pt-br'] = "";
+$text['option-hour']['pt-pt'] = "";
+$text['option-hour']['ro-ro'] = "";
+$text['option-hour']['ru-ru'] = "";
+$text['option-hour']['sv-se'] = "";
+$text['option-hour']['uk-ua'] = "";
+$text['option-hour']['tr-tr'] = "";
+
+$text['option-day']['en-us'] = "Day";
+$text['option-day']['ar-eg'] = "";
+$text['option-day']['de-at'] = ""; //copied from de-de
+$text['option-day']['de-ch'] = ""; //copied from de-de
+$text['option-day']['de-de'] = "";
+$text['option-day']['es-cl'] = "";
+$text['option-day']['es-mx'] = ""; //copied from es-cl
+$text['option-day']['fr-ca'] = ""; //copied from fr-fr
+$text['option-day']['fr-fr'] = "";
+$text['option-day']['he-il'] = "";
+$text['option-day']['it-it'] = "";
+$text['option-day']['nl-nl'] = "";
+$text['option-day']['pl-pl'] = "";
+$text['option-day']['pt-br'] = "";
+$text['option-day']['pt-pt'] = "";
+$text['option-day']['ro-ro'] = "";
+$text['option-day']['ru-ru'] = "";
+$text['option-day']['sv-se'] = "";
+$text['option-day']['uk-ua'] = "";
+$text['option-day']['tr-tr'] = "";
+
+$text['option-week']['en-us'] = "Week";
+$text['option-week']['ar-eg'] = "";
+$text['option-week']['de-at'] = "Woche"; //copied from de-de
+$text['option-week']['de-ch'] = "Woche"; //copied from de-de
+$text['option-week']['de-de'] = "Woche";
+$text['option-week']['es-cl'] = "Semana";
+$text['option-week']['es-mx'] = "Semana"; //copied from es-cl
+$text['option-week']['fr-ca'] = "Semaine"; //copied from fr-fr
+$text['option-week']['fr-fr'] = "Semaine";
+$text['option-week']['he-il'] = "";
+$text['option-week']['it-it'] = "";
+$text['option-week']['nl-nl'] = "";
+$text['option-week']['pl-pl'] = "W tym miesiącu";
+$text['option-week']['pt-br'] = "mês";
+$text['option-week']['pt-pt'] = "Semana";
+$text['option-week']['ro-ro'] = "";
+$text['option-week']['ru-ru'] = "На этой неделе";
+$text['option-week']['sv-se'] = "Månaden";
+$text['option-week']['uk-ua'] = "Цього тижня";
+$text['option-week']['tr-tr'] = "Bu Hafta";
+
+$text['option-month']['en-us'] = "Month";
+$text['option-month']['ar-eg'] = "";
+$text['option-month']['de-at'] = "Monat"; //copied from de-de
+$text['option-month']['de-ch'] = "Monat"; //copied from de-de
+$text['option-month']['de-de'] = "Monat";
+$text['option-month']['es-cl'] = "Mes";
+$text['option-month']['es-mx'] = "Mes"; //copied from es-cl
+$text['option-month']['fr-ca'] = "Mois"; //copied from fr-fr
+$text['option-month']['fr-fr'] = "Mois";
+$text['option-month']['he-il'] = "";
+$text['option-month']['it-it'] = "";
+$text['option-month']['nl-nl'] = "";
+$text['option-month']['pl-pl'] = "Miesiącu";
+$text['option-month']['pt-br'] = "Mês";
+$text['option-month']['pt-pt'] = "Mês";
+$text['option-month']['ro-ro'] = "";
+$text['option-month']['ru-ru'] = "В этом месяце";
+$text['option-month']['sv-se'] = "Denna Månaden";
+$text['option-month']['uk-ua'] = "Цього місяця";
+$text['option-month']['tr-tr'] = "Bu Ay";
+
+$text['option-year']['en-us'] = "Year";
+$text['option-year']['ar-eg'] = "";
+$text['option-year']['de-at'] = "Jahr"; //copied from de-de
+$text['option-year']['de-ch'] = "Jahr"; //copied from de-de
+$text['option-year']['de-de'] = "Jahr";
+$text['option-year']['es-cl'] = "Año";
+$text['option-year']['es-mx'] = "Año"; //copied from es-cl
+$text['option-year']['fr-ca'] = "Année"; //copied from fr-fr
+$text['option-year']['fr-fr'] = "Année";
+$text['option-year']['he-il'] = "";
+$text['option-year']['it-it'] = "";
+$text['option-year']['nl-nl'] = "";
+$text['option-year']['pl-pl'] = "W tym roku";
+$text['option-year']['pt-br'] = "Ano";
+$text['option-year']['pt-pt'] = "Ano";
+$text['option-year']['ro-ro'] = "";
+$text['option-year']['ru-ru'] = "В этом году";
+$text['option-year']['sv-se'] = "Året";
+$text['option-year']['uk-ua'] = "Цього року";
+$text['option-year']['tr-tr'] = "Bu Yıl";
 
 $text['option-default']['en-us'] = "Default";
 $text['option-default']['ar-eg'] = "";
@@ -2099,6 +2306,27 @@ $text['label-order']['sv-se'] = "Ordning";
 $text['label-order']['uk-ua'] = "Інше";
 $text['label-order']['tr-tr'] = "Sipariş";
 
+$text['label-add']['en-us'] = "Add";
+$text['label-add']['ar-eg'] = "اضافة";
+$text['label-add']['de-at'] = "Hinzufügen"; //copied from de-de
+$text['label-add']['de-ch'] = "Hinzufügen"; //copied from de-de
+$text['label-add']['de-de'] = "Hinzufügen";
+$text['label-add']['es-cl'] = "Agregar";
+$text['label-add']['es-mx'] = "Agregar"; //copied from es-cl
+$text['label-add']['fr-ca'] = "Ajouter"; //copied from fr-fr
+$text['label-add']['fr-fr'] = "Ajouter";
+$text['label-add']['he-il'] = " להוסיף";
+$text['label-add']['it-it'] = "Inserisci";
+$text['label-add']['nl-nl'] = "";
+$text['label-add']['pl-pl'] = "Dodaj";
+$text['label-add']['pt-br'] = "Adicionar"; //copied from pt-pt
+$text['label-add']['pt-pt'] = "Adicionar";
+$text['label-add']['ro-ro'] = "Adăuga";
+$text['label-add']['ru-ru'] = "Добавить";
+$text['label-add']['sv-se'] = "Lägg Till";
+$text['label-add']['uk-ua'] = "Додати";
+$text['label-add']['tr-tr'] = "Ekle";
+
 $text['label-delete']['en-us'] = "Delete";
 $text['label-delete']['ar-eg'] = "";
 $text['label-delete']['de-at'] = "Löschen"; //copied from de-de
@@ -2120,6 +2348,46 @@ $text['label-delete']['sv-se'] = "Ta Bort";
 $text['label-delete']['uk-ua'] = "Видалити";
 $text['label-delete']['tr-tr'] = "Sil";
 
+$text['label-actions']['en-us'] = "Actions";
+$text['label-actions']['ar-eg'] = "الأفعال";
+$text['label-actions']['de-at'] = "Aktionen"; //copied from de-de
+$text['label-actions']['de-ch'] = "Aktionen"; //copied from de-de
+$text['label-actions']['de-de'] = "Aktionen";
+$text['label-actions']['es-cl'] = "Accións";
+$text['label-actions']['es-mx'] = "Accións"; //copied from es-cl
+$text['label-actions']['fr-ca'] = "Actions"; //copied from fr-fr
+$text['label-actions']['fr-fr'] = "Actions";
+$text['label-actions']['he-il'] = "פעולות";
+$text['label-actions']['it-it'] = "Azioni";
+$text['label-actions']['nl-nl'] = "";
+$text['label-actions']['pl-pl'] = "Operacje (gdzie przesłać rozmowę).";
+$text['label-actions']['pt-br'] = "Ações"; //copied from pt-pt
+$text['label-actions']['pt-pt'] = "Ações";
+$text['label-actions']['ro-ro'] = "";
+$text['label-actions']['ru-ru'] = "Действия";
+$text['label-actions']['sv-se'] = "Åtgärder";
+$text['label-actions']['uk-ua'] = "Дії";
+
+$text['label-context']['en-us'] = "Context";
+$text['label-context']['ar-eg'] = "";
+$text['label-context']['de-at'] = "Kontext"; //copied from de-de
+$text['label-context']['de-ch'] = "Kontext"; //copied from de-de
+$text['label-context']['de-de'] = "Kontext";
+$text['label-context']['es-cl'] = "Contexto";
+$text['label-context']['es-mx'] = "Contexto"; //copied from es-cl
+$text['label-context']['fr-ca'] = "Contexte"; //copied from fr-fr
+$text['label-context']['fr-fr'] = "Contexte";
+$text['label-context']['he-il'] = "";
+$text['label-context']['it-it'] = "Contesto";
+$text['label-context']['nl-nl'] = "";
+$text['label-context']['pl-pl'] = "Kontekst";
+$text['label-context']['pt-br'] = "Contexto"; //copied from pt-pt
+$text['label-context']['pt-pt'] = "Contexto";
+$text['label-context']['ro-ro'] = "";
+$text['label-context']['ru-ru'] = "Контекст";
+$text['label-context']['sv-se'] = "Context";
+$text['label-context']['uk-ua'] = "Контекст";
+  
 $text['label-music_on_hold']['en-us'] = "Music on Hold";
 $text['label-music_on_hold']['ar-eg'] = "موسيقى المؤجلة";
 $text['label-music_on_hold']['de-at'] = "Wartemusik"; //copied from de-de
@@ -2698,6 +2966,206 @@ $text['label-caller_id_name']['ru-ru'] = "Caller ID Имя";
 $text['label-caller_id_name']['sv-se'] = "Namnpresentation";
 $text['label-caller_id_name']['uk-ua'] = "Caller ID Ім’я";
 
+$text['label-characters']['en-us'] = "Characters";
+$text['label-characters']['ar-eg'] = "الشخصيات";
+$text['label-characters']['de-at'] = "Zeichen"; //copied from de-de
+$text['label-characters']['de-ch'] = "Zeichen"; //copied from de-de
+$text['label-characters']['de-de'] = "Zeichen";
+$text['label-characters']['es-cl'] = "Caracteres";
+$text['label-characters']['es-mx'] = "Caracteres"; //copied from es-cl
+$text['label-characters']['fr-ca'] = "Personnages"; //copied from fr-fr
+$text['label-characters']['fr-fr'] = "Personnages";
+$text['label-characters']['he-il'] = "דמויות";
+$text['label-characters']['it-it'] = "Caratteri";
+$text['label-characters']['nl-nl'] = "";
+$text['label-characters']['pl-pl'] = "Postacie";
+$text['label-characters']['pt-br'] = "Personagens"; //copied from pt-pt
+$text['label-characters']['pt-pt'] = "Personagens";
+$text['label-characters']['ro-ro'] = "caractere";
+$text['label-characters']['ru-ru'] = "символов";
+$text['label-characters']['sv-se'] = "Tecken";
+$text['label-characters']['uk-ua'] = "персонажі";
+
+$text['label-numbers']['en-us'] = "Numbers";
+$text['label-numbers']['ar-eg'] = "أرقام";
+$text['label-numbers']['de-at'] = "Nummern"; //copied from de-de
+$text['label-numbers']['de-ch'] = "Nummern"; //copied from de-de
+$text['label-numbers']['de-de'] = "Nummern";
+$text['label-numbers']['es-cl'] = "Números";
+$text['label-numbers']['es-mx'] = "Números"; //copied from es-cl
+$text['label-numbers']['fr-ca'] = "Nombres"; //copied from fr-fr
+$text['label-numbers']['fr-fr'] = "Nombres";
+$text['label-numbers']['he-il'] = "מספרים";
+$text['label-numbers']['it-it'] = "Numeri";
+$text['label-numbers']['nl-nl'] = "";
+$text['label-numbers']['pl-pl'] = "Liczby";
+$text['label-numbers']['pt-br'] = "Números"; //copied from pt-pt
+$text['label-numbers']['pt-pt'] = "Números";
+$text['label-numbers']['ro-ro'] = "numere";
+$text['label-numbers']['ru-ru'] = "Цифры";
+$text['label-numbers']['sv-se'] = "Nummer";
+$text['label-numbers']['uk-ua'] = "чисел";
+
+$text['label-lowercase_letters']['en-us'] = "Lowercase Letters";
+$text['label-lowercase_letters']['ar-eg'] = "أحرف صغيرة";
+$text['label-lowercase_letters']['de-at'] = "Kleinbuchstaben"; //copied from de-de
+$text['label-lowercase_letters']['de-ch'] = "Kleinbuchstaben"; //copied from de-de
+$text['label-lowercase_letters']['de-de'] = "Kleinbuchstaben";
+$text['label-lowercase_letters']['es-cl'] = "Letras minusculas";
+$text['label-lowercase_letters']['es-mx'] = "Letras minusculas"; //copied from es-cl
+$text['label-lowercase_letters']['fr-ca'] = "Minuscules"; //copied from fr-fr
+$text['label-lowercase_letters']['fr-fr'] = "Minuscules";
+$text['label-lowercase_letters']['he-il'] = "אותיות קטנות";
+$text['label-lowercase_letters']['it-it'] = "Lettere Minuscole";
+$text['label-lowercase_letters']['nl-nl'] = "";
+$text['label-lowercase_letters']['pl-pl'] = "Małe litery";
+$text['label-lowercase_letters']['pt-br'] = "Letras minúsculas"; //copied from pt-pt
+$text['label-lowercase_letters']['pt-pt'] = "Letras minúsculas";
+$text['label-lowercase_letters']['ro-ro'] = "Litere mici";
+$text['label-lowercase_letters']['ru-ru'] = "Строчные буквы";
+$text['label-lowercase_letters']['sv-se'] = "Gemener";
+$text['label-lowercase_letters']['uk-ua'] = "Букви нижнього регістру";
+
+$text['label-uppercase_letters']['en-us'] = "Uppercase Letters";
+$text['label-uppercase_letters']['ar-eg'] = "الأحرف الكبيرة";
+$text['label-uppercase_letters']['de-at'] = "Großbuchstaben"; //copied from de-de
+$text['label-uppercase_letters']['de-ch'] = "Großbuchstaben"; //copied from de-de
+$text['label-uppercase_letters']['de-de'] = "Großbuchstaben";
+$text['label-uppercase_letters']['es-cl'] = "Letras mayúsculas";
+$text['label-uppercase_letters']['es-mx'] = "Letras mayúsculas"; //copied from es-cl
+$text['label-uppercase_letters']['fr-ca'] = "Lettres capitales"; //copied from fr-fr
+$text['label-uppercase_letters']['fr-fr'] = "Lettres capitales";
+$text['label-uppercase_letters']['he-il'] = "אותיות רישיות";
+$text['label-uppercase_letters']['it-it'] = "Lettere Maiuscole";
+$text['label-uppercase_letters']['nl-nl'] = "";
+$text['label-uppercase_letters']['pl-pl'] = "Wielkie litery";
+$text['label-uppercase_letters']['pt-br'] = "Letras maiúsculas"; //copied from pt-pt
+$text['label-uppercase_letters']['pt-pt'] = "Letras maiúsculas";
+$text['label-uppercase_letters']['ro-ro'] = "Litere mari";
+$text['label-uppercase_letters']['ru-ru'] = "Заглавные буквы";
+$text['label-uppercase_letters']['sv-se'] = "Versala bokstäver";
+$text['label-uppercase_letters']['uk-ua'] = "Великі літери";
+
+$text['label-special_characters']['en-us'] = "Special Characters";
+$text['label-special_characters']['ar-eg'] = "أحرف خاصة";
+$text['label-special_characters']['de-at'] = "Sonderzeichen"; //copied from de-de
+$text['label-special_characters']['de-ch'] = "Sonderzeichen"; //copied from de-de
+$text['label-special_characters']['de-de'] = "Sonderzeichen";
+$text['label-special_characters']['es-cl'] = "Caracteres especiales";
+$text['label-special_characters']['es-mx'] = "Caracteres especiales"; //copied from es-cl
+$text['label-special_characters']['fr-ca'] = "Caractères spéciaux"; //copied from fr-fr
+$text['label-special_characters']['fr-fr'] = "Caractères spéciaux";
+$text['label-special_characters']['he-il'] = "תווים מיוחדים";
+$text['label-special_characters']['it-it'] = "Caratteri Speciali";
+$text['label-special_characters']['nl-nl'] = "";
+$text['label-special_characters']['pl-pl'] = "Znaki specjalne";
+$text['label-special_characters']['pt-br'] = "Caracteres especiais"; //copied from pt-pt
+$text['label-special_characters']['pt-pt'] = "Caracteres especiais";
+$text['label-special_characters']['ro-ro'] = "caractere speciale";
+$text['label-special_characters']['ru-ru'] = "Специальные символы";
+$text['label-special_characters']['sv-se'] = "Speciella Karaktärer";
+$text['label-special_characters']['uk-ua'] = "спеціальні символи";
+
+$text['label-bridges']['en-us'] = 'Bridges';
+$text['label-bridges']['ar-eg'] = '';
+$text['label-bridges']['de-at'] = '';
+$text['label-bridges']['de-ch'] = '';
+$text['label-bridges']['de-de'] = '';
+$text['label-bridges']['es-cl'] = '';
+$text['label-bridges']['es-mx'] = '';
+$text['label-bridges']['fr-ca'] = '';
+$text['label-bridges']['fr-fr'] = '';
+$text['label-bridges']['he-il'] = '';
+$text['label-bridges']['it-it'] = '';
+$text['label-bridges']['nl-nl'] = '';
+$text['label-bridges']['pl-pl'] = '';
+$text['label-bridges']['pt-br'] = '';
+$text['label-bridges']['pt-pt'] = '';
+$text['label-bridges']['ro-ro'] = '';
+$text['label-bridges']['ru-ru'] = '';
+$text['label-bridges']['sv-se'] = '';
+$text['label-bridges']['uk-ua'] = '';
+
+$text['label-interval']['en-us'] = "Interval";
+$text['label-interval']['ar-eg'] = "";
+$text['label-interval']['de-at'] = "Intervall"; //copied from de-de
+$text['label-interval']['de-ch'] = "Intervall"; //copied from de-de
+$text['label-interval']['de-de'] = "Intervall";
+$text['label-interval']['es-cl'] = "Intervalo";
+$text['label-interval']['es-mx'] = "Intervalo"; //copied from es-cl
+$text['label-interval']['fr-ca'] = "Intervalle"; //copied from fr-fr
+$text['label-interval']['fr-fr'] = "Intervalle";
+$text['label-interval']['he-il'] = "";
+$text['label-interval']['it-it'] = "Intervallo";
+$text['label-interval']['nl-nl'] = "";
+$text['label-interval']['pl-pl'] = "Interwał";
+$text['label-interval']['pt-br'] = "Intervalo"; //copied from pt-pt
+$text['label-interval']['pt-pt'] = "Intervalo";
+$text['label-interval']['ro-ro'] = "";
+$text['label-interval']['ru-ru'] = "Интервал";
+$text['label-interval']['sv-se'] = "Intervall";
+$text['label-interval']['uk-ua'] = "Інтервал";
+
+$text['label-peak']['en-us'] = "Peak";
+$text['label-peak']['ar-eg'] = "";
+$text['label-peak']['de-at'] = "";
+$text['label-peak']['de-ch'] = "";
+$text['label-peak']['de-de'] = "";
+$text['label-peak']['es-cl'] = "";
+$text['label-peak']['es-mx'] = "";
+$text['label-peak']['fr-ca'] = "";
+$text['label-peak']['fr-fr'] = "";
+$text['label-peak']['he-il'] = "";
+$text['label-peak']['it-it'] = "";
+$text['label-peak']['nl-nl'] = "";
+$text['label-peak']['pl-pl'] = "";
+$text['label-peak']['pt-br'] = "";
+$text['label-peak']['pt-pt'] = "";
+$text['label-peak']['ro-ro'] = "";
+$text['label-peak']['ru-ru'] = "";
+$text['label-peak']['sv-se'] = "";
+$text['label-peak']['uk-ua'] = "";
+
+$text['label-tools']['en-us'] = "Tools";
+$text['label-tools']['ar-eg'] = "الادوات";
+$text['label-tools']['de-at'] = "Funktionen"; //copied from de-de
+$text['label-tools']['de-ch'] = "Funktionen"; //copied from de-de
+$text['label-tools']['de-de'] = "Funktionen";
+$text['label-tools']['es-cl'] = "Herramientas";
+$text['label-tools']['es-mx'] = "Herramientas"; //copied from es-cl
+$text['label-tools']['fr-ca'] = "Outils"; //copied from fr-fr
+$text['label-tools']['fr-fr'] = "Outils";
+$text['label-tools']['he-il'] = "כלים";
+$text['label-tools']['it-it'] = "Strumenti";
+$text['label-tools']['nl-nl'] = "";
+$text['label-tools']['pl-pl'] = "Narzędzia";
+$text['label-tools']['pt-br'] = "Ferramentas"; //copied from pt-pt
+$text['label-tools']['pt-pt'] = "Ferramentas";
+$text['label-tools']['ro-ro'] = "Utilitare";
+$text['label-tools']['ru-ru'] = "Инструменты";
+$text['label-tools']['sv-se'] = "Verktyg";
+$text['label-tools']['uk-ua'] = "Налаштування";
+
+$text['label-tickets']['en-us'] = "Tickets";
+$text['label-tickets']['ar-eg'] = "";
+$text['label-tickets']['de-at'] = ""; //copied from de-de
+$text['label-tickets']['de-ch'] = ""; //copied from de-de
+$text['label-tickets']['de-de'] = "";
+$text['label-tickets']['es-cl'] = "";
+$text['label-tickets']['es-mx'] = ""; //copied from es-cl
+$text['label-tickets']['fr-ca'] = ""; //copied from fr-fr
+$text['label-tickets']['fr-fr'] = "";
+$text['label-tickets']['he-il'] = "";
+$text['label-tickets']['it-it'] = "";
+$text['label-tickets']['nl-nl'] = "";
+$text['label-tickets']['pl-pl'] = "";
+$text['label-tickets']['pt-br'] = ""; //copied from pt-pt
+$text['label-tickets']['pt-pt'] = "";
+$text['label-tickets']['ro-ro'] = "";
+$text['label-tickets']['ru-ru'] = "";
+$text['label-tickets']['sv-se'] = "";
+$text['label-tickets']['uk-ua'] = "";
+
 $text['description-greeting']['en-us'] = "Select the desired Greeting.";
 $text['description-greeting']['ar-eg'] = "";
 $text['description-greeting']['de-at'] = "Geben Sie die Begrüßungs-ID an."; //copied from de-de
@@ -2865,4 +3333,24 @@ $text['description-enabled']['sv-se'] = "";
 $text['description-enabled']['uk-ua'] = "";
 $text['description-enabled']['tr-tr'] = "";
 
+$text['description-enter-context']['en-us'] = "Enter the context.";
+$text['description-enter-context']['ar-eg'] = "";
+$text['description-enter-context']['de-at'] = "Geben Sie den Kontext ein."; //copied from de-de
+$text['description-enter-context']['de-ch'] = "Geben Sie den Kontext ein."; //copied from de-de
+$text['description-enter-context']['de-de'] = "Geben Sie den Kontext ein.";
+$text['description-enter-context']['es-cl'] = "Ingrese un contexto";
+$text['description-enter-context']['es-mx'] = "Ingrese un contexto"; //copied from es-cl
+$text['description-enter-context']['fr-ca'] = "Entrez le contexte"; //copied from fr-fr
+$text['description-enter-context']['fr-fr'] = "Entrez le contexte";
+$text['description-enter-context']['he-il'] = "";
+$text['description-enter-context']['it-it'] = "Inserire il contesto.";
+$text['description-enter-context']['nl-nl'] = "";
+$text['description-enter-context']['pl-pl'] = "Wprowadź kontekst";
+$text['description-enter-context']['pt-br'] = "Insira um contexto";
+$text['description-enter-context']['pt-pt'] = "Introduza um contexto.";
+$text['description-enter-context']['ro-ro'] = "";
+$text['description-enter-context']['ru-ru'] = "Введите контекст.";
+$text['description-enter-context']['sv-se'] = "Ange Context";
+$text['description-enter-context']['uk-ua'] = "";
+
 ?>

+ 0 - 124
resources/captcha/img.php

@@ -1,124 +0,0 @@
-<?php
-/*
-	FusionPBX
-	Version: MPL 1.1
-
-	The contents of this file are subject to the Mozilla Public License Version
-	1.1 (the "License"); you may not use this file except in compliance with
-	the License. You may obtain a copy of the License at
-	http://www.mozilla.org/MPL/
-
-	Software distributed under the License is distributed on an "AS IS" basis,
-	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-	for the specific language governing rights and limitations under the
-	License.
-
-	The Original Code is FusionPBX
-
-	The Initial Developer of the Original Code is
-	Mark J Crane <[email protected]>
-	Portions created by the Initial Developer are Copyright (C) 2008-2012
-	the Initial Developer. All Rights Reserved.
-
-	Contributor(s):
-	Mark J Crane <[email protected]>
-*/
-include "root.php";
-require_once "config.php";
-error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING ); //hide notices and warnings
-
-//start the session
-ini_set("session.cookie_httponly", True);
-if (!isset($_SESSION)) { session_start(); }
-
-// Captcha verification image -----------------------
-// Description this page is used to verify the captcha
-
-$_SESSION["captcha"] = substr(md5(date('r')), 0, 6);
-$text = $_SESSION["captcha"];
-//echo $text;
-exit;
-
-
-function isfile($filename) {
-    if (@filesize($filename) > 0) { return true; } else { return false; }
-}
-
-function dircontents($dir) {
-  clearstatcache();
-  $htmldirlist = '';
-  $htmlfilelist = '';
-  $dirlist = opendir($dir);
-  while ($file = readdir ($dirlist)) {
-      if ($file != '.' && $file != '..') {
-          $newpath = $dir.'/'.$file;
-           $level = explode('/',$newpath);
-
-           if (is_dir($newpath)) {
-                //do nothing
-           }
-           else {
-                $mod_array[] = end($level);
-           }
-       }
-   }
-
-   closedir($dirlist);
-   return $mod_array;
-}
-
-$fontarray = dircontents($pathtofonts);
-//print_r($fontarray);
-
-function make_seed()
-{
-  list($usec, $sec) = explode(' ', microtime());
-  return (float) $sec + ((float) $usec * 100000);
-}
-srand(make_seed());
-$random = (rand()%count($fontarray));
-$font = $pathtofonts.$fontarray[$random];
-//echo $font;
-
-//echo phpinfo();
-//exit;
-
-$fontsize = 16;
-if(@$_GET['fontsize']) {
-	$fontsize = $_GET['fontsize'];
-}
-
-//picked up from a note at http://www.php.net/imagettfbbox
-function imagettfbbox_custom($size, $angle, $font, $text) {
-  $dummy = imagecreate(1, 1);
-  $black = imagecolorallocate($dummy, 0, 0, 0);
-  $bbox = imagettftext($dummy, $size, $angle, 0, 0, $black, $font, $text);
-  imagedestroy($dummy);
-  return $bbox;
-}
-
-// Create the image
-$size = imagettfbbox_custom($fontsize, 0, $font, $text);
-$width = $size[2] + $size[0] + 8;
-$height = abs($size[1]) + abs($size[7]);
-//$width = 200;
-//$height =  200;
-
-$im = imagecreate($width, $height);
-
-$colourBlack = imagecolorallocate($im, 255, 255, 255);
-imagecolortransparent($im, $colourBlack);
-
-// Create some colors
-$white = imagecolorallocate($im, 255, 255, 255);
-$black = imagecolorallocate($im, 0, 0, 0);
-
-// Add the text
-imagefttext($im, $fontsize, 0, 0, abs($size[5]), $black, $font, $text);
-
-// Set the content-type
-header("Content-type: image/png");
-// Using imagepng() results in clearer text compared with
-imagepng($im);
-imagedestroy($im);
-?>

+ 2 - 2
resources/check_auth.php

@@ -100,13 +100,13 @@
 
 				//redirect the user to the login page
 					$target_path = ($_REQUEST["path"] != '') ? $_REQUEST["path"] : $_SERVER["PHP_SELF"];
-					messages::add($text['message-invalid_credentials'], 'negative');
+					message::add($text['message-invalid_credentials'], 'negative');
 					header("Location: ".PROJECT_PATH."/login.php?path=".urlencode($target_path));
 					exit;
 			}
 
 		//get the groups assigned to the user and then set the groups in $_SESSION["groups"]
-			$sql = "SELECT * FROM v_group_users ";
+			$sql = "SELECT * FROM v_user_groups ";
 			//$sql .= "where domain_uuid='".$domain_uuid."' ";
 			//$sql .= "and user_uuid='".$_SESSION["user_uuid"]."' ";
 			$sql .= "where domain_uuid=:domain_uuid ";

+ 7 - 6
resources/classes/cache.php

@@ -109,14 +109,15 @@ class cache {
 
 		//cache method file
 			if ($_SESSION['cache']['method']['text'] == "file") {
-				$key = str_replace(":", ".", $key);
+				//change the delimiter
+					$key = str_replace(":", ".", $key);
 
 				// connect to event socket
 					$fp = event_socket_create($_SESSION['event_socket_ip_address'], $_SESSION['event_socket_port'], $_SESSION['event_socket_password']);
 					if ($fp === false) {
 						return false;
 					}
-					
+
 				//send a custom event
 					$event = "sendevent CUSTOM\n";
 					$event .= "Event-Name: CUSTOM\n";
@@ -124,7 +125,7 @@ class cache {
 					$event .= "API-Command: cache\n";
 					$event .= "API-Command-Argument: delete ".$key."\n";
 					event_socket_request($fp, $event);
-				
+
 				//remove the local files
 					if (file_exists($_SESSION['cache']['location']['text'] . "/" . $key)) {
 						unlink($_SESSION['cache']['location']['text'] . "/" . $key);
@@ -149,7 +150,7 @@ class cache {
 					if ($fp === false) {
 						return false;
 					}
-		
+
 				//send a custom event
 					$event = "sendevent CUSTOM\n";
 					$event .= "Event-Name: CUSTOM\n";
@@ -157,11 +158,11 @@ class cache {
 					$event .= "API-Command: memcache\n";
 					$event .= "API-Command-Argument: flush\n";
 					event_socket_request($fp, $event);
-		
+
 				//run the memcache
 					$command = "memcache flush";
 					$result = event_socket_request($fp, 'api '.$command);
-		
+
 				//close event socket
 					fclose($fp);
 

+ 161 - 0
resources/classes/captcha.php

@@ -0,0 +1,161 @@
+<?php
+/*
+	FusionPBX
+	Version: MPL 1.1
+
+	The contents of this file are subject to the Mozilla Public License Version
+	1.1 (the "License"); you may not use this file except in compliance with
+	the License. You may obtain a copy of the License at
+	http://www.mozilla.org/MPL/
+
+	Software distributed under the License is distributed on an "AS IS" basis,
+	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+	for the specific language governing rights and limitations under the
+	License.
+
+	The Original Code is FusionPBX
+
+	The Initial Developer of the Original Code is
+	Mark J Crane <[email protected]>
+	Portions created by the Initial Developer are Copyright (C) 2019
+	the Initial Developer. All Rights Reserved.
+
+	Contributor(s):
+	Mark J Crane <[email protected]>
+*/
+
+/**
+ * captcha class
+ *
+ * @method string get
+ */
+class captcha {
+
+	/**
+	* Called when the object is created
+	*/
+	//public $db;
+	//public $domain_uuid;
+	public $code;
+
+	/**
+	* Class constructor
+	*/
+	public function __construct() {
+
+	}
+
+	/**
+	 * Called when there are no references to a particular object
+	 * unset the variables used in the class
+	 */
+	public function __destruct() {
+		foreach ($this as $key => $value) {
+			unset($this->$key);
+		}
+	}
+
+	/**
+	 * Create the captcha image
+	 * @var string $code
+	 */
+	public function image_captcha() {
+
+		//includes
+		include "root.php";
+		require_once "config.php";
+		require_once "resources/functions.php";
+		error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING ); //hide notices and warnings
+
+		//start the session
+		ini_set("session.cookie_httponly", True);
+		if (!isset($_SESSION)) { session_start(); }
+
+		//$_SESSION["captcha"] = substr(md5(uuid()), 0, 6);
+		//$text = $_SESSION["captcha"];
+		$text = $this->code;
+
+		// Set the font path
+		$font_path = $_SERVER["DOCUMENT_ROOT"]."/resources/captcha/fonts";
+
+		// Array of fonts
+		//$fonts[] = 'ROUGD.TTF';
+		//$fonts[] = 'Zebra.ttf';
+		//$fonts[] = 'hanshand.ttf';
+		$fonts = glob($font_path.'/*.[tT][tT][fF]');
+		//print_r($fonts);
+		//exit;
+
+		// Randomize the fonts
+		srand(uuid());
+		$random = (rand()%count($fonts));
+		//$font = $font_path.'/'.$fonts[$random];
+		$font = $fonts[$random];
+
+		// Set the font size
+		$font_size = 16;
+		if(@$_GET['fontsize']) {
+			$font_size = $_GET['fontsize'];
+		}
+
+		// Create the image
+		$size = $this->image_size($font_size, 0, $font, $text);
+		$width = $size[2] + $size[0] + 8;
+		$height = abs($size[1]) + abs($size[7]);
+		//$width = 100;
+		//$height =  40;
+
+		// Set the image size
+		$image = imagecreate($width, $height);
+
+		// Create some colors
+		$white = imagecolorallocate($image, 255, 255, 255);
+		$black = imagecolorallocate($image, 0, 0, 0);
+
+		// Set the transparent color
+		imagecolortransparent($image, $white);
+
+		// Add the text
+		imagefttext($image, $font_size, 0, 0, abs($size[5]), $black, $font, $text);
+
+		// Set the content-type
+		//header("Content-type: image/png");
+		//imagepng($image));
+
+		ob_start();
+		imagepng($image);
+		$image_buffer = ob_get_clean();
+		//echo "<img src=\"data:image/png;base64, ".base64_encode($image_buffer)."\" />\n";
+		imagedestroy($image);
+		return $image_buffer;
+	}
+
+	/**
+	 * return the image in base64
+	 */
+	public function image_base64() {
+		return base64_encode($this->image_captcha());
+	}
+
+	/**
+	 * Get the image size
+	 * @var string $value	string image size
+	 */
+	private function image_size($size, $angle, $font, $text) {
+		$dummy = imagecreate(1, 1);
+		$black = imagecolorallocate($dummy, 0, 0, 0);
+		$bbox = imagettftext($dummy, $size, $angle, 0, 0, $black, $font, $text);
+		imagedestroy($dummy);
+		return $bbox;
+	}
+
+}
+
+/*
+$captcha = new captcha;
+$captcha->code = 'abcdefg';
+$image_base64 = $captcha->base64();
+echo "<img src=\"data:image/png;base64, ".$image_base64."\" />\n";
+*/
+
+?>

+ 242 - 468
resources/classes/database.php

@@ -17,7 +17,7 @@
 
 	The Initial Developer of the Original Code is
 	Mark J Crane <[email protected]>
-	Copyright (C) 2010 - 2017
+	Copyright (C) 2010 - 2019
 	All Rights Reserved.
 
 	Contributor(s):
@@ -450,20 +450,47 @@ include "root.php";
 			}
 
 			// Use this function to execute complex queries
-			public function execute() {
+			public function execute($sql, $parameters = null) {
 
 				//connect to the database if needed
 					if (!$this->db) {
 						$this->connect();
 					}
 
-				//get data from the database
-					$prep_statement = $this->db->prepare($this->sql);
-					if ($prep_statement) {
-						$prep_statement->execute();
+				//set the error mode
+					$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+				//execute the query, and return the results
+					try {
+						$prep_statement = $this->db->prepare($sql);
+						if (is_array($parameters)) {
+							$prep_statement->execute($parameters);
+						}
+						else {
+							$prep_statement->execute();
+						}
+						$message["message"] = "OK";
+						$message["code"] = "200";
+						$message["sql"] = $sql;
+						if (is_array($parameters)) {
+							$message["parameters"] = $parameters;
+						}
+						$this->message = $message;
+						//$result = $prep_statement->fetchAll(PDO::FETCH_ASSOC);
+						//unset($prep_statement);
 						return $prep_statement->fetchAll(PDO::FETCH_ASSOC);
 					}
-					else {
+					catch(PDOException $e) {
+						$message["message"] = "Bad Request";
+						$message["code"] = "400";
+						$message["error"]["message"] = $e->getMessage();
+						if ($this->debug["sql"]) {
+							$message["sql"] = $sql;
+						}
+						if (is_array($parameters)) {
+							$message["parameters"] = $parameters;
+						}
+						$this->message = $message;
 						return false;
 					}
 			}
@@ -636,60 +663,6 @@ include "root.php";
 						$this->connect();
 					}
 
-				//sanitize the table name
-					$this->table = preg_replace('#[^a-zA-Z0-9_\-]#', '', $this->table);
-
-				//delete from the database
-					if (isset($this->table) && isset($this->where)) {
-						$i = 0;
-						$sql = "delete from ".$this->table." ";
-						if (is_array($this->where)) {
-							foreach($this->where as $row) {
-								//sanitize the name
-								$row['name'] = preg_replace('#[^a-zA-Z0-9_\-]#', '', $row['name']);
-
-								//validate the operator
-								switch ($row['operator']) {
-									case "<": break;
-									case ">": break;
-									case "<=": break;
-									case ">=": break;
-									case "=": break;
-									case ">=": break;
-									case "<>": break;
-									case "!=": break;
-									default:
-										//invalid operator
-										return false;
-								}
-
-								//build the sql
-								if ($i == 0) {
-									//$sql .= $row['name']." ".$row['operator']." '".$row['value']."' ";
-									$sql .= "where ".$row['name']." ".$row['operator']." :".$row['name']." ";
-								}
-								else {
-									//$sql .= $row['name']." ".$row['operator']." '".$row['value']."' ";
-									$sql .= "and ".$row['name']." ".$row['operator']." :".$row['name']." ";
-								}
-
-								//add the name and value to the params array
-								$params[$row['name']] = $row['value'];
-
-								//increment $i
-								$i++;
-							}
-						}
-						//echo $sql."<br>\n";
-						$prep_statement = $this->db->prepare($sql);
-						$prep_statement->execute($params);
-						unset($sql, $this->where);
-						return;
-					}
-
-				//return the array
-					if (!is_array($array)) { echo "not an array"; return false; }
-
 				//set the message id
 					$m = 0;
 
@@ -697,11 +670,9 @@ include "root.php";
 					if (!isset($this->app_name)) {
 						$this->app_name = $this->name;
 					}
-
-				//normalize the array structure
-					//$new_array = $this->normalize_array($array, $this->name);
-					//unset($array);
-					$new_array = $array;
+				
+				//set the table prefix
+					$table_prefix = 'v_';
 
 				//debug sql
 					$this->debug["sql"] = true;
@@ -711,339 +682,82 @@ include "root.php";
 
 				//debug info
 					//echo "<pre>\n";
-					//print_r($new_array);
+					//print_r($array);
 					//echo "</pre>\n";
 					//exit;
 
-				//get the $apps array from the installed apps from the core and mod directories
-					//$config_list = glob($_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/*/$schema_name/app_config.php");
-					/*
-					$x = 0;
-					if (is_array($config_list)) {
-						foreach ($config_list as &$config_path) {
-							include($config_path);
-							$x++;
-						}
-					}
-					$tables = $apps[0]['db'];
-					if (is_array($tables)) {
-						foreach ($tables as &$row) {
-							//print_r($row);
-							$table = $row['table'];
-							echo $table."\n";
-							foreach ($row['fields'] as &$field) {
-								if (isset($field['key']['type'])) {
-									print_r($field);
-								}
+				//get the current data
+					foreach($array as $table_name => $rows) {
+						foreach($rows as $row) {
+							$i = 0;
+							$sql = "select * from ".$table_prefix.$table_name." ";
+							foreach($row as $field_name => $field_value) {
+								if ($i == 0) { $sql .= "where "; } else { $sql .= "and "; }
+								$sql .= $field_name." = :".$field_name." ";
+								$parameters[$field_name] = $field_value;
+								$i++;
 							}
+							$old_array[$table_name] = $this->execute($sql, $parameters);
+							unset($parameters);
 						}
 					}
-					*/
-
-				//loop through the array
-					if (is_array($new_array)) {
-						foreach ($new_array as $schema_name => $schema_array) {
-
-							$this->name = preg_replace('#[^a-zA-Z0-9_\-]#', '', $schema_name);
-							if (is_array($schema_array)) {
-								foreach ($schema_array as $schema_id => $array) {
-
-									//set the variables
-										$table_name = "v_".$this->name;
-										$parent_key_name = $this->singular($this->name)."_uuid";
-
-									//if the uuid is set then set parent key exists and value 
-										//determine if the parent_key_exists
-										$parent_key_exists = false;
-										if (isset($array[$parent_key_name])) {
-											$parent_key_value = $array[$parent_key_name];
-											$parent_key_exists = true;
-										}
-										else {
-											if (isset($this->uuid)) {
-												$parent_key_exists = true;
-												$parent_key_value = $this->uuid;
-											}
-											else {
-												$parent_key_value = uuid();
-											}
-										}
-
-									//get the parent field names
-										$parent_field_names = array();
-										if (is_array($array)) {
-											foreach ($array as $key => $value) {
-												if (!is_array($value)) {
-													$parent_field_names[] = $key;
-												}
-											}
-										}
-
-									//get the data before the delete
-										if ($parent_key_exists) {
-											$sql = "SELECT * FROM ".$table_name." ";
-											$sql .= "WHERE ".$parent_key_name." = '".$parent_key_value."' ";
-											$prep_statement = $this->db->prepare($sql);
-											if ($prep_statement) {
-												//get the data
-													try {
-														$prep_statement->execute();
-														$result = $prep_statement->fetchAll(PDO::FETCH_ASSOC);
-													}
-													catch(PDOException $e) {
-														echo 'Caught exception: ',  $e->getMessage(), "<br/><br/>\n";
-														echo $sql;
-														exit;
-													}
-
-												//set the action
-													if (count($result) > 0) {
-														$action = "delete";
-														$old_array[$schema_name] = $result;
-													}
-													else {
-														$action = "";
-													}
-											}
-											unset($prep_statement);
-											unset($result);
-										}
-										else {
-											$action = "";
-										}
-
-									//delete a specific uuid
-										if ($action == "delete") {
-											if (permission_exists($this->singular($this->name).'_delete') && strlen($parent_key_value) > 0
-												&& ($parent_key_exists) &&  is_uuid($parent_key_value)) {
-												//set the table name
-													$table_name = 'v_'.$this->name;
-
-												//parent data
-													$sql = "DELETE FROM $table_name ";
-													$sql .= "WHERE $parent_key_name = '$parent_key_value' ;";
-													//echo $sql;
-													//$sql = "DELETE FROM :table_name ";
-													//$sql .= "WHERE :parent_key_name = ':parent_key_value'; ";
-													//$statement = $this->db->prepare($sql);
-													//$statement->bindParam(':table_name', $table_name);
-													//$statement->bindParam(':parent_key_name', $parent_key_name);
-													//$statement->bindParam(':parent_key_value', $parent_key_value);
-													$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-													try {
-														$this->db->query(check_sql($sql));
-														//$statement->execute();
-														$message["message"] = "OK";
-														$message["code"] = "200";
-														$message["uuid"] = $parent_key_value;
-														$message["details"][$m]["name"] = $this->name;
-														$message["details"][$m]["message"] = "OK";
-														$message["details"][$m]["code"] = "200";
-														$message["details"][$m]["uuid"] = $parent_key_value;
-														if ($this->debug["sql"]) {
-															$message["details"][$m]["sql"] = $sql;
-														}
-														$this->message = $message;
-														$m++;
-														unset($sql);
-														unset($statement);
-													}
-													catch(PDOException $e) {
-														$message["message"] = "Bad Request";
-														$message["code"] = "400";
-														$message["details"][$m]["name"] = $this->name;
-														$message["details"][$m]["message"] = $e->getMessage();
-														$message["details"][$m]["code"] = "400";
-														if ($this->debug["sql"]) {
-															$message["details"][$m]["sql"] = $sql;
-														}
-														$this->message = $message;
-														$m++;
-													}
-											}
-											else {
-												$message["name"] = $this->name;
-												$message["message"] = "Forbidden, does not have '".$this->singular($this->name)."_delete'";
-												$message["code"] = "403";
-												$message["line"] = __line__;
-												$this->message = $message;
-												$m++;
-											}
-										}
-
-									//unset the variables
-										unset($sql, $action);
-
-									//child data
-										if (is_array($array)) {
-											foreach ($array as $key => $value) {
-
-												if (is_array($value)) {
-														$table_name = "v_".$key;
-														foreach ($value as $id => $row) {
-															//prepare the variables
-																$child_name = $this->singular($key);
-																$child_key_name = $child_name."_uuid";
-
-															//determine if the parent key exists in the child array
-																$parent_key_exists = false;
-																if (!isset($array[$parent_key_name])) {
-																	$parent_key_exists = true;
-																}
-
-															//determine if the uuid exists
-																$uuid_exists = false;
-																if (is_array($row)) {
-																	foreach ($row as $k => $v) {
-																		if ($child_key_name == $k) {
-																			if (strlen($v) > 0) {
-																				$child_key_value = $v;
-																				$uuid_exists = true;
-																				break;
-																			}
-																		}
-																		else {
-																			$uuid_exists = false;
-																		}
-																	}
-																}
-
-															//get the child field names
-																$child_field_names = array();
-																if (is_array($row)) {
-																	foreach ($row as $k => $v) {
-																		if (!is_array($v)) {
-																			$child_field_names[] = $k;
-																		}
-																	}
-																}
-
-															//get the child data
-																if ($uuid_exists) {
-																	$sql = "SELECT * FROM ".$table_name." ";
-																	$sql .= "WHERE ".$child_key_name." = '".$child_key_value."' ";
-																	$prep_statement = $this->db->prepare($sql);
-																	if ($prep_statement) {
-																		//get the data
-																			$prep_statement->execute();
-																			$child_array = $prep_statement->fetch(PDO::FETCH_ASSOC);
-																		//set the action
-																			if (is_array($child_array)) {
-																				$action = "delete";
-																			}
-																			else {
-																				$action = "";
-																			}
-																		//add to the parent array
-																			if (is_array($child_array)) {
-																				$old_array[$schema_name][$schema_id][$key][] = $child_array;
-																			}
-																	}
-																	unset($prep_statement);
-																}
-																else {
-																	$action = "";
-																}
-
-															//delete the child data
-																if ($action == "delete") {
-																	if (permission_exists($child_name.'_delete')) {
-																		$sql = "DELETE FROM ".$table_name." ";
-																		$sql .= "WHERE ".$child_key_name." = '".$child_key_value."' ";
-																		if (strlen($parent_key_value) > 0) { $sql .= "AND ".$parent_key_name." = '".$parent_key_value."' "; }
-																		//$sql = "DELETE FROM :table_name ";
-																		//$sql .= "WHERE :child_key_name = ':child_key_value' ";
-																		//if (strlen($parent_key_value) > 0) { $sql .= "AND :parent_key_name = ':parent_key_value' }";
-																		//$statement = $this->db->prepare($sql);
-																		//$statement->bindParam(':table_name', $table_name);
-																		//$statement->bindParam(':parent_key_name', $parent_key_name);
-																		//$statement->bindParam(':parent_key_value', $parent_key_value);
-																		//$statement->bindParam(':child_key_name', $child_key_name);
-																		//$statement->bindParam(':child_key_value', $child_key_value);
-																		$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-																		try {
-																			$this->db->query(check_sql($sql));
-																			//$statement->execute();
-																			$message["details"][$m]["name"] = $key;
-																			$message["details"][$m]["message"] = "OK";
-																			$message["details"][$m]["code"] = "200";
-																			$message["details"][$m]["uuid"] = $child_key_value;
-																			if ($this->debug["sql"]) {
-																				$message["details"][$m]["sql"] = $sql;
-																			}
-																			$this->message = $message;
-																			$m++;
-																		}
-																		catch(PDOException $e) {
-																			if ($message["code"] = "200") {
-																				$message["message"] = "Bad Request";
-																				$message["code"] = "400";
-																			}
-																			$message["details"][$m]["name"] = $key;
-																			$message["details"][$m]["message"] = $e->getMessage();
-																			$message["details"][$m]["code"] = "400";
-																			if ($this->debug["sql"]) {
-																				$message["details"][$m]["sql"] = $sql;
-																			}
-																			$this->message = $message;
-																			$m++;
-																		}
-																	}
-																	else {
-																		$message["name"] = $child_name;
-																		$message["message"] = "Forbidden, does not have '${child_name}_delete'";
-																		$message["code"] = "403";
-																		$message["line"] = __line__;
-																		$this->message = $message;
-																		$m++;
-																	}
-																} //action update
-
-														//unset the variables
-															unset($sql, $action, $child_key_name, $child_key_value);
-													} // foreach value
-
-												} //is array
-											} //foreach array
-
-										} //is_array array
-								} // foreach schema_array
-
-							} //is_array $schema_array
-						}  // foreach main array
-					}
 
-				//return the before and after data
-					//log this in the future
-					//if (is_array($old_array)) {
-						//normalize the array structure
-							//$old_array = $this->normalize_array($old_array, $this->name);
+				//start the atomic transaction
+					$this->db->beginTransaction();
 
-						//debug info
-							//echo "<pre>\n";
-							//print_r($old_array);
-							//echo "</pre>\n";
-							//exit;
-					//}
-					//$message["new"] = $new_array;
-					//$message["new"]["md5"] = md5(json_encode($new_array));
-					$this->message = $message;
+				//delete the current data
+					foreach($array as $table_name => $rows) {
+						//echo "table: ".$table_name."\n";
+						foreach($rows as $row) {
+							if (permission_exists($this->singular($table_name).'_delete')) {
+								$sql = "delete from ".$table_prefix.$table_name." ";
+								$i = 0;
+								foreach($row as $field_name => $field_value) {
+									//echo "field: ".$field_name." = ".$field_value."\n";
+									if ($i == 0) { $sql .= "where "; } else { $sql .= "and "; }
+									$sql .= $field_name." = :".$field_name." ";
+									$parameters[$field_name] = $field_value;
+									$i++;
+								}
+								try {
+									$this->execute($sql, $parameters);
+									$message["message"] = "OK";
+									$message["code"] = "200";
+									$message["uuid"] = $id;
+									$message["details"][$m]["name"] = $this->name;
+									$message["details"][$m]["message"] = "OK";
+									$message["details"][$m]["code"] = "200";
+									//$message["details"][$m]["uuid"] = $parent_key_value;
+									if ($this->debug["sql"]) {
+										$message["details"][$m]["sql"] = $sql;
+									}
+									$this->message = $message;
+									$m++;
+									unset($sql);
+									unset($statement);
+								}
+								catch(PDOException $e) {
+									$message["message"] = "Bad Request";
+									$message["code"] = "400";
+									$message["details"][$m]["name"] = $this->name;
+									$message["details"][$m]["message"] = $e->getMessage();
+									$message["details"][$m]["code"] = "400";
+									if ($this->debug["sql"]) {
+										$message["details"][$m]["sql"] = $sql;
+									}
+									$this->message = $message;
+									$m++;
+								}
+								unset($parameters);
+							} //if permission
+						} //foreach rows
+					} //foreach $array
 
 				//commit the atomic transaction
-					//$this->db->commit();
+					$this->db->commit();
 
 				//set the action if not set
-					if (strlen($action) == 0) {
-						if (is_array($old_array)) {
-							$transaction_type = 'update';
-						}
-						else {
-							$transaction_type = 'add';
-						}
-					}
-					else {
-						$transaction_type = $action;
-					}
+					$transaction_type = 'delete';
 
 				//get the UUIDs
 					$user_uuid = $_SESSION['user_uuid'];
@@ -1060,7 +774,9 @@ include "root.php";
 						if (strlen($this->app_uuid) > 0) {
 							$sql .= "app_uuid, ";
 						}
-						$sql .= "app_name, ";
+						if (strlen($this->app_name) > 0) {
+							$sql .= "app_name, ";
+						}
 						$sql .= "transaction_code, ";
 						$sql .= "transaction_address, ";
 						$sql .= "transaction_type, ";
@@ -1074,31 +790,51 @@ include "root.php";
 						$sql .= "'".uuid()."', ";
 						$sql .= "'".$this->domain_uuid."', ";
 						if (strlen($user_uuid) > 0) {
-							$sql .= "'".$user_uuid."', ";
+							$sql .= ":user_uuid, ";
 						}
 						if (strlen($this->app_uuid) > 0) {
-							$sql .= "'".$this->app_uuid."', ";
+							$sql .= ":app_uuid, ";
+						}
+						if (strlen($this->app_name) > 0) {
+							$sql .= ":app_name, ";
 						}
-						$sql .= "'".$this->app_name."', ";
 						$sql .= "'".$message["code"]."', ";
-						$sql .= "'".$_SERVER['REMOTE_ADDR']."', ";
+						$sql .= ":remote_address, ";
 						$sql .= "'".$transaction_type."', ";
 						$sql .= "now(), ";
 						if (is_array($old_array)) {
-							$sql .= "'".check_str(json_encode($old_array, JSON_PRETTY_PRINT))."', ";
+							$sql .= ":transaction_old, ";
 						}
 						else {
 							$sql .= "null, ";
 						}
 						if (is_array($new_array)) {
-							$sql .= "'".check_str(json_encode($new_array, JSON_PRETTY_PRINT))."', ";
+							$sql .= ":transaction_new, ";
 						}
 						else {
 							$sql .= "null, ";
 						}
-						$sql .= "'".check_str(json_encode($this->message, JSON_PRETTY_PRINT))."' ";
+						$sql .= ":transaction_result ";
 						$sql .= ")";
-						$this->db->exec(check_sql($sql));
+						$statement = $this->db->prepare($sql);
+						if (strlen($user_uuid) > 0) {
+							$statement->bindParam(':user_uuid', $user_uuid);
+						}
+						if (strlen($this->app_uuid) > 0) {
+							$statement->bindParam(':app_uuid', $this->app_uuid);
+						}
+						if (strlen($this->app_name) > 0) {
+							$statement->bindParam(':app_name', $this->app_name);
+						}
+						$statement->bindParam(':remote_address', $_SERVER['REMOTE_ADDR']);
+						if (is_array($old_array)) {
+							$statement->bindParam(':transaction_old', json_encode($old_array, JSON_PRETTY_PRINT));
+						}
+						if (is_array($new_array)) {
+							$statement->bindParam(':transaction_new', json_encode($new_array, JSON_PRETTY_PRINT));
+						}
+						$statement->bindParam(':transaction_result', json_encode($this->message, JSON_PRETTY_PRINT));
+						$statement->execute();
 						unset($sql);
 					}
 			} //delete
@@ -1170,42 +906,48 @@ include "root.php";
 
 			} //count
 
-			public function select($sql) {
+			public function select($sql, $parameters = null) {
+
 				//connect to the database if needed
 					if (!$this->db) {
 						$this->connect();
 					}
+
+				//set the error mode
+					$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
 				//execute the query, and return the results
 					try {
-						$prep_statement = $this->db->prepare(check_sql($sql));
-						$prep_statement->execute();
+						$prep_statement = $this->db->prepare($sql);
+						if (is_array($parameters)) {
+							$prep_statement->execute($parameters);
+						}
+						else {
+							$prep_statement->execute();
+						}
 						$message["message"] = "OK";
 						$message["code"] = "200";
-						$message["details"][$m]["name"] = $this->name;
-						$message["details"][$m]["message"] = "OK";
-						$message["details"][$m]["code"] = "200";
-						if ($this->debug["sql"]) {
-							$message["details"][$m]["sql"] = $sql;
+						$message["sql"] = $sql;
+						if (is_array($parameters)) {
+							$message["parameters"] = $parameters;
 						}
 						$this->message = $message;
-						$this->result = $prep_statement->fetchAll(PDO::FETCH_NAMED);
-						unset($prep_statement);
-						$m++;
-						return $this;
+						//$result = $prep_statement->fetchAll(PDO::FETCH_ASSOC);
+						//unset($prep_statement);
+						return $prep_statement->fetchAll(PDO::FETCH_ASSOC);
 					}
 					catch(PDOException $e) {
 						$message["message"] = "Bad Request";
 						$message["code"] = "400";
-						$message["details"][$m]["name"] = $this->name;
-						$message["details"][$m]["message"] = $e->getMessage();
-						$message["details"][$m]["code"] = "400";
+						$message["error"]["message"] = $e->getMessage();
 						if ($this->debug["sql"]) {
-							$message["details"][$m]["sql"] = $sql;
+							$message["sql"] = $sql;
+						}
+						if (is_array($parameters)) {
+							$message["parameters"] = $parameters;
 						}
 						$this->message = $message;
-						$this->result = '';
-						$m++;
-						return $this;
+						return false;
 					}
 			} //select
 
@@ -1946,62 +1688,94 @@ include "root.php";
 
 				//log the transaction results
 					if (file_exists($_SERVER["PROJECT_ROOT"]."/app/database_transactions/app_config.php")) {
-						$sql = "insert into v_database_transactions ";
-						$sql .= "(";
-						$sql .= "database_transaction_uuid, ";
-						$sql .= "domain_uuid, ";
-						if (strlen($user_uuid) > 0) {
-							$sql .= "user_uuid, ";
-						}
-						if (strlen($this->app_uuid) > 0) {
-							$sql .= "app_uuid, ";
-						}
-						$sql .= "app_name, ";
-						$sql .= "transaction_code, ";
-						$sql .= "transaction_address, ";
-						$sql .= "transaction_type, ";
-						$sql .= "transaction_date, ";
-						$sql .= "transaction_old, ";
-						$sql .= "transaction_new, ";
-						$sql .= "transaction_result ";
-						$sql .= ")";
-						$sql .= "values ";
-						$sql .= "(";
-						$sql .= "'".uuid()."', ";
-						if (is_null($this->domain_uuid)) {
-							$sql .= "null, ";
-						}
-						else {
-							$sql .= "'".$this->domain_uuid."', ";
-						}
-						if (strlen($user_uuid) > 0) {
-							$sql .= "'".$user_uuid."', ";
-						}
-						if (strlen($this->app_uuid) > 0) {
-							$sql .= "'".$this->app_uuid."', ";
-						}
-						$sql .= "'".$this->app_name."', ";
-						$sql .= "'".$message["code"]."', ";
-						$sql .= "'".$_SERVER['REMOTE_ADDR']."', ";
-						$sql .= "'".$transaction_type."', ";
-						$sql .= "now(), ";
-						if (is_array($old_array)) {
-							$sql .= "'".check_str(json_encode($old_array, JSON_PRETTY_PRINT))."', ";
-						}
-						else {
-							$sql .= "null, ";
-						}
-						if (is_array($new_array)) {
-							$sql .= "'".check_str(json_encode($new_array, JSON_PRETTY_PRINT))."', ";
+						try {
+							$sql = "insert into v_database_transactions ";
+							$sql .= "(";
+							$sql .= "database_transaction_uuid, ";
+							$sql .= "domain_uuid, ";
+							if (strlen($user_uuid) > 0) {
+								$sql .= "user_uuid, ";
+							}
+							if (strlen($this->app_uuid) > 0) {
+								$sql .= "app_uuid, ";
+							}
+							if (strlen($this->app_name) > 0) {
+								$sql .= "app_name, ";
+							}
+							$sql .= "transaction_code, ";
+							$sql .= "transaction_address, ";
+							$sql .= "transaction_type, ";
+							$sql .= "transaction_date, ";
+							$sql .= "transaction_old, ";
+							$sql .= "transaction_new, ";
+							$sql .= "transaction_result ";
+							$sql .= ")";
+							$sql .= "values ";
+							$sql .= "(";
+							$sql .= "'".uuid()."', ";
+							if (is_null($this->domain_uuid)) {
+								$sql .= "null, ";
+							}
+							else {
+								$sql .= "'".$this->domain_uuid."', ";
+							}
+							if (strlen($user_uuid) > 0) {
+								$sql .= ":user_uuid, ";
+							}
+							if (strlen($this->app_uuid) > 0) {
+								$sql .= ":app_uuid, ";
+							}
+							if (strlen($this->app_name) > 0) {
+								$sql .= ":app_name, ";
+							}
+							$sql .= "'".$message["code"]."', ";
+							$sql .= ":remote_address, ";
+							$sql .= "'".$transaction_type."', ";
+							$sql .= "now(), ";
+							if (is_array($old_array)) {
+								$sql .= ":transaction_old, ";
+							}
+							else {
+								$sql .= "null, ";
+							}
+							if (is_array($new_array)) {
+								$sql .= ":transaction_new, ";
+							}
+							else {
+								$sql .= "null, ";
+							}
+							$sql .= ":transaction_result ";
+							$sql .= ")";
+							$statement = $this->db->prepare($sql);
+							if (strlen($user_uuid) > 0) {
+								$statement->bindParam(':user_uuid', $user_uuid);
+							}
+							if (strlen($this->app_uuid) > 0) {
+								$statement->bindParam(':app_uuid', $this->app_uuid);
+							}
+							if (strlen($this->app_name) > 0) {
+								$statement->bindParam(':app_name', $this->app_name);
+							}
+							$statement->bindParam(':remote_address', $_SERVER['REMOTE_ADDR']);
+							if (is_array($old_array)) {
+								$old_json = json_encode($old_array, JSON_PRETTY_PRINT);
+								$statement->bindParam(':transaction_old', $old_json);
+							}
+							if (is_array($new_array)) {
+								$new_json = json_encode($new_array, JSON_PRETTY_PRINT);
+								$statement->bindParam(':transaction_new', $new_json);
+							}
+							$message = json_encode($this->message, JSON_PRETTY_PRINT);
+							$statement->bindParam(':transaction_result', $message);
+							$statement->execute();
+							unset($sql);
 						}
-						else {
-							$sql .= "null, ";
+						catch(PDOException $e) {
+							echo $e->getMessage();
+							exit;
 						}
-						$sql .= "'".check_str(json_encode($this->message, JSON_PRETTY_PRINT))."' ";
-						$sql .= ")";
-						$this->db->exec(check_sql($sql));
-						unset($sql);
 					}
+
 			} //save method
 
 			//define singular function to convert a word in english to singular

+ 229 - 27
resources/classes/destinations.php

@@ -287,7 +287,199 @@ class destinations {
 	}
 
 	/**
-	 * delete destinations
+	 * Get all the destinations
+	 * @var string $destination_type can be ivr, dialplan, call_center_contact or bridge
+	 */
+	public function all($destination_type) {
+
+		//set the global variables
+		global $db_type;
+
+		//get the destinations	
+		if (!is_array($this->destinations)) {
+
+			//get the array from the app_config.php files
+			$config_list = glob($_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/*/*/app_config.php");
+			$x = 0;
+			foreach ($config_list as &$config_path) {
+				include($config_path);
+				$x++;
+			}
+			$i = 0;
+			foreach ($apps as $x => &$app) {
+				if (isset($app['destinations'])) foreach ($app['destinations'] as &$row) {
+					$this->destinations[] = $row;
+				}
+			}
+	
+			//put the array in order
+			foreach ($this->destinations as $row) {
+				$option_groups[] = $row['label'];
+			}
+			array_multisort($option_groups, SORT_ASC, $this->destinations);
+	
+			//add the sql and data to the array
+			$x = 0;
+			foreach ($this->destinations as $row) {
+				if ($row['type'] = 'sql') {
+					if (isset($row['sql'])) {
+						if (is_array($row['sql'])) {
+							$sql = trim($row['sql'][$db_type])." ";
+						}
+						else {
+							$sql = trim($row['sql'])." ";
+						}
+					}
+					else {
+						$field_count = count($row['field']);
+						$fields = '';
+						$c = 1;
+						foreach ($row['field'] as $key => $value) {
+							if ($field_count != $c) { $delimiter = ','; } else { $delimiter = ''; }
+							$fields .= $value." as ".$key.$delimiter." ";
+							$c++;
+						}
+						$sql = "select ".$fields;
+						$sql .= " from v_".$row['name']." ";
+					}
+					if (isset($row['where'])) {
+						$sql .= trim($row['where'])." ";
+					}
+					$sql .= "order by ".trim($row['order_by']);
+					$sql = str_replace("\${domain_uuid}", $_SESSION['domain_uuid'], $sql);
+					$sql = trim($sql);
+					$statement = $this->db->prepare($sql);
+					$statement->execute();
+					$result = $statement->fetchAll(PDO::FETCH_NAMED);
+					unset($statement);
+
+					$this->destinations[$x]['result']['sql'] = $sql;
+					$this->destinations[$x]['result']['data'] = $result;
+				}
+				$x++;
+			}
+			$this->destinations[$x]['type'] = 'array';
+			$this->destinations[$x]['label'] = 'other';
+			$this->destinations[$x]['name'] = 'dialplans';
+			$this->destinations[$x]['field']['name'] = "name";
+			$this->destinations[$x]['field']['destination'] = "destination";
+			$this->destinations[$x]['select_value']['dialplan'] = "transfer:\${destination}";
+			$this->destinations[$x]['select_value']['ivr'] = "menu-exec-app:transfer \${destination}";
+			$this->destinations[$x]['select_label'] = "\${name}";
+			$y = 0;
+			$this->destinations[$x]['result']['data'][$y]['label'] = 'check_voicemail';
+			$this->destinations[$x]['result']['data'][$y]['name'] = '*98';
+			$this->destinations[$x]['result']['data'][$y]['destination'] = '*98 XML ${context}';
+			$y++;
+			$this->destinations[$x]['result']['data'][$y]['label'] = 'company_directory';
+			$this->destinations[$x]['result']['data'][$y]['name'] = '*411';
+			$this->destinations[$x]['result']['data'][$y]['destination'] = '*411 XML ${context}';
+			$y++;
+			$this->destinations[$x]['result']['data'][$y]['label'] = 'hangup';
+			$this->destinations[$x]['result']['data'][$y]['name'] = 'hangup';
+			$this->destinations[$x]['result']['data'][$y]['application'] = 'hangup';
+			$this->destinations[$x]['result']['data'][$y]['destination'] = '';
+			$y++;
+			$this->destinations[$x]['result']['data'][$y]['label'] = 'record';
+			$this->destinations[$x]['result']['data'][$y]['name'] = '*732';
+			$this->destinations[$x]['result']['data'][$y]['destination'] = '*732 XML ${context}';
+			$y++;
+		}
+
+		//remove special characters from the name
+		$destination_id = str_replace("]", "", $destination_name);
+		$destination_id = str_replace("[", "_", $destination_id);
+
+		//set default to false
+		$select_found = false;
+
+		foreach ($this->destinations as $row) {
+
+			$name = $row['name'];
+			$label = $row['label'];
+			$destination = $row['field']['destination'];
+
+			//add multi-lingual support
+			if (file_exists($_SERVER["PROJECT_ROOT"]."/app/".$name."/app_languages.php")) {
+				$language2 = new text;
+				$text2 = $language2->get($_SESSION['domain']['language']['code'], 'app/'.$name);
+			}
+
+			if (count($row['result']['data']) > 0 and strlen($row['select_value'][$destination_type]) > 0) {
+				$label2 = $label;
+				foreach ($row['result']['data'] as $data) {
+					$select_value = $row['select_value'][$destination_type];
+					$select_label = $row['select_label'];
+					foreach ($row['field'] as $key => $value) {
+						if ($key == 'destination' and is_array($value)){
+							if ($value['type'] == 'csv') {
+								$array = explode($value['delimiter'], $data[$key]);
+								$select_value = str_replace("\${destination}", $array[0], $select_value);
+								$select_label = str_replace("\${destination}", $array[0], $select_label);
+							}
+						}
+						else {
+							if (strpos($value,',') !== false) {
+								$keys = explode(",", $value);
+								foreach ($keys as $k) {
+									if (strlen($data[$k]) > 0) {
+										$select_value = str_replace("\${".$key."}", $data[$k], $select_value);
+										if (strlen($data['label']) == 0) {
+											$select_label = str_replace("\${".$key."}", $data[$k], $select_label);
+										}
+										else {
+											$label = $data['label'];
+											$select_label = str_replace("\${".$key."}", $text2['option-'.$label], $select_label);
+										}
+									}
+								}
+
+							}
+							else {
+								$select_value = str_replace("\${".$key."}", $data[$key], $select_value);
+								if (strlen($data['label']) == 0) {
+									$select_label = str_replace("\${".$key."}", $data[$key], $select_label);
+								}
+								else {
+									$label = $data['label'];
+									$select_label = str_replace("\${".$key."}", $text2['option-'.$label], $select_label);
+								}
+							}
+							//application: hangup
+							if (strlen($data['application']) > 0) {
+								$select_value = str_replace("transfer", $data['application'], $select_value);
+							}
+						}
+					}
+
+					$select_value = str_replace("\${domain_name}", $_SESSION['domain_name'], $select_value);
+					$select_value = str_replace("\${context}", $_SESSION['domain_name'], $select_value);
+					$select_label = str_replace("\${domain_name}", $_SESSION['domain_name'], $select_label);
+					$select_label = str_replace("\${context}", $_SESSION['domain_name'], $select_label);
+					$select_label = str_replace("&#9993", '{email-icon}', $select_label);
+					$select_label = escape(trim($select_label));
+					$select_label = str_replace('{email-icon}', '&#9993', $select_label);
+					if ($select_value == $destination_value) { $selected = "selected='selected' "; $select_found = true; } else { $selected = ''; }
+					if ($label2 == 'destinations') { $select_label = format_phone($select_label); }
+					$array[$label][$select_label] = $select_value;
+				}
+				unset($text);
+			}
+		}
+		if (!$select_found) {
+			$destination_label = str_replace(":", " ", $destination_value);
+			$destination_label = str_replace("menu-exec-app", "", $destination_label);
+			$destination_label = str_replace("transfer", "", $destination_label);
+			$destination_label = str_replace("XML ".$_SESSION['domain_name'], "", $destination_label);
+			$array[$label][$destination_label] = $destination_value;
+		}
+
+		//return the formatted destinations
+		return $array;
+	}
+
+	/**
+	 * delete destinations and related dialplan
 	 */
 	public function delete($destinations) {
 		if (permission_exists('destination_delete')) {
@@ -304,36 +496,46 @@ class destinations {
 
 				//delete the checked rows
 				if ($action == 'delete') {
+
+					//add the dialplan permission
+					$p = new permissions;
+					$p->add('dialplan_delete', 'temp');
+					$p->add('dialplan_detail_delete', 'temp');
+
+					//loop through selected destinations
 					foreach($destinations as $row) {
 						if ($row['action'] == 'delete' or $row['checked'] == 'true') {
-							//get the list destinations
-							$sql = "select * from v_destinations ";
-							$sql .= "where destination_uuid = '".$row['destination_uuid']."';";
-							$prep_statement = $this->db->prepare($sql);
-							$prep_statement->execute();
-							$destinations = $prep_statement->fetchAll(PDO::FETCH_NAMED);
-							$row = $destinations[0];
-
-							//delete th dialplan
-							$sql = "delete from v_dialplan_details ";
-							$sql .= "where dialplan_uuid = '".$row['dialplan_uuid']."';";
-							$this->db->query($sql);
-							unset($sql);
-
-							//delete th dialplan
-							$sql = "delete from v_dialplans ";
-							$sql .= "where dialplan_uuid = '".$row['dialplan_uuid']."';";
-							$this->db->query($sql);
-							unset($sql);
-
-							//delete the destinations
-							$sql = "delete from v_destinations ";
-							$sql .= "where destination_uuid = '".$row['destination_uuid']."';";
-							$this->db->query($sql);
-							unset($sql);
+
+							//get the dialplan uuid and context
+								$sql = "select * from v_destinations ";
+								$sql .= "where destination_uuid = :destination_uuid ";
+								$database = new database;
+								$parameters['destination_uuid'] = $row['destination_uuid'];
+								$destinations = $database->select($sql,$parameters);
+								$row = $destinations[0];
+
+							//prepare and then delete the selected data
+								if (isset($row["dialplan_uuid"]) && is_uuid($row["dialplan_uuid"])) {
+									$array['dialplan_details'][]['dialplan_uuid'] = $row["dialplan_uuid"];
+									$array['dialplans'][]['dialplan_uuid'] = $row["dialplan_uuid"];
+								}
+								$array['destinations'][]['destination_uuid'] = $row['destination_uuid'];
+								$database->app_name = 'destinations';
+								$database->app_uuid = '5ec89622-b19c-3559-64f0-afde802ab139';
+								$database->delete($array);
+								//$message = $database->message;
+
+							//clear the cache
+								$cache = new cache;
+								$cache->delete("dialplan:".$row['destination_context']);
+
 						}
 					}
-					unset($destinations);
+					unset($destinations, $row);
+
+					//remove the temporary permission
+					$p->delete('dialplan_delete', 'temp');
+					$p->delete('dialplan_detail_delete', 'temp');
 				}
 			}
 		}

+ 0 - 7
resources/classes/menu.php

@@ -223,13 +223,6 @@ if (!class_exists('menu')) {
 				//get default global group_uuids
 					$sql = "select group_uuid, group_name from v_groups ";
 					$sql .= "where domain_uuid is null ";
-					$sql .= "and ( ";
-					$sql .= "	group_name = 'public' ";
-					$sql .= "	or group_name = 'user' ";
-					$sql .= "	or group_name = 'admin' ";
-					$sql .= "	or group_name = 'superadmin' ";
-					$sql .= "	or group_name = 'agent' ";
-					$sql .= ") ";
 					$prep_statement = $db->prepare(check_sql($sql));
 					$prep_statement->execute();
 					$result = $prep_statement->fetchAll(PDO::FETCH_ASSOC);

+ 9 - 5
resources/classes/messages.php → resources/classes/message.php

@@ -25,8 +25,8 @@
 	Matthew Vale <[email protected]>
 */
 
-if (!class_exists('messages')) {
-	class messages {
+if (!class_exists('message')) {
+	class message {
 		
 		static function add($message, $mood = NULL, $delay = NULL) {
 			$mood = $mood ?: 'positive';
@@ -35,21 +35,25 @@ if (!class_exists('messages')) {
 			$_SESSION["messages"][$mood]['delay'][] = $delay;
 		}
 		
+		static function count() {
+			return is_array($_SESSION["messages"]) ? sizeof($_SESSION["messages"]) : 0;
+		}
+		
 		static function html($clear_messages = true, $spacer = "") {
 			$html = "${spacer}//render the messages\n";
 			$spacer .="\t";
-			if (strlen($_SESSION['message']) > 0) {
+			if (is_string($_SESSION['message']) && strlen(trim($_SESSION['message'])) > 0) {
 				self::add($_SESSION['message'], $_SESSION['message_mood'], $_SESSION['message_delay']);
 				unset($_SESSION['message'], $_SESSION['message_mood'], $_SESSION['message_delay']);
 			}
-			if(count($_SESSION['messages']) > 0 ) {
+			if (is_array($_SESSION['messages']) && count($_SESSION['messages']) > 0 ) {
 				foreach ($_SESSION['messages'] as $message_mood => $message) {
 					$message_text = str_replace(array("\r\n", "\n", "\r"),'\\n',addslashes(join('<br/>', $message['message'])));
 					$message_delay = array_sum($message['delay'])/count($message['delay']);
 					$html .= "${spacer}display_message('$message_text', '$message_mood', '$message_delay');\n";
 				}
 			}
-			if($clear_messages) {
+			if ($clear_messages) {
 				unset($_SESSION['messages']);
 			}
 			return $html;

+ 0 - 924
resources/classes/orm.php

@@ -1,924 +0,0 @@
-<?php
-/*
-	FusionPBX
-	Version: MPL 1.1
-
-	The contents of this file are subject to the Mozilla Public License Version
-	1.1 (the "License"); you may not use this file except in compliance with
-	the License. You may obtain a copy of the License at
-	http://www.mozilla.org/MPL/
-
-	Software distributed under the License is distributed on an "AS IS" basis,
-	WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-	for the specific language governing rights and limitations under the
-	License.
-
-	The Original Code is FusionPBX
-
-	The Initial Developer of the Original Code is
-	Mark J Crane <[email protected]>
-	Copyright (C) 2014-2016
-	All Rights Reserved.
-
-	Contributor(s):
-	Mark J Crane <[email protected]>
-*/
-
-//define the orm class
-	if (!class_exists('orm')) {
-		class orm extends database {
-			//factory - sets the model_name
-			//set - sets the array
-				public $name;
-			//get - get the results
-				public $result;
-			//find
-				public $uuid;
-				//public $name;
-				public $where;
-				public $limit;
-				public $offset;
-			//save
-				//public $uuid;
-				//public $name;
-				public $message;
-				public $debug;
-			//delete
-				//public $uuid;
-				//public $name;
-				//public $where;
-				//public $message;
-			//application 
-				public $app_name;
-				public $app_uuid;
-
-			public function factory($name) {
-				$this->name = $name;
-				return $this;
-			}
-
-			public function name($name) {
-				$this->name = $name;
-				return $this;
-			}
-
-			public function uuid($uuid) {
-				$this->uuid = $uuid;
-				return $this;
-			}
-
-			public function set($array) {
-				foreach ($array as $key => $value) {
-					//public $this->$$key = $value;
-				}
-				return $this;
-			}
-
-			public function get() {
-				return $this->result;
-			}
-
-			public function find() {
-
-				//connect to the database if needed
-					if (!$this->db) {
-						$this->connect();
-					}
-				//set the name
-					if (isset($array['name'])) {
-						$this->name = $array['name'];
-					}
-				//set the uuid
-					if (isset($array['uuid'])) {
-						$this->uuid = $array['uuid'];
-					}
-				//build the query
-					$sql = "SELECT * FROM v_".$this->name." ";
-					if (isset($this->uuid)) {
-						//get the specific uuid
-							$sql .= "WHERE ".$this->singular($this->name)."_uuid = '".$this->uuid."' ";
-					}
-					else {
-						//where
-							if (is_array($array['where'])) {
-								$i = 0;
-								foreach($array['where'] as $row) {
-									if ($i == 0) {
-										$sql .= "WHERE ".$row['name']." ".$row['operator']." '".$row['value']."' ";
-									}
-									else {
-										$sql .= "AND ".$row['name']." ".$row['operator']." '".$row['value']."' ";
-									}
-									$i++;
-								}
-							}
-						//order by
-							if (is_array($array['order_by'])) {
-								$sql .= "ORDER BY ".$array['order_by']." ";
-							}
-						//limit
-							if (isset($array['limit'])) {
-								$sql .= "LIMIT ".$array['limit']." ";
-							}
-						//offset
-							if (isset($array['offset'])) {
-								$sql .= "OFFSET ".$array['offset']." ";
-							}
-					}
-				//execute the query, and return the results
-					try {
-						$prep_statement = $this->db->prepare(check_sql($sql));
-						$prep_statement->execute();
-						$message["message"] = "OK";
-						$message["code"] = "200";
-						$message["details"][$m]["name"] = $this->name;
-						$message["details"][$m]["message"] = "OK";
-						$message["details"][$m]["code"] = "200";
-						if ($this->debug["sql"]) {
-							$message["details"][$m]["sql"] = $sql;
-						}
-						$this->message = $message;
-						$this->result = $prep_statement->fetchAll(PDO::FETCH_NAMED);
-						unset($prep_statement);
-						$m++;
-						return $this;
-					}
-					catch(PDOException $e) {
-						$message["message"] = "Bad Request";
-						$message["code"] = "400";
-						$message["details"][$m]["name"] = $this->name;
-						$message["details"][$m]["message"] = $e->getMessage();
-						$message["details"][$m]["code"] = "400";
-						if ($this->debug["sql"]) {
-							$message["details"][$m]["sql"] = $sql;
-						}
-						$this->message = $message;
-						$this->result = '';
-						$m++;
-						return $this;
-					}
-			}
-
-			public function delete($uuid = null, $array = null) {
-				//connect to the database if needed
-					if (!$this->db) {
-						$this->connect();
-					}
-
-				//delete a specific uuid
-					if (permission_exists($this->singular($this->name).'_delete')) {
-						if (isset($api_uuid)) {
-							//start the atomic transaction
-								$this->db->beginTransaction();
-							//delete the primary data
-								$primary_key_name = $this->singular($this->name)."_uuid";
-								$sql = "DELETE FROM v_".$this->name." ";
-								$sql .= "WHERE ".$this->singular($this->name)."_uuid = '".$uuid."' ";
-								$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-								try {
-									$this->db->query(check_sql($sql));
-									$message["message"] = "OK";
-									$message["code"] = "200";
-									$message["details"][$m]["name"] = $this->name;
-									$message["details"][$m]["message"] = "OK";
-									$message["details"][$m]["code"] = "200";
-									if ($this->debug["sql"]) {
-										$message["details"][$m]["sql"] = $sql;
-									}
-									$this->message = $message;
-									$m++;
-								}
-								catch(PDOException $e) {
-									$message["message"] = "Bad Request";
-									$message["code"] = "400";
-									$message["details"][$m]["name"] = $this->name;
-									$message["details"][$m]["message"] = $e->getMessage();
-									$message["details"][$m]["code"] = "400";
-									if ($this->debug["sql"]) {
-										$message["details"][$m]["sql"] = $sql;
-									}
-									$this->message = $message;
-									$m++;
-								}
-							//delete the related data
-								$relations = $this->get_relations($this->name);
-								foreach ($relations as &$row) {
-									$schema_name = $row['table'];
-									if (substr($schema_name, 0,2) == "v_") {
-										$schema_name = substr($schema_name, 2);
-									}
-									if (permission_exists($this->singular($schema_name).'_delete')) {
-										$sql = "DELETE FROM ".$row['table']." ";
-										$sql .= "WHERE ".$row['key']['field']." = '".$uuid."' ";
-										$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-										try {
-											$this->db->query(check_sql($sql));
-											$message["details"][$m]["name"] = $schema_name;
-											$message["details"][$m]["message"] = "OK";
-											$message["details"][$m]["code"] = "200";
-											if ($this->debug["sql"]) {
-												$message["details"][$m]["sql"] = $sql;
-											}
-											$this->message = $message;
-											$m++;
-										}
-										catch(PDOException $e) {
-											if ($message["code"] = "200") {
-												$message["message"] = "Bad Request";
-												$message["code"] = "400";
-											}
-											$message["details"][$m]["name"] = $schema_name;
-											$message["details"][$m]["message"] = $e->getMessage();
-											$message["details"][$m]["code"] = "400";
-											if ($this->debug["sql"]) {
-												$message["details"][$m]["sql"] = $sql;
-											}
-											$this->message = $message;
-											$m++;
-										}
-										unset ($sql);
-									}
-								}
-							//commit the atomic transaction
-								if ($message["code"] == "200") {
-									$this->db->commit();
-								}
-						}
-					}
-					else {
-						$message["name"] = $this->name;
-						$message["message"] = "Forbidden, does not have '".$this->singular($this->name)."_delete'";
-						$message["code"] = "403";
-						$message["line"] = __line__;
-						$this->message = $message;
-						$m++;
-					}
-			}
-
-			private function normalize_array($array, $name) {
-				//get the depth of the array
-					$depth = $this->array_depth($array);
-				//before normalizing the array
-					//echo "before: ".$depth."<br />\n";
-					//echo "<pre>\n";
-					//print_r($array);
-					//echo "</pre>\n";
-				//normalize the array
-					if ($depth == 1) {
-						$return_array[$name][] = $array;
-					} else if ($depth == 2) {
-						$return_array[$name] = $array;
-					//} else if ($depth == 3) {
-					//	$return_array[$name][] = $array;
-					} else {
-						$return_array = $array;
-					}
-					unset($array);
-				//after normalizing the array
-					$depth = $this->array_depth($new_array);
-					//echo "after: ".$depth."<br />\n";
-					//echo "<pre>\n";
-					//print_r($new_array);
-					//echo "</pre>\n";
-				//return the array
-					return $return_array;
-			}
-
-			public function save($array) {
-
-				//return the array
-					if (!is_array($array)) { echo "not an array"; return false; }
-
-				//set the message id
-					$m = 0;
-
-				//set the app name
-					if (!isset($this->app_name)) {
-						$this->app_name = $this->name;
-					}
-
-				//normalize the array structure
-					//$new_array = $this->normalize_array($array, $this->name);
-					//unset($array);
-					$new_array = $array;
-
-				//connect to the database if needed
-					if (!$this->db) {
-						$this->connect();
-					}
-
-				//debug sql
-					$this->debug["sql"] = true;
-
-				//start the atomic transaction
-//					$this->db->beginTransaction();
-
-				//debug info
-					//echo "<pre>\n";
-					//print_r($new_array);
-					//echo "</pre>\n";
-					//exit;
-
-				//loop through the array
-					foreach ($new_array as $schema_name => $schema_array) {
-
-						$this->name = $schema_name;
-						foreach ($schema_array as $schema_id => $array) {
-
-							//set the variables
-								$table_name = "v_".$this->name;
-								$parent_key_name = $this->singular($this->name)."_uuid";
-
-							//if the uuid is set then set parent key exists and value 
-								//determine if the parent_key_exists
-								$parent_key_exists = false;
-								if (isset($array[$parent_key_name])) {
-									$this->uuid = $array[$parent_key_name];
-									$parent_key_value = $this->uuid;
-									$parent_key_exists = true;
-								}
-								else {
-									if (isset($this->uuid)) {
-										$parent_key_exists = true;
-										$parent_key_value = $this->uuid;
-									}
-									else {
-										$parent_key_value = uuid();
-									}
-								}
-
-							//get the parent field names
-								$parent_field_names = array();
-								foreach ($array as $key => $value) {
-									if (!is_array($value)) {
-										$parent_field_names[] = $key;
-									}
-								}
-
-							//determine action update or delete and get the original data
-								if ($parent_key_exists) {
-									$sql = "SELECT ".implode(", ", $parent_field_names)." FROM ".$table_name." ";
-									$sql .= "WHERE ".$parent_key_name." = '".$this->uuid."' ";
-									$prep_statement = $this->db->prepare($sql);
-									if ($prep_statement) {
-										//get the data
-											try {
-												$prep_statement->execute();
-												$result = $prep_statement->fetchAll(PDO::FETCH_ASSOC);
-											}
-											catch(PDOException $e) {
-												echo 'Caught exception: ',  $e->getMessage(), "<br/><br/>\n";
-												echo $sql;
-												exit;
-											}
-
-										//set the action
-											if (count($result) > 0) {
-												$action = "update";
-												$old_array[$schema_name] = $result;
-											}
-											else {
-												$action = "add";
-											}
-									}
-									unset($prep_statement);
-									unset($result);
-								}
-								else {
-									$action = "add";
-								}
-
-							//add a record
-								if ($action == "add") {
-
-									if (permission_exists($this->singular($this->name).'_add')) {
-
-											$sql = "INSERT INTO v_".$this->name." ";
-											$sql .= "(";
-											if (!$parent_key_exists) {
-												$sql .= $parent_key_name.", ";
-											}
-											//foreach ($parent_field_names as $field_name) {
-											//		$sql .= check_str($field_name).", ";
-											//}
-											foreach ($array as $array_key => $array_value) {
-												if (!is_array($array_value)) {
-													$sql .= check_str($array_key).", ";
-												}
-											}
-											$sql .= ") ";
-											$sql .= "VALUES ";
-											$sql .= "(";
-											if (!$parent_key_exists) {
-												$sql .= "'".$parent_key_value."', ";
-											}
-											foreach ($array as $array_key => $array_value) {
-												if (!is_array($array_value)) {
-													if (strlen($array_value) == 0) {
-														$sql .= "null, ";
-													}
-													else {
-														$sql .= "'".check_str($array_value)."', ";
-													}
-												}
-											}
-											$sql .= ");";
-											$sql = str_replace(", )", ")", $sql);
-											$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-											try {
-												$this->db->query(check_sql($sql));
-												$message["message"] = "OK";
-												$message["code"] = "200";
-												$message["uuid"] = $parent_key_value;
-												$message["details"][$m]["name"] = $this->name;
-												$message["details"][$m]["message"] = "OK";
-												$message["details"][$m]["code"] = "200";
-												$message["details"][$m]["uuid"] = $parent_key_value;
-												if ($this->debug["sql"]) {
-													$message["details"][$m]["sql"] = $sql;
-												}
-												$this->message = $message;
-												$m++;
-											}
-											catch(PDOException $e) {
-												$message["message"] = "Bad Request";
-												$message["code"] = "400";
-												$message["details"][$m]["name"] = $this->name;
-												$message["details"][$m]["message"] = $e->getMessage();
-												$message["details"][$m]["code"] = "400";
-												if ($this->debug["sql"]) {
-													$message["details"][$m]["sql"] = $sql;
-												}
-												$this->message = $message;
-												$m++;
-											}
-											unset($sql);
-									}
-									else {
-										$message["name"] = $this->name;
-										$message["message"] = "Forbidden, does not have '".$this->singular($this->name)."_add'";
-										$message["code"] = "403";
-										$message["line"] = __line__;
-										$this->message[] = $message;
-										$m++;
-									}
-								}
-
-							//edit a specific uuid
-								if ($action == "update") {
-									if (permission_exists($this->singular($this->name).'_edit')) {
-
-										//parent data
-											$sql = "UPDATE v_".$this->name." SET ";
-											foreach ($array as $array_key => $array_value) {
-												if (!is_array($array_value) && $array_key != $parent_key_name) {
-													if (strlen($array_value) == 0) {
-														$sql .= check_str($array_key)." = null, ";
-													}
-													else {
-														$sql .= check_str($array_key)." = '".check_str($array_value)."', ";
-													}
-												}
-											}
-											$sql .= "WHERE ".$parent_key_name." = '".$parent_key_value."' ";
-											$sql = str_replace(", WHERE", " WHERE", $sql);
-											$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-											try {
-												$this->db->query(check_sql($sql));
-												$message["message"] = "OK";
-												$message["code"] = "200";
-												$message["uuid"] = $parent_key_value;
-												$message["details"][$m]["name"] = $this->name;
-												$message["details"][$m]["message"] = "OK";
-												$message["details"][$m]["code"] = "200";
-												$message["details"][$m]["uuid"] = $parent_key_value;
-												if ($this->debug["sql"]) {
-													$message["details"][$m]["sql"] = $sql;
-												}
-												$this->message = $message;
-												$m++;
-												unset($sql);
-											}
-											catch(PDOException $e) {
-												$message["message"] = "Bad Request";
-												$message["code"] = "400";
-												$message["details"][$m]["name"] = $this->name;
-												$message["details"][$m]["message"] = $e->getMessage();
-												$message["details"][$m]["code"] = "400";
-												if ($this->debug["sql"]) {
-													$message["details"][$m]["sql"] = $sql;
-												}
-												$this->message = $message;
-												$m++;
-											}
-									}
-									else {
-										$message["name"] = $this->name;
-										$message["message"] = "Forbidden, does not have '".$this->singular($this->name)."_edit'";
-										$message["code"] = "403";
-										$message["line"] = __line__;
-										$this->message = $message;
-										$m++;
-									}
-								}
-
-							//unset the variables
-								unset($sql, $action);
-
-							//child data
-								foreach ($array as $key => $value) {
-
-									if (is_array($value)) {
-											$table_name = "v_".$key;
-
-											foreach ($value as $id => $row) {
-												//prepare the variables
-													$child_name = $this->singular($key);
-													$child_key_name = $child_name."_uuid";
-			
-												//determine if the parent key exists in the child array
-													$parent_key_exists = false;
-													if (!isset($array[$parent_key_name])) {
-														$parent_key_exists = true;
-													}
-
-												//determine if the uuid exists
-													$uuid_exists = false;
-													foreach ($row as $k => $v) {
-														if ($child_key_name == $k) {
-															if (strlen($v) > 0) {
-																$child_key_value = $v;
-																$uuid_exists = true;
-																break;
-															}
-														}
-														else {
-															$uuid_exists = false;
-														}
-													}
-
-												//get the child field names
-													$child_field_names = array();
-													foreach ($row as $k => $v) {
-														if (!is_array($v)) {
-															$child_field_names[] = $k;
-														}
-													}
-
-												//determine sql update or delete and get the original data
-													if ($uuid_exists) {
-														$sql = "SELECT ". implode(", ", $child_field_names)." FROM ".$table_name." ";
-														$sql .= "WHERE ".$child_key_name." = '".$child_key_value."' ";
-														$prep_statement = $this->db->prepare($sql);
-														if ($prep_statement) {
-															//get the data
-																$prep_statement->execute();
-																$child_array = $prep_statement->fetch(PDO::FETCH_ASSOC);
-															//set the action
-																if (is_array($child_array)) {
-																	$action = "update";
-																}
-																else {
-																	$action = "add";
-																}
-															//add to the parent array
-																if (is_array($child_array)) {
-																	$old_array[$schema_name][$schema_id][$key][] = $child_array;
-																}
-														}
-														unset($prep_statement);
-													}
-													else {
-														$action = "add";
-													}
-
-												//update the data
-													if ($action == "update") {
-														if (permission_exists($child_name.'_edit')) {
-															$sql = "UPDATE ".$table_name." SET ";
-															foreach ($row as $k => $v) {
-																//if (!is_array($v) && $k != $child_key_name) { //original
-																if (!is_array($v) && ($k != $parent_key_name || $k != $child_key_name)) {
-																	if (strlen($v) == 0) {
-																		$sql .= check_str($k)." = null, ";
-																	}
-																	else {
-																		$sql .= check_str($k)." = '".check_str($v)."', ";
-																	}
-																}
-															}
-															$sql .= "WHERE ".$parent_key_name." = '".$this->uuid."' ";
-															$sql .= "AND ".$child_key_name." = '".$child_key_value."' ";
-															$sql = str_replace(", WHERE", " WHERE", $sql);
-															$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-															try {
-																$this->db->query(check_sql($sql));
-																$message["details"][$m]["name"] = $key;
-																$message["details"][$m]["message"] = "OK";
-																$message["details"][$m]["code"] = "200";
-																$message["details"][$m]["uuid"] = $child_key_value;
-																if ($this->debug["sql"]) {
-																	$message["details"][$m]["sql"] = $sql;
-																}
-																$this->message = $message;
-																$m++;
-															}
-															catch(PDOException $e) {
-																if ($message["code"] = "200") {
-																	$message["message"] = "Bad Request";
-																	$message["code"] = "400";
-																}
-																$message["details"][$m]["name"] = $key;
-																$message["details"][$m]["message"] = $e->getMessage();
-																$message["details"][$m]["code"] = "400";
-																if ($this->debug["sql"]) {
-																	$message["details"][$m]["sql"] = $sql;
-																}
-																$this->message = $message;
-																$m++;
-															}
-														}
-														else {
-															$message["name"] = $child_name;
-															$message["message"] = "Forbidden, does not have '${child_name}_edit'";
-															$message["code"] = "403";
-															$message["line"] = __line__;
-															$this->message = $message;
-															$m++;
-														}
-													} //action update
-
-											//add the data
-												if ($action == "add") {
-													if (permission_exists($child_name.'_add')) {
-														//determine if child or parent key exists
-														$child_key_name = $this->singular($child_name).'_uuid';
-														$parent_key_exists = false;
-														$child_key_exists = false;
-														foreach ($row as $k => $v) {
-															if ($k == $parent_key_name) {
-																$parent_key_exists = true; 
-															}
-															if ($k == $child_key_name) {
-																$child_key_exists = true;
-																$child_key_value = $v;
-															}
-														}
-														if (!$child_key_value) {
-															$child_key_value = uuid();
-														}
-														//build the insert
-														$sql = "INSERT INTO ".$table_name." ";
-														$sql .= "(";
-														if (!$parent_key_exists) {
-															$sql .= $this->singular($parent_key_name).", ";
-														}
-														if (!$child_key_exists) {
-															$sql .= $this->singular($child_key_name).", ";
-														}
-														foreach ($row as $k => $v) {
-															if (!is_array($v)) {
-																$sql .= check_str($k).", ";
-															}
-														}
-														$sql .= ") ";
-														$sql .= "VALUES ";
-														$sql .= "(";
-														if (!$parent_key_exists) {
-															$sql .= "'".$parent_key_value."', ";
-														}
-														if (!$child_key_exists) {
-															$sql .= "'".$child_key_value."', ";
-														}
-														foreach ($row as $k => $v) {
-															if (!is_array($v)) {
-																if (strlen($v) == 0) {
-																	$sql .= "null, ";
-																}
-																else {
-																	$sql .= "'".check_str($v)."', ";
-																}
-															}
-														}
-														$sql .= ");";
-														$sql = str_replace(", )", ")", $sql);
-														$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-														try {
-															$this->db->query(check_sql($sql));
-															$message["details"][$m]["name"] = $key;
-															$message["details"][$m]["message"] = "OK";
-															$message["details"][$m]["code"] = "200";
-															$message["details"][$m]["uuid"] = $child_key_value;
-															if ($this->debug["sql"]) {
-																$message["details"][$m]["sql"] = $sql;
-															}
-															$this->message = $message;
-															$m++;
-														}
-														catch(PDOException $e) {
-															if ($message["code"] = "200") {
-																$message["message"] = "Bad Request";
-																$message["code"] = "400";
-															}
-															$message["details"][$m]["name"] = $key;
-															$message["details"][$m]["message"] = $e->getMessage();
-															$message["details"][$m]["code"] = "400";
-															if ($this->debug["sql"]) {
-																$message["details"][$m]["sql"] = $sql;
-															}
-															$this->message = $message;
-															$m++;
-														}
-													}
-													else {
-														$message["name"] = $child_name;
-														$message["message"] = "Forbidden, does not have '${child_name}_add'";
-														$message["code"] = "403";
-														$message["line"] = __line__;
-														$this->message = $message;
-														$m++;
-													}
-												} //action add
-
-											//unset the variables
-												unset($sql, $action, $child_key_name, $child_key_value);
-										} // foreach value
-
-									} //is array
-								} //foreach array
-
-						} // foreach schema_array
-					}  // foreach main array
-
-				//return the before and after data
-					//log this in the future
-					if (is_array($old_array)) {
-						//normalize the array structure
-							//$old_array = $this->normalize_array($old_array, $this->name);
-
-						//debug info
-							//echo "<pre>\n";
-							//print_r($old_array);
-							//echo "</pre>\n";
-							//exit;
-					}
-					//$message["new"] = $new_array;
-					//$message["new"]["md5"] = md5(json_encode($new_array));
-					$this->message = $message;
-
-				//commit the atomic transaction
-//					$this->db->commit();
-
-				//get the domain uuid
-					$domain_uuid = $_SESSION['domain_uuid'];
-
-				//log the transaction results
-					if (file_exists($_SERVER["PROJECT_ROOT"]."/app/database_transactions/app_config.php")) {
-						$sql = "insert into v_database_transactions ";
-						$sql .= "(";
-						$sql .= "database_transaction_uuid, ";
-						$sql .= "domain_uuid, ";
-						$sql .= "user_uuid, ";
-						if (isset($this->app_uuid)) {
-							$sql .= "app_uuid, ";
-						}
-						$sql .= "app_name, ";
-						$sql .= "transaction_code, ";
-						$sql .= "transaction_address, ";
-						//$sql .= "transaction_type, ";
-						$sql .= "transaction_date, ";
-						$sql .= "transaction_old, ";
-						$sql .= "transaction_new, ";
-						$sql .= "transaction_result ";
-						$sql .= ")";
-						$sql .= "values ";
-						$sql .= "(";
-						$sql .= "'".uuid()."', ";
-						$sql .= "'".$domain_uuid."', ";
-						$sql .= "'".$_SESSION['user_uuid']."', ";
-						if (isset($this->app_uuid)) {
-							$sql .= "'".$this->app_uuid."', ";
-						}
-						$sql .= "'".$this->app_name."', ";
-						$sql .= "'".$message["code"]."', ";
-						$sql .= "'".$_SERVER['REMOTE_ADDR']."', ";
-						//$sql .= "'$transaction_type', ";
-						$sql .= "now(), ";
-						$sql .= "'".check_str(json_encode($old_array, JSON_PRETTY_PRINT))."', ";
-						$sql .= "'".check_str(json_encode($new_array, JSON_PRETTY_PRINT))."', ";
-						$sql .= "'".check_str(json_encode($this->message, JSON_PRETTY_PRINT))."' ";
-						$sql .= ")";
-						$this->db->exec(check_sql($sql));
-						unset($sql);
-					}
-			} //save method
-
-			//define singular function to convert a word in english to singular
-			private function singular($word) {
-				//"-es" is used for words that end in "-x", "-s", "-z", "-sh", "-ch" in which case you add
-				if (substr($word, -2) == "es") {
-					if (substr($word, -3, 1) == "x") {
-						return substr($word,0,-2);
-					}
-					if (substr($word, -3, 1) == "s") {
-						return substr($word,0,-2);
-					}
-					elseif (substr($word, -3, 1) == "z") {
-						return substr($word,0,-2);
-					}
-					elseif (substr($word, -4, 2) == "sh") {
-						return substr($word,0,-2);
-					}
-					elseif (substr($word, -4, 2) == "ch") {
-						return substr($word,0,-2);
-					}
-					else {
-						return rtrim($word, "s");
-					}
-				}
-				else {
-					return rtrim($word, "s");
-				}
-			}
-
-			public function get_apps() {
-				//get the $apps array from the installed apps from the core and mod directories
-					$config_list = glob($_SERVER["DOCUMENT_ROOT"] . PROJECT_PATH . "/*/*/app_config.php");
-					$x = 0;
-					foreach ($config_list as &$config_path) {
-						include($config_path);
-						$x++;
-					}
-					$_SESSION['apps'] = $apps;
-			}
-
-			public function array_depth($array) {
-				if (is_array($array)) {
-					foreach ($array as $value) {
-						if (!isset($depth)) { $depth = 1; }
-						if (is_array($value)) {
-							$depth = $this->array_depth($value) + 1;
-						}
-					}
-				}
-				else {
-					$depth = 0;
-				}
-				return $depth;
-			}
-
-			public function domain_uuid_exists($name) {
-				//get the $apps array from the installed apps from the core and mod directories
-					if (!is_array($_SESSION['apps'])) {
-						$this->get_apps();
-					}
-				//search through all fields to see if domain_uuid exists
-					foreach ($_SESSION['apps'] as $x => &$app) {
-						foreach ($app['db'] as $y => &$row) {
-							if ($row['table'] == $name) {
-								foreach ($row['fields'] as $z => $field) {
-									if ($field['name'] == "domain_uuid") {
-										return true;
-									}
-								}
-							}
-						}
-					}
-				//not found
-					return false;
-			}
-		}
-	}
-
-	//examples
-		/*
-		//get records
-			$orm = new orm();
-			$result = $orm->name('dialplans')->find()->get();
-			print_r($result);
-
-		//get a single record
-			$orm = new orm();
-			$orm->name('dialplans')
-			$orm->uuid('a8363085-8318-4dee-b87f-0818be0d6318');
-			$orm->find();
-			$result = $orm->get();
-			print_r($result);
-
-		//get a single record
-			$array['name'] = "dialplans";
-			$array['uuid'] = "2d27e4a4-c954-4f8a-b734-88b0e1054b86";
-			$orm = new orm();
-			$result = $orm->find($array)->get();
-			print_r($result);
-
-		//get limited records with limit and offset
-			$array['name'] = "dialplans";
-			$array['limit'] = "10";
-			$array['offset'] = "2";
-			$orm = new orm();
-			$result = $orm->find($array)->get();
-			print_r($result);
-		*/
-
-?>

+ 35 - 15
resources/classes/schema.php

@@ -348,8 +348,14 @@ if (!class_exists('schema')) {
 			public function db_create_table ($apps, $db_type, $table) {
 				if (is_array($apps)) foreach ($apps as $x => &$app) {
 					if (is_array($app['db'])) foreach ($app['db'] as $y => $row) {
-						if ($row['table']['name'] == $table) {
-							$sql = "CREATE TABLE " . $row['table']['name'] . " (\n";
+						if (is_array($row['table']['name'])) {
+							$table_name = $row['table']['name']['text'];
+						}
+						else {
+							$table_name = $row['table']['name'];
+						}
+						if ($table_name == $table) {
+							$sql = "CREATE TABLE " . $table_name . " (\n";
 							$field_count = 0;
 							if (is_array($row['fields'])) foreach ($row['fields'] as $field) {
 								if ($field['deprecated'] == "true") {
@@ -585,19 +591,26 @@ if (!class_exists('schema')) {
 						if (isset($app['db'])) foreach ($app['db'] as $y => &$row) {
 							if (is_array($row['table']['name'])) {
 								$table_name = $row['table']['name']['text'];
-								if (!$this->db_table_exists($db_type, $db_name, $row['table']['name']['text'])) {
-									$row['exists'] = "true"; //testing
-									//if (db_table_exists($db_type, $db_name, $row['table']['name']['deprecated'])) {
-										if ($db_type == "pgsql") {
-											$sql_update .= "ALTER TABLE ".$row['table']['name']['deprecated']." RENAME TO ".$row['table']['name']['text'].";\n";
-										}
-										if ($db_type == "mysql") {
-											$sql_update .= "RENAME TABLE ".$row['table']['name']['deprecated']." TO ".$row['table']['name']['text'].";\n";
-										}
-										if ($db_type == "sqlite") {
-											$sql_update .= "ALTER TABLE ".$row['table']['name']['deprecated']." RENAME TO ".$row['table']['name']['text'].";\n";
-										}
-									//}
+								if ($this->db_table_exists($db_type, $db_name, $row['table']['name']['deprecated'])) {
+									$row['exists'] = "false"; //testing
+									if ($db_type == "pgsql") {
+										$sql_update .= "ALTER TABLE ".$row['table']['name']['deprecated']." RENAME TO ".$row['table']['name']['text'].";\n";
+									}
+									if ($db_type == "mysql") {
+										$sql_update .= "RENAME TABLE ".$row['table']['name']['deprecated']." TO ".$row['table']['name']['text'].";\n";
+									}
+									if ($db_type == "sqlite") {
+										$sql_update .= "ALTER TABLE ".$row['table']['name']['deprecated']." RENAME TO ".$row['table']['name']['text'].";\n";
+									}
+								}
+								else {
+									if ($this->db_table_exists($db_type, $db_name, $row['table']['name']['text'])) {
+										$row['exists'] = "true";
+									}
+									else {
+										$row['exists'] = "false";
+										$sql_update .= $this->db_create_table($apps, $db_type, $row['table']['name']['text']);
+									}
 								}
 							}
 							else {
@@ -635,6 +648,11 @@ if (!class_exists('schema')) {
 																$sql_update .= "ALTER TABLE ".$table_name." ADD ".$field['name']." ".$field_type.";\n";
 															}
 														}
+														else {
+															if ($field['exists'] == "false") {
+																$sql_update .= "ALTER TABLE ".$table_name." ADD ".$field['name']["text"]." ".$field_type.";\n";
+															}
+														}
 													}
 												//rename fields where the name has changed
 													if (is_array($field['name'])) {
@@ -672,6 +690,8 @@ if (!class_exists('schema')) {
 																		//field type has not changed
 																	} elseif ($db_field_type = "timestamp without time zone" && strtolower($field_type) == "datetime") {
 																		//field type has not changed
+																	} elseif ($db_field_type = "timestamp with time zone" && strtolower($field_type) == "timestamptz") {
+																		//field type has not changed
 																	} elseif ($db_field_type = "integer" && strtolower($field_type) == "numeric") {
 																		//field type has not changed
 																	} elseif ($db_field_type = "character" && strtolower($field_type) == "char") {

+ 1 - 1
resources/fpdf/fpdf.php

@@ -73,7 +73,7 @@ var $PDFVersion;         // PDF version number
 *                               Public methods                                 *
 *                                                                              *
 *******************************************************************************/
-function FPDF($orientation='P', $unit='mm', $size='A4')
+function __construct($orientation='P', $unit='mm', $size='A4')
 {
 	// Some checks
 	$this->_dochecks();

+ 265 - 110
resources/functions.php

@@ -17,7 +17,7 @@
 
 	The Initial Developer of the Original Code is
 	Mark J Crane <[email protected]>
-	Portions created by the Initial Developer are Copyright (C) 2008-2016
+	Portions created by the Initial Developer are Copyright (C) 2008-2019
 	the Initial Developer. All Rights Reserved.
 
 	Contributor(s):
@@ -27,7 +27,7 @@
 
 	if (!function_exists('software_version')) {
 		function software_version() {
-			return '4.5.1';
+			return '4.5.5';
 		}
 	}
 
@@ -45,6 +45,12 @@
 		}
 	}
 
+	if (!function_exists('mb_strtoupper')) {
+		function mb_strtoupper($string) {
+			return strtoupper($string);
+		}
+	}
+
 	if (!function_exists('check_float')) {
 		function check_float($string) {
 			$string = str_replace(",",".",$string);
@@ -258,7 +264,7 @@
 	if (!function_exists('group_members')) {
 		function group_members($db, $user_uuid) {
 			global $domain_uuid;
-			$sql = "select * from v_group_users ";
+			$sql = "select * from v_user_groups ";
 			$sql .= "where domain_uuid = '$domain_uuid' ";
 			$sql .= "and user_uuid = '".$user_uuid."' ";
 			$prep_statement = $db->prepare(check_sql($sql));
@@ -289,7 +295,7 @@
 	if (!function_exists('superadmin_list')) {
 		function superadmin_list($db) {
 			global $domain_uuid;
-			$sql = "select * from v_group_users ";
+			$sql = "select * from v_user_groups ";
 			$sql .= "where group_name = 'superadmin' ";
 			$prep_statement = $db->prepare(check_sql($sql));
 			$prep_statement->execute();
@@ -766,9 +772,9 @@
 
 				//add the user to the member group
 					$group_name = 'user';
-					$sql = "insert into v_group_users ";
+					$sql = "insert into v_user_groups ";
 					$sql .= "(";
-					$sql .= "group_user_uuid, ";
+					$sql .= "user_group_uuid, ";
 					$sql .= "domain_uuid, ";
 					$sql .= "group_name, ";
 					$sql .= "user_uuid ";
@@ -850,69 +856,86 @@ function format_string ($format, $data) {
 		return $phone_number;
 	}
 
+//format seconds into hh:mm:ss
+	function format_hours($seconds) {
+		$hours = floor($seconds / 3600);
+		$minutes = floor(($seconds / 60) % 60);
+		$seconds = $seconds % 60;
+		if (strlen($minutes) == 1) { $minutes = '0'.$minutes; }
+		if (strlen($seconds) == 1) { $seconds = '0'.$seconds; }
+		return "$hours:$minutes:$seconds";
+	}
+
 //browser detection without browscap.ini dependency
 	function http_user_agent($info = '') {
-		$u_agent = $_SERVER['HTTP_USER_AGENT'];
-		$bname = 'Unknown';
-		$platform = 'Unknown';
-		$version= "";
 
-		//get the platform?
-			if (preg_match('/linux/i', $u_agent)) {
-				$platform = 'linux';
+		//set default values
+			$user_agent = $_SERVER['HTTP_USER_AGENT'];
+			$browser_name = 'Unknown';
+			$platform = 'Unknown';
+			$version = '';
+			$mobile = false;
+
+		//get the platform
+			if (preg_match('/linux/i', $user_agent)) {
+				$platform = 'Linux';
+			}
+			elseif (preg_match('/macintosh|mac os x/i', $user_agent)) {
+				$platform = 'Apple';
 			}
-			elseif (preg_match('/macintosh|mac os x/i', $u_agent)) {
-				$platform = 'mac';
+			elseif (preg_match('/windows|win32/i', $user_agent)) {
+				$platform = 'Windows';
 			}
-			elseif (preg_match('/windows|win32/i', $u_agent)) {
-				$platform = 'windows';
+
+		//set mobile to true or false
+			if (preg_match('/mobile/i', $user_agent)) {
+				$platform = 'Mobile';
+				$mobile = true;
+			}
+			elseif (preg_match('/android/i', $user_agent)) {
+				$platform = 'Android';
+				$mobile = true;
 			}
 
-		//get the name of the useragent yes seperately and for good reason
-			if(preg_match('/MSIE/i',$u_agent) && !preg_match('/Opera/i',$u_agent))
-			{
-				$bname = 'Internet Explorer';
-				$ub = "MSIE";
+		//get the name of the useragent
+			if (preg_match('/MSIE/i',$user_agent) && !preg_match('/Opera/i',$user_agent)) {
+				$browser_name = 'Internet Explorer';
+				$browser_shortname = 'MSIE';
 			}
-			elseif(preg_match('/Firefox/i',$u_agent))
-			{
-				$bname = 'Mozilla Firefox';
-				$ub = "Firefox";
+			elseif (preg_match('/Firefox/i',$user_agent)) {
+				$browser_name = 'Mozilla Firefox';
+				$browser_shortname = 'Firefox';
 			}
-			elseif(preg_match('/Chrome/i',$u_agent))
-			{
-				$bname = 'Google Chrome';
-				$ub = "Chrome";
+			elseif (preg_match('/Chrome/i',$user_agent)) {
+				$browser_name = 'Google Chrome';
+				$browser_shortname = 'Chrome';
 			}
-			elseif(preg_match('/Safari/i',$u_agent))
-			{
-				$bname = 'Apple Safari';
-				$ub = "Safari";
+			elseif (preg_match('/Safari/i',$user_agent)) {
+				$browser_name = 'Apple Safari';
+				$browser_shortname = 'Safari';
 			}
-			elseif(preg_match('/Opera/i',$u_agent))
-			{
-				$bname = 'Opera';
-				$ub = "Opera";
+			elseif (preg_match('/Opera/i',$user_agent)) {
+				$browser_name = 'Opera';
+				$browser_shortname = 'Opera';
 			}
-			elseif(preg_match('/Netscape/i',$u_agent))
-			{
-				$bname = 'Netscape';
-				$ub = "Netscape";
+			elseif (preg_match('/Netscape/i',$user_agent)) {
+				$browser_name = 'Netscape';
+				$browser_shortname = 'Netscape';
 			}
 
 		//finally get the correct version number
-			$known = array('Version', $ub, 'other');
+			$known = array('Version', $browser_shortname, 'other');
 			$pattern = '#(?<browser>' . join('|', $known) . ')[/ ]+(?<version>[0-9.|a-zA-Z.]*)#';
-			if (!preg_match_all($pattern, $u_agent, $matches)) {
-				// we have no matching number just continue
+			if (!preg_match_all($pattern, $user_agent, $matches)) {
+				//we have no matching number just continue
 			}
 
-		// see how many we have
+		//see how many we have
 			$i = count($matches['browser']);
 			if ($i != 1) {
 				//we will have two since we are not using 'other' argument yet
 				//see if version is before or after the name
-				if (strripos($u_agent,"Version") < strripos($u_agent,$ub)){
+				if (strripos($user_agent,"Version") < strripos($user_agent,$browser_shortname)) {
 					$version= $matches['version'][0];
 				}
 				else {
@@ -923,58 +946,63 @@ function format_string ($format, $data) {
 				$version= $matches['version'][0];
 			}
 
-		// check if we have a number
-			if ($version==null || $version=="") {$version="?";}
-
-		switch ($info) {
-			case "agent": return $u_agent; break;
-			case "name": return $bname; break;
-			case "version": return $version; break;
-			case "platform": return $platform; break;
-			case "pattern": return $pattern; break;
-			default :
-				return array(
-					'userAgent' => $u_agent,
-					'name' => $bname,
-					'version' => $version,
-					'platform' => $platform,
-					'pattern' => $pattern
-				);
-		}
+		//check if we have a number
+			if ($version == null || $version == "") { $version = "?"; }
+
+		//return the data
+			switch ($info) {
+				case "agent": return $user_agent; break;
+				case "name": return $browser_name; break;
+				case "version": return $version; break;
+				case "platform": return $platform; break;
+				case "mobile": return $mobile; break;
+				case "pattern": return $pattern; break;
+				default :
+					return array(
+						'user_agent' => $user_agent,
+						'name' => $browser_name,
+						'version' => $version,
+						'platform' => $platform,
+						'mobile' => $mobile,
+						'pattern' => $pattern
+					);
+			}
 	}
 
 //tail php function for non posix systems
 	function tail($file, $num_to_get=10) {
-			$fp = fopen($file, 'r');
-			$position = filesize($file);
-			$chunklen = 4096;
-			if($position-$chunklen<=0) {
+		$fp = fopen($file, 'r');
+		$position = filesize($file);
+		$chunklen = 4096;
+		if($position-$chunklen<=0) {
+			fseek($fp,0);
+		}
+		else {
+			fseek($fp, $position-$chunklen);
+		}
+		$data="";$ret="";$lc=0;
+		while($chunklen > 0) {
+			$data = fread($fp, $chunklen);
+			$dl=strlen($data);
+			for($i=$dl-1;$i>=0;$i--){
+				if($data[$i]=="\n"){
+					if($lc==0 && $ret!="")$lc++;
+					$lc++;
+					if($lc>$num_to_get)return $ret;
+				}
+				$ret=$data[$i].$ret;
+			}
+			if($position-$chunklen<=0){
 				fseek($fp,0);
+				$chunklen=$chunklen-abs($position-$chunklen);
 			}
 			else {
 				fseek($fp, $position-$chunklen);
 			}
-			$data="";$ret="";$lc=0;
-			while($chunklen > 0)
-			{
-					$data = fread($fp, $chunklen);
-					$dl=strlen($data);
-					for($i=$dl-1;$i>=0;$i--){
-							if($data[$i]=="\n"){
-									if($lc==0 && $ret!="")$lc++;
-									$lc++;
-									if($lc>$num_to_get)return $ret;
-							}
-							$ret=$data[$i].$ret;
-					}
-					if($position-$chunklen<=0){
-							fseek($fp,0);
-							$chunklen=$chunklen-abs($position-$chunklen);
-					}else   fseek($fp, $position-$chunklen);
-					$position = $position - $chunklen;
-			}
-			fclose($fp);
-			return $ret;
+			$position = $position - $chunklen;
+		}
+		fclose($fp);
+		return $ret;
 	}
 
 //generate a random password with upper, lowercase and symbols
@@ -982,8 +1010,8 @@ function format_string ($format, $data) {
 		$password = '';
 		$charset = '';
 		if ($length === 0 && $strength === 0) { //set length and strenth if specified in default settings and strength isn't numeric-only
-			$length = (is_numeric($_SESSION["security"]["password_length"]["numeric"])) ? $_SESSION["security"]["password_length"]["numeric"] : 10;
-			$strength = (is_numeric($_SESSION["security"]["password_strength"]["numeric"])) ? $_SESSION["security"]["password_strength"]["numeric"] : 4;
+			$length = (is_numeric($_SESSION["extension"]["password_length"]["numeric"])) ? $_SESSION["extension"]["password_length"]["numeric"] : 10;
+			$strength = (is_numeric($_SESSION["extension"]["password_strength"]["numeric"])) ? $_SESSION["extension"]["password_strength"]["numeric"] : 4;
 		}
 		if ($strength >= 1) { $charset .= "0123456789"; }
 		if ($strength >= 2) { $charset .= "abcdefghijkmnopqrstuvwxyz";	}
@@ -1001,11 +1029,11 @@ function format_string ($format, $data) {
 	function check_password_strength($password, $text, $type = 'default') {
 		if ($password != '') {
 			if ($type == 'default') {
-				$req['length'] = $_SESSION['security']['password_length']['numeric'];
-				$req['number'] = ($_SESSION['security']['password_number']['boolean'] == 'true') ? true : false;
-				$req['lowercase'] = ($_SESSION['security']['password_lowercase']['boolean'] == 'true') ? true : false;
-				$req['uppercase'] = ($_SESSION['security']['password_uppercase']['boolean'] == 'true') ? true : false;
-				$req['special'] = ($_SESSION['security']['password_special']['boolean'] == 'true') ? true : false;
+				$req['length'] = $_SESSION['extension']['password_length']['numeric'];
+				$req['number'] = ($_SESSION['extension']['password_number']['boolean'] == 'true') ? true : false;
+				$req['lowercase'] = ($_SESSION['extension']['password_lowercase']['boolean'] == 'true') ? true : false;
+				$req['uppercase'] = ($_SESSION['extension']['password_uppercase']['boolean'] == 'true') ? true : false;
+				$req['special'] = ($_SESSION['extension']['password_special']['boolean'] == 'true') ? true : false;
 			} elseif ($type == 'user') {
 				$req['length'] = $_SESSION['user']['password_length']['numeric'];
 				$req['number'] = ($_SESSION['user']['password_number']['boolean'] == 'true') ? true : false;
@@ -1029,7 +1057,7 @@ function format_string ($format, $data) {
 				$msg_errors[] = '1+ '.$text['label-special_characters'];
 			}
 			if (is_array($msg_errors) && sizeof($msg_errors) > 0) {
-				messages::add($_SESSION["message"] = $text['message-password_requirements'].': '.implode(', ', $msg_errors), 'negative', 6000);
+				message::add($_SESSION["message"] = $text['message-password_requirements'].': '.implode(', ', $msg_errors), 'negative', 6000);
 				return false;
 			}
 			else {
@@ -1369,7 +1397,7 @@ function number_pad($number,$n) {
 
 //function to send email
 	if (!function_exists('send_email')) {
-		function send_email($eml_recipients, $eml_subject, $eml_body, &$eml_error = '', $eml_from_address = '', $eml_from_name = '', $eml_priority = 3) {
+		function send_email($eml_recipients, $eml_subject, $eml_body, &$eml_error = '', $eml_from_address = '', $eml_from_name = '', $eml_priority = 3, $eml_debug_level = 0) {
 			/*
 			RECIPIENTS NOTE:
 
@@ -1424,23 +1452,37 @@ function number_pad($number,$n) {
 
 			$mail = new PHPMailer();
 			$mail -> IsSMTP();
+			if ($_SESSION['email']['smtp_hostname']['text'] != '') {
+				$mail -> Hostname = $_SESSION['email']['smtp_hostname']['text'];
+			}
 			$mail -> Host = $_SESSION['email']['smtp_host']['text'];
-			if ($_SESSION['email']['smtp_port']['text'] != '') {
-				$mail -> Port = $_SESSION['email']['smtp_port']['text'];
+			if (is_numeric($_SESSION['email']['smtp_port']['numeric'])) {
+				$mail -> Port = $_SESSION['email']['smtp_port']['numeric'];
 			}
 			if ($_SESSION['email']['smtp_auth']['text'] == "true") {
 				$mail -> SMTPAuth = $_SESSION['email']['smtp_auth']['text'];
-			}
-			if ($_SESSION['email']['smtp_username']['text']) {
 				$mail -> Username = $_SESSION['email']['smtp_username']['text'];
 				$mail -> Password = $_SESSION['email']['smtp_password']['text'];
 			}
+			else {
+				$mail -> SMTPAuth = 'false';
+			}
 			if ($_SESSION['email']['smtp_secure']['text'] == "none") {
 				$_SESSION['email']['smtp_secure']['text'] = '';
 			}
 			if ($_SESSION['email']['smtp_secure']['text'] != '') {
 				$mail -> SMTPSecure = $_SESSION['email']['smtp_secure']['text'];
 			}
+			if (isset($_SESSION['email']['smtp_validate_certificate']) && $_SESSION['email']['smtp_validate_certificate']['boolean'] == "false") {
+				// bypass TLS certificate check e.g. for self-signed certificates
+				$mail -> SMTPOptions = array(
+					'ssl' => array(
+					'verify_peer' => false,
+					'verify_peer_name' => false,
+					'allow_self_signed' => true
+					)
+				);
+			}
 			$eml_from_address = ($eml_from_address != '') ? $eml_from_address : $_SESSION['email']['smtp_from']['text'];
 			$eml_from_name = ($eml_from_name != '') ? $eml_from_name : $_SESSION['email']['smtp_from_name']['text'];
 			$mail -> SetFrom($eml_from_address, $eml_from_name);
@@ -1448,6 +1490,9 @@ function number_pad($number,$n) {
 			$mail -> Subject = $eml_subject;
 			$mail -> MsgHTML($eml_body);
 			$mail -> Priority = $eml_priority;
+			if (is_numeric($eml_debug_level) && $eml_debug_level > 0) {
+				$mail -> SMTPDebug = $eml_debug_level;
+			}
 
 			$address_found = false;
 
@@ -1509,15 +1554,20 @@ function number_pad($number,$n) {
 
 //encrypt a string
 	if (!function_exists('encrypt')) {
-		function encrypt($key, $str_to_enc) {
-			return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), $str_to_enc, MCRYPT_MODE_CBC, md5(md5($key))));
+		function encrypt($key, $data) {
+			$encryption_key = base64_decode($key);
+			$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
+			$encrypted = openssl_encrypt($data, 'aes-256-cbc', $encryption_key, 0, $iv);
+			return base64_encode($encrypted.'::'.$iv);
 		}
 	}
 
 //decrypt a string
 	if (!function_exists('decrypt')) {
-		function decrypt($key, $str_to_dec) {
-			return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode($str_to_dec), MCRYPT_MODE_CBC, md5(md5($key))), "\0");
+		function decrypt($key, $data) {
+			$encryption_key = base64_decode($key);
+			list($encrypted_data, $iv) = explode('::', base64_decode($data), 2);
+			return openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0, $iv);
 		}
 	}
 
@@ -1707,11 +1757,15 @@ function number_pad($number,$n) {
 
 //converts a string to a regular expression
 	if (!function_exists('string_to_regex')) {
-		function string_to_regex($string) {
+		function string_to_regex($string, $prefix='') {
 			//escape the plus
 				if (substr($string, 0, 1) == "+") {
 					$string = "^\\+(".substr($string, 1).")$";
 				}
+			//add prefix
+				if (strlen($prefix) > 0) {
+					$prefix = $prefix.'?';
+				}
 			//convert N,X,Z syntax to regex
 				$string = str_ireplace("N", "[2-9]", $string);
 				$string = str_ireplace("X", "[0-9]", $string);
@@ -1724,10 +1778,10 @@ function number_pad($number,$n) {
 				if (substr($string, -1) != "$") {
 					$string = $string."$";
 				}
-			//add the round brackgets ( and )
+			//add the round brackets ( and )
 				if (!strstr($string, '(')) {
 					if (strstr($string, '^')) {
-						$string = str_replace("^", "^(", $string);
+						$string = str_replace("^", "^".$prefix."(", $string);
 					}
 					else {
 						$string = '^('.$string;
@@ -1930,4 +1984,105 @@ function number_pad($number,$n) {
 		//return htmlentities($string, ENT_QUOTES, 'UTF-8');
 	}
 
+//output pre-formatted array keys and values
+	if (!function_exists('view_array')) {
+		function view_array($array, $exit = true) {
+			echo '<br><pre>'.print_r($array, true).'</pre><br>';
+			$exit and exit();
+		}
+	}
+
+//format db date and/or time to local date and/or time
+	if (!function_exists('format_when_local')) {
+		function format_when_local($when, $format = 'dt', $include_seconds = false) {
+			if ($when != '') {
+				// determine when format
+				if (substr_count($when, ' ') > 0) { // date and time
+					$tmp = explode(' ', $when);
+					$date = $tmp[0];
+					$time = $tmp[1];
+				}
+				else if (substr_count($when, '-') > 0) { // date only
+					$date = $when;
+				}
+				else if (substr_count($when, ':') > 0) { // time only
+					$time = $when;
+				}
+				unset($when, $tmp);
+
+				// format date
+				if ($date != '') {
+					$tmp = explode('-', $date);
+					$date = $tmp[1].'-'.$tmp[2].'-'.$tmp[0];
+				}
+
+				// format time
+				if ($time != '') {
+					$tmp = explode(':', $time);
+					if ($tmp[0] >= 0 && $tmp[0] <= 11) {
+						$meridiem = 'AM';
+						$hour = ($tmp[0] == 0) ? 12 : $tmp[0];
+					}
+					else {
+						$meridiem = 'PM';
+						$hour = ($tmp[0] > 12) ? ($tmp[0] - 12) : $tmp[0];
+					}
+					$minute = $tmp[1];
+					$second = $tmp[2];
+				}
+
+				// structure requested time format
+				$time = $hour.':'.$minute;
+				if ($include_seconds) { $time .= ':'.$second; }
+				$time .= ' '.$meridiem;
+
+				$return['d'] = $date;
+				$return['t'] = $time;
+				$return['dt'] = $date.' '.$time;
+
+				return $return[$format];
+			}
+			else {
+				return false;
+			}
+		}
+	}
+
+//define email button (src: https://buttons.cm)
+	if (!function_exists('email_button')) {
+		function email_button($text = 'Click Here!', $link = URL, $bg_color = '#dddddd', $fg_color = '#000000', $radius = '') {
+
+			// default button radius
+			$radius = $radius != '' ? $radius : '3px';
+
+			// retrieve single/first numeric radius value for ms arc
+			$tmp = $radius;
+			if (substr_count($radius, ' ') > 0) {
+				$tmp = explode(' ', $radius);
+				$tmp = $tmp[0];
+			}
+			$tmp = preg_replace("/[^0-9,.]/", '', $tmp); // remove non-numeric characters
+			$arc = floor($tmp / 35 * 100); // calculate percentage
+
+			// create button code
+			$btn = "
+				<div>
+					<!--[if mso]>
+					  <v:roundrect xmlns:v='urn:schemas-microsoft-com:vml' xmlns:w='urn:schemas-microsoft-com:office:word' href='".$link."' style='height: 35px; v-text-anchor: middle; width: 140px;' arcsize='".$arc."%' stroke='f' fillcolor='".$bg_color."'>
+							<w:anchorlock/>
+							<center>
+					<![endif]-->
+					<a href='".$link."' style='background-color: ".$bg_color."; border-radius: ".$radius."; color: ".$fg_color."; display: inline-block; font-family: sans-serif; font-size: 13px; font-weight: bold; line-height: 35px; text-align: center; text-decoration: none; width: 140px; -webkit-text-size-adjust: none;'>".$text."</a>
+					<!--[if mso]>
+							</center>
+						</v:roundrect>
+					<![endif]-->
+				</div>
+				";
+
+			return $btn;
+		}
+	}
+
+
 ?>

+ 1 - 32
resources/licenses.php

@@ -21,7 +21,7 @@
 
 	The Initial Developer of the Original Code is
 	Mark J Crane <[email protected]>
-	Portions created by the Initial Developer are Copyright (C) 2008-2012
+	Portions created by the Initial Developer are Copyright (C) 2008-2019
 	the Initial Developer. All Rights Reserved.
 
 	Contributor(s):
@@ -37,12 +37,6 @@ License: MPL (Mozilla Public License)
 
 //-----------------------------------------------------------------------------------
 
-EditArea
-http://www.cdolivet.com/editarea/editarea/docs/license.html
-License BSD/Apache/LGPL
-
-//-----------------------------------------------------------------------------------
-
 PHPMailer
 http://code.google.com/a/apache-extras.org/p/phpmailer/
 License: LGPL
@@ -94,31 +88,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 //-----------------------------------------------------------------------------------
 
-Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
-AUTHORS:
-  Mike Crawford
-  Ben Maurer
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-//-----------------------------------------------------------------------------------
-
 EmailAddressValidator Class
 http://code.google.com/p/php-email-address-validation/
 

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 60 - 0
resources/login.php


+ 4 - 4
resources/pdo.php

@@ -255,7 +255,7 @@ if ($db_type == "pgsql") {
 } //end if db_type pgsql
 
 //get the domain list
-	if (!is_array($_SESSION['domains']) or (!isset($_SESSION["domain_uuid"])) or (strlen($_SESSION["domain_uuid"]) == 0)) {
+	if (!is_array($_SESSION['domains']) or !isset($_SESSION["domain_uuid"])) {
 
 		//get the domain
 			$domain_array = explode(":", $_SERVER["HTTP_HOST"]);
@@ -333,8 +333,8 @@ if ($db_type == "pgsql") {
 		$domain_uuid = uuid();
 	}
 
-//check the domain cidr range
-	if (is_array($_SESSION['domain']["cidr"])) {
+//check the domain cidr range 
+	if (isset($_SESSION['domain']["cidr"]) && !defined('STDIN')) {
 		$found = false;
 		foreach($_SESSION['domain']["cidr"] as $cidr) {
 			if (check_cidr($cidr, $_SERVER['REMOTE_ADDR'])) {
@@ -349,7 +349,7 @@ if ($db_type == "pgsql") {
 	}
 
 //check the api cidr range
-	if (is_array($_SESSION['api']["cidr"])) {
+	if (isset($_SESSION['api']["cidr"])) {
 		$found = false;
 		foreach($_SESSION['api']["cidr"] as $cidr) {
 			if (check_cidr($cidr, $_SERVER['REMOTE_ADDR'])) {

+ 81 - 0
resources/qr_code/QR8bitByte.php

@@ -0,0 +1,81 @@
+<?php
+/**
+ * This file is part of the phpQr package
+ * 
+ * See @see QRCode class for description of package and license.
+ */
+
+/**
+ * Import necessary dependencies
+ */
+require_once 'QRByte.php';
+require_once 'QRMode.php';
+
+/**
+ * This class provides the 8bit Byte implementaton of a QRByte
+ * 
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ */
+class QR8bitByte implements QRByte
+{
+  /**
+   * The data
+   * @var array
+   */
+  private $data;
+  
+  /**
+   * The mode
+   * @var unknown
+   */
+  private $mode;
+  
+  /**
+   * Retrieve the mode
+   * 
+   * @return int The mode
+   * @see QRByte::getMode()
+   */
+  public function getMode()
+  {
+    return $this->mode;
+  }
+  
+  /**
+   * Retrieve the length
+   * 
+   * @return int The length
+   * @see QRByte::getLength()
+   */
+  public function getLength()
+  {
+    return strlen($this->data);    
+  }
+  
+  /**
+   * Write data to byte
+   * 
+   * @param QRBitBuffer $buffer The data to write into byte
+   * 
+   * @see QRByte::write()
+   */
+  public function write(QRBitBuffer $buffer)
+  {
+    for($i = 0; $i < strlen($this->data); $i++)
+    {
+      $buffer->put(ord($this->data[$i]), 8);
+    }
+  }
+  
+  /**
+   * Create a new instance of a QR8bitByte
+   * 
+   * @param array $data The data for the Byte
+   */
+  public function __construct($data)
+  {
+    $this->data = $data;
+    $this->mode = QRMode::MODE_8BIT_BYTE;
+  }
+}

+ 107 - 0
resources/qr_code/QRBitBuffer.php

@@ -0,0 +1,107 @@
+<?php
+/**
+ * This file is part of the phpQr package
+ *
+ * See @see QRCode class for description of package and license.
+ */
+
+/**
+ * QRBitBuffer class
+ * 
+ * The purpose of this class is to act as data holder for QRCode.
+ * 
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ */
+class QRBitBuffer
+{
+  /**
+   * Array based buffer access
+   * 
+   * @var array
+   */
+  private $buffer;
+  
+  /**
+   * Length of array
+   * 
+   * @var int
+   */
+  private $length;
+  
+  /**
+   * Create a new instance of QRBitBuffer
+   */
+  public function __construct()
+  {
+    $this->buffer = array();
+    $this->length = 0;
+  }
+
+  /**
+   * Get particular bit given by index
+   * 
+   * @param int $index The index of bit
+   * @return boolean
+   */
+  public function get($index)
+  {
+    $bufIndex = floor($index / 8);
+    return ( ($this->buffer[$bufIndex] >> (7 - $index % 8) ) & 1) == 1;
+  }
+  
+  /**
+   * Get the byte at particular index
+   * 
+   * @param int $index The index of the byte
+   * @return string
+   */
+  public function getAt($index)
+  {
+    return $this->buffer[$index];
+  }
+  
+  /**
+   * Put amount of bits
+   * @param int $num The data to put
+   * @param int $length The length of data
+   */
+  public function put($num, $length)
+  {
+    for($i = 0; $i < $length; $i++)
+    {
+      $this->putBit((($num >> ($length - $i - 1)) & 1) == 1);
+    }
+  }
+  
+  /**
+   * Get current length in bits
+   * 
+   * @return int The amount of bits
+   */
+  public function getLengthInBits()
+  {
+    return $this->length;
+  }
+  
+  /**
+   * Put particular bit
+   * 
+   * @param int $bit The bit to put
+   */
+  public function putBit($bit)
+  {
+    $bufIndex = floor($this->length / 8);
+    if(sizeof($this->buffer) <= $bufIndex)
+    {
+      array_push($this->buffer, 0);
+    }
+    
+    if($bit)
+    {
+      $this->buffer[$bufIndex] |= (0x80 >> ($this->length % 8));
+    }
+    
+    $this->length++;
+  }
+}

+ 41 - 0
resources/qr_code/QRByte.php

@@ -0,0 +1,41 @@
+<?php
+/**
+ * This file is part of the phpQr package
+ *
+ * See @see QRCode class for description of package and license.
+ */
+
+/**
+ * Import necessary dependencies
+ */
+require_once 'QRBitBuffer.php';
+
+/**
+ * This interface describes a QRByte implementation
+ * 
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ */
+interface QRByte
+{
+  /**
+   * Retrieve the mode
+   * 
+   * @return  int The mode
+   */
+  public function getMode();
+  
+  /**
+   * Retrieve the length
+   * 
+   * @return int The length
+   */
+  public function getLength();
+  
+  /**
+   * Write data to byte
+   * 
+   * @param QRBitBuffer $buffer The data to write into byte
+   */
+  public function write(QRBitBuffer $buffer);
+}

+ 656 - 0
resources/qr_code/QRCode.php

@@ -0,0 +1,656 @@
+<?php
+/**
+ * This file provides the main QRCode class.
+ * 
+ * The project is a rewrite from jQuery extension available at
+ * @link https://github.com/jeromeetienne/jquery-qrcode
+ * 
+ * For a detailed description of QRCode and its features please check
+ * @link http://www.qrcode.com/
+ * 
+ * QR Code is registered trademark of
+ *  DENSO WAVE INCORPORATED
+ *  http://www.denso-wave.com/qrcode/faqpatent-e.html
+ *  
+ * All files in the package have the same license:
+ * http://opensource.org/licenses/BSD-2-Clause
+ * 
+ * @copyright BSD2
+ * @author Maik Greubel <[email protected]>
+ */
+
+/**
+ * Import necessary dependencies
+ */
+require_once 'QR8bitByte.php';
+require_once 'QRBitBuffer.php';
+require_once 'QRRSBlock.php';
+require_once 'QRUtil.php';
+require_once 'QRCodeException.php';
+
+/**
+ * This is the main class
+ *
+ * It provides the functionality to generate a QRCode bitmap
+ * out of appended data elements.
+ *
+ * @package phpQr
+ * @author Maik Greubel <[email protected]>
+ */
+class QRCode
+{
+  /**
+   * Needed for padding
+   * 
+   * @final
+   *
+   */
+  const PAD0 = 0xec;
+  
+  /**
+   * Needed for padding
+   * 
+   * @final
+   *
+   */
+  const PAD1 = 0x11;
+  
+  /**
+   * The type number of qrcode
+   * 
+   * @var int
+   */
+  private $typeNumber;
+  
+  /**
+   * Level of error correction
+   * 
+   * @see QRErrorCorrectLevel
+   *
+   * @var int
+   */
+  private $errorCorrectLevel;
+  
+  /**
+   * Bitmap
+   * 
+   * @var array
+   */
+  private $modules;
+  
+  /**
+   * Amount of modules in bitmap
+   *
+   * @var int
+   */
+  private $moduleCount;
+  
+  /**
+   * The data as array
+   *
+   * @var array
+   */
+  private $dataCache;
+  
+  /**
+   * All append data elements
+   *
+   * @var array
+   */
+  private $dataList;
+  
+  /**
+   * Create a new instance of QRCode
+   * 
+   * @param int $typeNumber
+   *          The type of QRCode
+   * @param int $errorCorrectLevel
+   *          The error correction level
+   */
+  public function __construct($typeNumber, $errorCorrectLevel)
+  {
+    $this->typeNumber = $typeNumber;
+    $this->errorCorrectLevel = $errorCorrectLevel;
+    $this->modules = null;
+    $this->moduleCount = 0;
+    $this->dataCache = null;
+    $this->dataList = array ();
+  }
+  
+  /**
+   * This function is only needed for debugging purposes and returns the bitmap
+   * DONT USE THIS TO MANIPULATE THE BITMAP!
+   *
+   * @return array
+   */
+  public function getModules()
+  {
+    return $this->modules;
+  }
+  
+  /**
+   * Add a new data element to the QRCode
+   *
+   * @param string $data          
+   */
+  public function addData($data)
+  {
+    $newData = new QR8bitByte ( $data );
+    array_push ( $this->dataList, $newData );
+    $this->dataCache = null;
+  }
+  
+  /**
+   * Returns whether a given bitmap entry is dark or not
+   *
+   * @param int $row
+   *          The row in bitmap
+   * @param int $col
+   *          The column in bitmap
+   *          
+   * @throws QRCodeException
+   * @return true in case of its a dark bit, false otherwise
+   */
+  public function isDark($row, $col)
+  {
+    if ($row < 0 || $this->moduleCount <= $row || $col < 0 || $this->moduleCount <= $col)
+    {
+      throw new QRCodeException ( "$row,$col" );
+    }
+    
+    return $this->modules [$row] [$col];
+  }
+  
+  /**
+   * Get the amount of modules in bitmap
+   *
+   * @return int
+   */
+  public function getModuleCount()
+  {
+    return $this->moduleCount;
+  }
+  
+  /**
+   * Generate the QRCode bitmap
+   */
+  public function make()
+  {
+    if ($this->typeNumber < 1)
+    {
+      $typeNumber = 1;
+      for($typeNumber = 1; $typeNumber < 40; $typeNumber ++)
+      {
+        $rsBlocks = QRRSBlock::getInstance ()->getRSBlocks ( $typeNumber, $this->errorCorrectLevel );
+        
+        $buffer = new QRBitBuffer ();
+        $totalDataCount = 0;
+        for($i = 0; $i < sizeof ( $rsBlocks ); $i ++)
+        {
+          $totalDataCount += $rsBlocks [$i]->getDataCount ();
+        }
+        
+        for($i = 0; $i < sizeof ( $this->dataList ); $i ++)
+        {
+          $data = $this->dataList [$i];
+          
+          assert ( $data instanceof QRByte );
+          
+          $buffer->put ( $data->getMode (), 4 );
+          $buffer->put ( $data->getLength (), QRUtil::getInstance ()->getLengthInBits ( $data->getMode (), $typeNumber ) );
+          $data->write ( $buffer );
+        }
+        if ($buffer->getLengthInBits () <= $totalDataCount * 8)
+          break;
+      }
+      $this->typeNumber = $typeNumber;
+    }
+    $this->makeImpl ( false, $this->getBestMaskPattern () );
+  }
+  
+  /**
+   * Generates the bitmap (really)
+   *
+   * @param boolean $test          
+   * @param int $maskPattern          
+   */
+  private function makeImpl($test, $maskPattern)
+  {
+    $this->moduleCount = $this->typeNumber * 4 + 17;
+    $this->modules = QRUtil::getInstance ()->createEmptyArray ( $this->moduleCount );
+    
+    for($row = 0; $row < $this->moduleCount; $row ++)
+    {
+      $this->modules [$row] = QRUtil::getInstance ()->createEmptyArray ( $this->moduleCount );
+      
+      for($col = 0; $col < $this->moduleCount; $col ++)
+      {
+        $this->modules [$row] [$col] = null;
+      }
+    }
+    
+    $this->setupPositionProbePattern ( 0, 0 );
+    $this->setupPositionProbePattern ( $this->moduleCount - 7, 0 );
+    $this->setupPositionProbePattern ( 0, $this->moduleCount - 7 );
+    $this->setupPositionAdjustPattern ();
+    $this->setupTimingPattern ();
+    $this->setupTypeInfo ( $test, $maskPattern );
+    
+    if ($this->typeNumber >= 7)
+    {
+      $this->setTypeNumber ( $test );
+    }
+    
+    if ($this->dataCache == null)
+    {
+      $this->dataCache = self::createData ( $this->typeNumber, $this->errorCorrectLevel, $this->dataList );
+    }
+    
+    $this->mapData ( $this->dataCache, $maskPattern );
+  }
+  
+  /**
+   * Add the position probes to the bitmap
+   *
+   * @param int $row          
+   * @param int $col          
+   */
+  private function setupPositionProbePattern($row, $col)
+  {
+    for($r = - 1; $r <= 7; $r ++)
+    {
+      if ($row + $r <= - 1 || $this->moduleCount <= $row + $r)
+        continue;
+      
+      for($c = - 1; $c <= 7; $c ++)
+      {
+        if ($col + $c <= - 1 || $this->moduleCount <= $col + $c)
+          continue;
+        
+        if ((0 <= $r && $r <= 6 && ($c == 0 || $c == 6)) || (0 <= $c && $c <= 6 && ($r == 0 || $r == 6)) || (2 <= $r && $r <= 4 && 2 <= $c && $c <= 4))
+        {
+          $this->modules [$row + $r] [$col + $c] = true;
+        }
+        else
+        {
+          $this->modules [$row + $r] [$col + $c] = false;
+        }
+      }
+    }
+  }
+  
+  /**
+   * Get the best mask pattern for this QRCode
+   *
+   * @return int
+   */
+  private function getBestMaskPattern()
+  {
+    $minLostPoint = 0;
+    $pattern = 0;
+    
+    for($i = 0; $i < 8; $i ++)
+    {
+      $this->makeImpl ( true, $i );
+      
+      $lostPoint = QRUtil::getInstance ()->getLostPoint ( $this );
+      
+      if ($i == 0 || $minLostPoint > $lostPoint)
+      {
+        $minLostPoint = $lostPoint;
+        $pattern = $i;
+      }
+    }
+    
+    return $pattern;
+  }
+  
+  /**
+   * Add the timing pattern to bitmap
+   */
+  private function setupTimingPattern()
+  {
+    for($r = 8; $r < $this->moduleCount - 8; $r ++)
+    {
+      if ($this->modules [$r] [6] != null)
+      {
+        continue;
+      }
+      $this->modules [$r] [6] = ($r % 2 == 0);
+    }
+    
+    for($c = 8; $c < $this->moduleCount - 8; $c ++)
+    {
+      if ($this->modules [6] [$c] != null)
+      {
+        continue;
+      }
+      $this->modules [6] [$c] = ($c % 2 == 0);
+    }
+  }
+  
+  /**
+   * Add the position adjust pattern to bitmap
+   */
+  private function setupPositionAdjustPattern()
+  {
+    $pos = QRUtil::getInstance ()->getPatternPosition ( $this->typeNumber );
+    
+    for($i = 0; $i < sizeof ( $pos ); $i ++)
+    {
+      for($j = 0; $j < sizeof ( $pos ); $j ++)
+      {
+        $row = $pos [$i];
+        $col = $pos [$j];
+        
+        if ($this->modules [$row] [$col] != null)
+        {
+          continue;
+        }
+        
+        for($r = - 2; $r <= 2; $r ++)
+        {
+          for($c = - 2; $c <= 2; $c ++)
+          {
+            if ($r == - 2 || $r == 2 || $c == - 2 || $c == 2 || ($r == 0 && $c == 0))
+            {
+              $this->modules [$row + $r] [$col + $c] = true;
+            }
+            else
+            {
+              $this->modules [$row + $r] [$col + $c] = false;
+            }
+          }
+        }
+      }
+    }
+  }
+  
+  /**
+   * Add the type number to bitmap
+   * 
+   * @param boolean $test          
+   */
+  private function setTypeNumber($test)
+  {
+    $bits = QRUtil::getInstance ()->getBCHTypeNumber ( $this->typeNumber );
+    
+    for($i = 0; $i < 18; $i ++)
+    {
+      $mod = (! $test && (($bits >> $i) & 1) == 1);
+      $this->modules [floor ( $i / 3 )] [$i % 3 + $this->moduleCount - 8 - 3] = $mod;
+    }
+    
+    for($i = 0; $i < 18; $i ++)
+    {
+      $mod = (! $test && (($bits >> $i) & 1) == 1);
+      $this->modules [$i % 3 + $this->moduleCount - 8 - 3] [floor ( $i / 3 )] = $mod;
+    }
+  }
+  
+  /**
+   * Add the type info to bitmap
+   *
+   * @param boolean $test          
+   * @param int $maskPattern          
+   */
+  private function setupTypeInfo($test, $maskPattern)
+  {
+    $data = ($this->errorCorrectLevel << 3) | $maskPattern;
+    $bits = QRUtil::getInstance ()->getBCHTypeInfo ( $data );
+    
+    // vertical
+    for($i = 0; $i < 15; $i ++)
+    {
+      $mod = (! $test && (($bits >> $i) & 1) == 1);
+      if ($i < 6)
+      {
+        $this->modules [$i] [8] = $mod;
+      }
+      else if ($i < 8)
+      {
+        $this->modules [$i + 1] [8] = $mod;
+      }
+      else
+      {
+        $this->modules [$this->moduleCount - 15 + $i] [8] = $mod;
+      }
+    }
+    
+    // horizontal
+    for($i = 0; $i < 15; $i ++)
+    {
+      $mod = (! $test && (($bits >> $i) & 1) == 1);
+      
+      if ($i < 8)
+      {
+        $this->modules [8] [$this->moduleCount - $i - 1] = $mod;
+      }
+      else if ($i < 9)
+      {
+        $this->modules [8] [15 - $i - 1 + 1] = $mod;
+      }
+      else
+      {
+        $this->modules [8] [15 - $i - 1] = $mod;
+      }
+    }
+    
+    // fixed module
+    $this->modules [$this->moduleCount - 8] [8] = (! $test);
+  }
+  
+  /**
+   * Add the data to bitmap
+   *
+   * @param array $data          
+   * @param int $maskPattern          
+   */
+  private function mapData($data, $maskPattern)
+  {
+    $inc = - 1;
+    $row = $this->moduleCount - 1;
+    $bitIndex = 7;
+    $byteIndex = 0;
+    
+    for($col = $this->moduleCount - 1; $col > 0; $col -= 2)
+    {
+      if ($col == 6)
+        $col --;
+      
+      while ( true )
+      {
+        for($c = 0; $c < 2; $c ++)
+        {
+          if ($this->modules [$row] [$col - $c] === null)
+          {
+            $dark = false;
+            
+            if ($byteIndex < sizeof ( $data ))
+            {
+              $dark = ((($data [$byteIndex] >> $bitIndex) & 1) == 1);
+            }
+            
+            $mask = QRUtil::getInstance ()->getMask ( $maskPattern, $row, $col - $c );
+            
+            if ($mask)
+              $dark = ! $dark;
+            
+            $this->modules [$row] [$col - $c] = $dark;
+            $bitIndex --;
+            
+            if ($bitIndex == - 1)
+            {
+              $byteIndex ++;
+              $bitIndex = 7;
+            }
+          }
+        }
+        
+        $row += $inc;
+        
+        if ($row < 0 || $this->moduleCount <= $row)
+        {
+          $row -= $inc;
+          $inc = - $inc;
+          break;
+        }
+      }
+    }
+  }
+  
+  /**
+   * Create a bitmap out of all append data elements
+   *
+   * @param int $typeNumber          
+   * @param int $errorCorrectLevel          
+   * @param array $dataList          
+   *
+   * @throws QRCodeException
+   *
+   * @return array
+   */
+  private function createData($typeNumber, $errorCorrectLevel, $dataList)
+  {
+    $rsBlocks = QRRSBlock::getInstance ()->getRSBlocks ( $typeNumber, $errorCorrectLevel );
+    
+    $buffer = new QRBitBuffer ();
+    
+    for($i = 0; $i < sizeof ( $dataList ); $i ++)
+    {
+      $data = $dataList [$i];
+      assert ( $data instanceof QRByte );
+      
+      $buffer->put ( $data->getMode (), 4 );
+      $buffer->put ( $data->getLength (), QRUtil::getInstance ()->getLengthInBits ( $data->getMode (), $typeNumber ) );
+      $data->write ( $buffer );
+    }
+    
+    // calc num max data
+    $totalDataCount = 0;
+    for($i = 0; $i < sizeof ( $rsBlocks ); $i ++)
+    {
+      $totalDataCount += $rsBlocks [$i]->getDataCount ();
+    }
+    
+    if ($buffer->getLengthInBits () > $totalDataCount * 8)
+    {
+      throw new QRCodeException ( "code length overflow (" . $buffer->getLengthInBits () . " > " . ($totalDataCount * 8) . ")" );
+    }
+    
+    // end code
+    if ($buffer->getLengthInBits () + 4 <= $totalDataCount * 8)
+    {
+      $buffer->put ( 0, 4 );
+    }
+    
+    // padding
+    while ( $buffer->getLengthInBits () % 8 != 0 )
+    {
+      $buffer->putBit ( false );
+    }
+    
+    // padding
+    while ( true )
+    {
+      if ($buffer->getLengthInBits () >= $totalDataCount * 8)
+      {
+        break;
+      }
+      
+      $buffer->put ( QRCode::PAD0, 8 );
+      
+      if ($buffer->getLengthInBits () >= $totalDataCount * 8)
+      {
+        break;
+      }
+      $buffer->put ( QRCode::PAD1, 8 );
+    }
+    
+    return $this->createBytes ( $buffer, $rsBlocks );
+  }
+  
+  /**
+   * Create bitmap out of the bit buffer using reed solomon blocks
+   *
+   * @param QRBitBuffer $buffer          
+   * @param array $rsBlocks          
+   * @return array
+   */
+  public function createBytes(QRBitBuffer $buffer, $rsBlocks)
+  {
+    $offset = 0;
+    $maxDcCount = 0;
+    $maxEcCount = 0;
+    
+    $dcdata = QRUtil::getInstance ()->createEmptyArray ( sizeof ( $rsBlocks ) );
+    $ecdata = QRUtil::getInstance ()->createEmptyArray ( sizeof ( $rsBlocks ) );
+    
+    for($r = 0; $r < sizeof ( $rsBlocks ); $r ++)
+    {
+      $dcCount = $rsBlocks [$r]->getDataCount ();
+      $ecCount = $rsBlocks [$r]->getTotalCount () - $dcCount;
+      
+      $maxDcCount = max ( array (
+          $maxDcCount,
+          $dcCount 
+      ) );
+      $maxEcCount = max ( array (
+          $maxEcCount,
+          $ecCount 
+      ) );
+      
+      $dcdata [$r] = QRUtil::getInstance ()->createEmptyArray ( $dcCount );
+      
+      for($i = 0; $i < sizeof ( $dcdata [$r] ); $i ++)
+      {
+        $dcdata [$r] [$i] = 0xff & $buffer->getAt ( $i + $offset );
+      }
+      $offset += $dcCount;
+      
+      $rsPoly = QRUtil::getInstance ()->getErrorCorrectPolynominal ( $ecCount );
+      $rawPoly = new QRPolynominal ( $dcdata [$r], $rsPoly->getLength () - 1 );
+      
+      $modPoly = $rawPoly->mod ( $rsPoly );
+      $ecdata [$r] = QRUtil::getInstance ()->createEmptyArray ( $rsPoly->getLength () - 1 );
+      for($i = 0; $i < sizeof ( $ecdata [$r] ); $i ++)
+      {
+        $modIndex = $i + $modPoly->getLength () - sizeof ( $ecdata [$r] );
+        $ecdata [$r] [$i] = ($modIndex >= 0) ? $modPoly->get ( $modIndex ) : 0;
+      }
+    }
+    
+    $totalCodeCount = 0;
+    for($i = 0; $i < sizeof ( $rsBlocks ); $i ++)
+    {
+      $totalCodeCount += $rsBlocks [$i]->getTotalCount ();
+    }
+    
+    $data = QRUtil::getInstance ()->createEmptyArray ( $totalCodeCount );
+    $index = 0;
+    
+    for($i = 0; $i < $maxDcCount; $i ++)
+    {
+      for($r = 0; $r < sizeof ( $rsBlocks ); $r ++)
+      {
+        if ($i < sizeof ( $dcdata [$r] ))
+        {
+          $data [$index ++] = $dcdata [$r] [$i];
+        }
+      }
+    }
+    
+    for($i = 0; $i < $maxEcCount; $i ++)
+    {
+      for($r = 0; $r < sizeof ( $rsBlocks ); $r ++)
+      {
+        if ($i < sizeof ( $ecdata [$r] ))
+        {
+          $data [$index ++] = $ecdata [$r] [$i];
+        }
+      }
+    }
+    
+    return $data;
+  }
+}

+ 14 - 0
resources/qr_code/QRCodeException.php

@@ -0,0 +1,14 @@
+<?php
+/**
+ * This file is part of the phpQr package
+ *
+ * See @see QRCode class for description of package and license.
+ */
+
+/**
+ * A derived exception
+ *
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ */
+class QRCodeException extends ErrorException {};

+ 187 - 0
resources/qr_code/QRCodeImage.php

@@ -0,0 +1,187 @@
+<?php
+/**
+ * This file is part of the phpQr package
+ *
+ * See @see QRCode class for description of package and license.
+ */
+
+/**
+ * Import necessary dependencies
+ */
+require_once 'QRCodeException.php';
+
+/**
+ * Derived exception class
+ *  
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ */
+class QRCodeImageException extends QRCodeException{};
+
+/**
+ * This class provides all needed functionality to create an image out of an QRCode bitmap
+ * 
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ */
+class QRCodeImage
+{
+  /**
+   * The previously created QRCode
+   * 
+   * @var QRCode
+   */
+  private $qrcode;
+  
+  /**
+   * The desired width of the destination image
+   * 
+   * @var int
+   */
+  private $width;
+
+  /**
+   * The desired height of the destination image
+   * 
+   * @var int
+   */
+  private $height;
+  
+  /**
+   * Quality of the destination image
+   * 
+   * @var int
+   */
+  private $quality;
+  
+  /**
+   * The image buffer provided by GD function imagecreate()
+   * 
+   * @var resource
+   */
+  private $img;
+  
+  /**
+   * Create a new QRCodeImage instance
+   * 
+   * @param QRCode $qrcode The previously created QRCode
+   * @param int $width The desired width of the destination image
+   * @param int $height The desired height of the destination image
+   * @param int $quality The desired quality of the destination image
+   */
+  public function __construct(QRCode $qrcode, $width, $height, $quality = 90)
+  {
+    $this->qrcode = $qrcode;
+    $this->width  = $width;
+    $this->height = $height;
+    $this->quality = $quality;
+    $this->img    = null;
+  }
+  
+  /**
+   * Draw the image
+   */
+  public function draw()
+  {
+    $moduleCount = $this->qrcode->getModuleCount();
+    $tileWidth  = $this->width / $moduleCount;
+    $tileHeight = $this->height / $moduleCount;
+    
+    $this->img = imagecreatetruecolor($this->width, $this->height);
+    
+    if($this->img)
+    {
+      $fg = imagecolorallocate($this->img, 0, 0, 0);
+      if($fg === false)
+      {
+        $this->finish();
+        throw new QRCodeImageException('Could not allocate foreground color!');
+      }
+      $bg = imagecolorallocate($this->img, 255, 255, 255);
+      if($bg === false)
+      {
+        $this->finish();
+        throw new QRCodeImageException('Could not allocate background color!');
+      }
+      
+      for($row = 0; $row < $moduleCount; $row++)
+      {
+        for($col = 0; $col < $moduleCount; $col++)
+        {
+          $fillStyle = $this->qrcode->isDark($row, $col) ? $fg : $bg;
+          
+          $x = round($col * $tileWidth);
+          $y = round($row * $tileHeight);
+          $w = (ceil(($col + 1) * $tileWidth) - floor($col * $tileWidth));
+          if($x + $w > $this->width)
+          {
+            $w = $this->width - $x;
+          }
+          $h = (ceil(($row + 1) * $tileWidth) - floor($row * $tileWidth));
+          if($y + $h > $this->height)
+          {
+            $h = $this->height - $y;
+          }
+          
+          if(!imagefilledrectangle($this->img, $x, $y, $x + $w, $y + $h, $fillStyle))
+          {
+            $this->finish();
+            throw new QRCodeImageException(sprintf('Could not fill the rectangle using desired coordinates (x = %d, y = %d, w = %d, h = %d, c = %d)',
+                $x, $y, $w, $h, $fillStyle));
+          }
+        }
+      }
+    }
+    else
+    {
+      throw new QRCodeImageException('Could not create true color image buffer!');
+    }
+  }
+  
+  /**
+   * Store the image
+   * 
+   * @param string $filename
+   */
+  public function store($filename)
+  {
+    if($this->img)
+    {
+      if(!imagejpeg($this->img, $filename, $this->quality))
+      {
+        throw new QRCodeImageException(sprintf('Could not save image to file %s', $filename));
+      }
+    }
+  }
+  
+  /**
+   * Return the image as string
+   */
+  public function getImage()
+  {
+    if($this->img)
+    {
+      ob_start();
+      if(!imagejpeg($this->img, null, $this->quality))
+      {
+        ob_end_flush();
+        throw new QRCodeImageException('Could not create a jpeg out of the image buffer!');
+      }
+      $out = ob_get_clean();
+      return $out;
+    }
+    throw new QRCodeImageException('No image data available!');
+  }
+  
+  /**
+   * Clean the image buffer
+   */
+  public function finish()
+  {
+    if($this->img)
+    {
+      imagedestroy($this->img);
+      $this->img = null;
+    }
+  }
+}

+ 20 - 0
resources/qr_code/QRErrorCorrectLevel.php

@@ -0,0 +1,20 @@
+<?php
+/**
+ * This file is part of the phpQr package
+ *
+ * See @see QRCode class for description of package and license.
+ */
+
+/**
+ * Error correct level enumeration
+ *
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ */
+abstract class QRErrorCorrectLevel
+{
+  const L = 1;
+  const M = 0;
+  const Q = 3;
+  const H = 2;
+}

+ 145 - 0
resources/qr_code/QRMath.php

@@ -0,0 +1,145 @@
+<?php
+/**
+ * This file is part of the phpQr package
+ *
+ * See @see QRCode class for description of package and license.
+ */
+
+/**
+ * Import necessary dependencies
+ */
+require_once 'QRCodeException.php';
+
+/**
+ * Derived exception
+ * 
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ */
+class QRMathException extends QRCodeException
+{
+}
+
+/**
+ * QR Code math helper class
+ *
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ */
+final class QRMath
+{
+  /**
+   * Exponent table
+   *
+   * @var array
+   */
+  private $EXP_TABLE = null;
+  
+  /**
+   * Logarithm table
+   * 
+   * @var array
+   */
+  private $LOG_TABLE = null;
+  
+  /**
+   * Singleton pattern
+   * 
+   * @var QRMath
+   */
+  private static $instance = null;
+  
+  /**
+   * Singleton pattern
+   *
+   * @return QRMath Singleton
+   */
+  public static function getInstance()
+  {
+    if (! self::$instance)
+    {
+      self::$instance = new self ();
+    }
+    
+    return self::$instance;
+  }
+  
+  /**
+   * Create a new instance of QRMath
+   */
+  private function __construct()
+  {
+    $this->init ();
+  }
+  
+  /**
+   * Initialize the tables
+   */
+  private function init()
+  {
+    $this->EXP_TABLE = array ();
+    for($i = 0; $i < 8; $i ++)
+    {
+      $this->EXP_TABLE [$i] = 1 << $i;
+    }
+    
+    for($i = 8; $i < 256; $i ++)
+    {
+      $this->EXP_TABLE [$i] = $this->EXP_TABLE [$i - 4] ^ $this->EXP_TABLE [$i - 5] ^ $this->EXP_TABLE [$i - 6] ^ $this->EXP_TABLE [$i - 8];
+    }
+    
+    $this->LOG_TABLE = array ();
+    for($i = 0; $i < 255; $i ++)
+    {
+      $this->LOG_TABLE [$this->EXP_TABLE [$i]] = $i;
+    }
+  }
+  
+  /**
+   * Get logarithm of n
+   *
+   * @param int $n          
+   * @throws QRMathException
+   * @return int
+   */
+  public function glog($n)
+  {
+    if ($n < 1)
+    {
+      throw new QRMathException ( "glog(" . $n . ")" );
+    }
+    
+    foreach ( $this->LOG_TABLE as $key => $value )
+    {
+      if ($key == $n)
+        return $value;
+    }
+    
+    throw new QRMathException ( "glog($n)" );
+  }
+  
+  /**
+   * Get the exponent of n
+   *
+   * @param int $n          
+   * @return int
+   */
+  public function gexp($n)
+  {
+    while ( $n < 0 )
+    {
+      $n += 255;
+    }
+    while ( $n >= 256 )
+    {
+      $n -= 255;
+    }
+    foreach ( $this->EXP_TABLE as $key => $value )
+    {
+      if ($key == $n)
+        return $value;
+    }
+    
+    throw new QRMathException ( "gexp($n)" );
+  }
+} 

+ 20 - 0
resources/qr_code/QRMode.php

@@ -0,0 +1,20 @@
+<?php
+/**
+ * This file is part of the phpQr package
+ *
+ * See @see QRCode class for description of package and license.
+ */
+
+/**
+ * QRCode mode enumeration
+ * 
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ */
+abstract class QRMode
+{
+  const MODE_NUMBER = 1;
+  const MODE_ALPHA_NUM = 2;
+  const MODE_8BIT_BYTE = 4;
+  const MODE_KANJI = 8;
+}

+ 145 - 0
resources/qr_code/QRPolynominal.php

@@ -0,0 +1,145 @@
+<?php
+/**
+ * This file is part of the phpQr package
+ *
+ * See @see QRCode class for description of package and license.
+ */
+
+/**
+ * Import necessary dependencies
+ */
+require_once 'QRUtil.php';
+require_once 'QRMath.php';
+require_once 'QRCodeException.php';
+
+/**
+ * Derived exception
+ *
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ */
+class QRPolynominalException extends QRCodeException{};
+
+/**
+ * The purpose of this class is to provide a polynominal implementation for the QRCode package
+ * 
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ */
+class QRPolynominal
+{
+  /**
+   * Bitmap
+   * 
+   * @var array
+   */
+  private $num;
+  
+  /**
+   * Create a new QRPolynominal instance
+   * 
+   * @param array $num
+   * @param int $shift
+   * 
+   * @throws QRPolynominalException
+   */
+  public function __construct($num, $shift)
+  {
+    if(sizeof($num) == 0)
+    {
+      throw new QRPolynominalException("Invalid num size");
+    }
+    
+    $offset = 0;
+    while($offset < sizeof($num) && $num[$offset] == 0)
+    {
+      $offset++;
+    }
+    
+    $this->num = QRUtil::getInstance()->createEmptyArray(sizeof($num) - $offset + $shift);
+    for($i = 0; $i < sizeof($num) - $offset; $i++)
+    {
+      $this->num[$i] = $num[$i + $offset];
+    }
+  }
+  
+  /**
+   * Get a particular bitmap index
+   * 
+   * @param int $index
+   * @return multitype:
+   */
+  public function get($index)
+  {
+    return $this->num[$index];
+  }
+  
+  /**
+   * Get the length of bitmap
+   */
+  public function getLength()
+  {
+    return sizeof($this->num);
+  }
+  
+  /**
+   * Multiply another polynom against this
+   * 
+   * @param QRPolynominal $e The other
+   * @return QRPolynominal The multiplied result
+   */
+  public function multiply(QRPolynominal $e)
+  {
+    $num = QRUtil::getInstance()->createEmptyArray($this->getLength() + $e->getLength() - 1);
+    
+    for($i = 0; $i < $this->getLength(); $i++)
+    {
+      for($j = 0; $j < $e->getLength(); $j++)
+      {
+        $a = QRMath::getInstance()->glog($this->get($i));
+        $b = QRMath::getInstance()->glog($e->get($j));
+        
+        $base = 0;
+        if(isset($num[$i + $j]))
+          $base = $num[$i + $j];
+        $num[$i + $j] = $base ^ QRMath::getInstance()->gexp( $a + $b );
+      }
+    }
+    
+    return new QRPolynominal($num, 0);
+  }
+  
+  /**
+   * Perform modulus against another polynom
+   * 
+   * @param QRPolynominal $e
+   * 
+   * @return QRPolynominal
+   */
+  public function mod(QRPolynominal $e)
+  {
+    if($this->getLength() - $e->getLength() < 0)
+    {
+      return $this;
+    }
+    
+    $ratio = QRMath::getInstance()->glog($this->get(0)) - QRMath::getInstance()->glog($e->get(0));
+    
+    $num = QRUtil::getInstance()->createEmptyArray($this->getLength());
+    
+    for($i = 0; $i < $this->getLength(); $i++)
+    {
+      $num[$i] = $this->get($i);
+    }
+    
+    for($i = 0; $i < $e->getLength(); $i++)
+    {
+      $num[$i] ^= QRMath::getInstance()->gexp(QRMath::getInstance()->glog($e->get($i)) + $ratio);
+    }
+    
+    $result = new QRPolynominal($num, 0);
+    $result = $result->mod($e);
+    
+    return $result;
+  }
+}

+ 503 - 0
resources/qr_code/QRRSBlock.php

@@ -0,0 +1,503 @@
+<?php
+/**
+ * This file is part of the phpQr package
+ *
+ * See @see QRCode class for description of package and license.
+ */
+
+/**
+ * Import necessary dependencies
+ */
+require_once 'QRCodeException.php';
+require_once 'QRErrorCorrectLevel.php';
+
+/**
+ * Derived exception class
+ * 
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ */
+class QRRSBlockException extends QRCodeException
+{ 
+}
+
+/**
+ * This class is a Reed-Solomon implementation for the QRCode.
+ * The purpose is to provide error correction and block information.
+ *
+ * Inspired by qrcode.js from https://github.com/jeromeetienne/jquery-qrcode
+ * 
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ * @link http://www.thonky.com/qr-code-tutorial/error-correction-table/
+ */
+class QRRSBlock
+{
+  /**
+   * The total count of blocks
+   * 
+   * @var int The total count of blocks
+   */
+  private $totalCount;
+  
+  /**
+   * The data count of blocks
+   * 
+   * @var int The data count of blocks
+   */
+  private $dataCount;
+  
+  /**
+   * The block table
+   * @var array The block table
+   */
+  private $RS_BLOCK_TABLE;
+  
+  /**
+   * Singleton pattern
+   * 
+   * @var QRRSBlock Singleton
+   */
+  private static $instance;
+  
+  /**
+   * The serialized block data for faster initialization
+   * 
+   * @var string
+   */
+  private $blockFileName = 'rsblock.dat';
+  
+  /**
+   * Singleton pattern
+   * 
+   * @return QRRSBlock
+   */
+  public static function getInstance()
+  {
+    if(!self::$instance)
+    {
+      self::$instance = new self(0, 0);
+    }
+    
+    return self::$instance;
+  }
+  
+  /**
+   * Retrieve the data count
+   * 
+   * @return int The data count
+   */
+  public function getDataCount()
+  {
+    return $this->dataCount;
+  }
+  
+  /**
+   * Retrieve the total count
+   * 
+   * @return int The total count
+   */
+  public function getTotalCount()
+  {
+    return $this->totalCount;
+  }
+  
+  /**
+   * Create a new QR Reed-Solomon block instance
+   * 
+   * @param int $totalCount The total count of blocks
+   * @param int $dataCount The data count of blocks
+   */
+  private function __construct($totalCount, $dataCount)
+  {
+    $this->initRsBlock();
+    
+    $this->totalCount = $totalCount;
+    $this->dataCount  = $dataCount;
+  }
+  
+  /**
+   * Get rs blocks of particular type and error correction level
+   * 
+   * @param int $typeNumber
+   * @param int $errorCorrectLevel
+   * @throws QRRSBlockException
+   * @return QRRSBlock
+   */
+  public function getRSBlocks($typeNumber, $errorCorrectLevel)
+  {
+    $rsBlock = $this->getRsBlockTable($typeNumber, $errorCorrectLevel);
+    
+    if(!$rsBlock)
+    {
+      throw new QRRSBlockException("Bad RS Block at type number " . $typeNumber . " / error correct level " . $errorCorrectLevel);
+    }
+    
+    $length = sizeof($rsBlock) / 3;
+    
+    $list = array();
+    
+    for($i = 0; $i < $length; $i++)
+    {
+      $count = $rsBlock[$i * 3 + 0];
+      $totalCount = $rsBlock[$i * 3 + 1];
+      $dataCount = $rsBlock[$i * 3 + 2];
+      
+      for($j = 0; $j < $count; $j++)
+      {
+        array_push($list, new QRRSBlock($totalCount, $dataCount));
+      }
+    }
+    
+    return $list;
+  }
+  
+  /**
+   * Get the reed-solomon block table
+   * 
+   * @param int $typeNumber
+   * @param int $errorCorrectLevel
+   * @return int|NULL
+   */
+  public function getRsBlockTable($typeNumber, $errorCorrectLevel)
+  {
+    switch ($errorCorrectLevel)
+    {
+      case QRErrorCorrectLevel::L:
+        return $this->RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 0];
+      case QRErrorCorrectLevel::M:
+        return $this->RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 1];
+      case QRErrorCorrectLevel::Q:
+        return $this->RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 2];
+      case QRErrorCorrectLevel::H:
+        return $this->RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 3];
+      default:
+        return null;
+    }
+  }
+  
+  /**
+   * This method initialize the RS block
+   */
+  private function initRsBlock()
+  {
+    if($this->loadBlockFile())
+    {
+      return;
+    }
+    
+    $this->RS_BLOCK_TABLE = array();
+    
+    // L
+    // M
+    // Q
+    // H
+    
+    // 1
+    $this->addRsBlock(array(1, 26, 19));
+    $this->addRsBlock(array(1, 26, 16));
+    $this->addRsBlock(array(1, 26, 13));
+    $this->addRsBlock(array(1, 26, 9));
+    
+    // 2
+    $this->addRsBlock(array(1, 44, 34));
+    $this->addRsBlock(array(1, 44, 28));
+    $this->addRsBlock(array(1, 44, 22));
+    $this->addRsBlock(array(1, 44, 16));
+    
+    // 3
+    $this->addRsBlock(array(1, 70, 55));
+    $this->addRsBlock(array(1, 70, 44));
+    $this->addRsBlock(array(2, 35, 17));
+    $this->addRsBlock(array(2, 35, 13));
+    
+    // 4
+    $this->addRsBlock(array(1, 100, 80));
+    $this->addRsBlock(array(2, 50, 32));
+    $this->addRsBlock(array(2, 50, 24));
+    $this->addRsBlock(array(4, 25, 9));
+    
+    // 5
+    $this->addRsBlock(array(1, 134, 108));
+    $this->addRsBlock(array(2, 67, 43));
+    $this->addRsBlock(array(2, 33, 15, 2, 34, 16));
+    $this->addRsBlock(array(2, 33, 11, 2, 34, 12));
+    
+    // 6
+    $this->addRsBlock(array(2, 86, 68));
+    $this->addRsBlock(array(4, 43, 27));
+    $this->addRsBlock(array(4, 43, 19));
+    $this->addRsBlock(array(4, 43, 15));
+    
+    // 7
+    $this->addRsBlock(array(2, 98, 78));
+    $this->addRsBlock(array(4, 49, 31));
+    $this->addRsBlock(array(2, 32, 14, 4, 33, 15));
+    $this->addRsBlock(array(4, 39, 13, 1, 40, 14));
+    
+    // 8
+    $this->addRsBlock(array(2, 121, 97));
+    $this->addRsBlock(array(2, 60, 38, 2, 61, 39));
+    $this->addRsBlock(array(4, 40, 18, 2, 41, 19));
+    $this->addRsBlock(array(4, 40, 14, 2, 41, 15));
+    
+    // 9
+    $this->addRsBlock(array(2, 146, 116));
+    $this->addRsBlock(array(3, 58, 36, 2, 59, 37));
+    $this->addRsBlock(array(4, 36, 16, 4, 37, 17));
+    $this->addRsBlock(array(4, 36, 12, 4, 37, 13));
+    
+    // 10
+    $this->addRsBlock(array(2, 86, 68, 2, 87, 69));
+    $this->addRsBlock(array(4, 69, 43, 1, 70, 44));
+    $this->addRsBlock(array(6, 43, 19, 2, 44, 20));
+    $this->addRsBlock(array(6, 43, 15, 2, 44, 16));
+    
+    // 11
+    $this->addRsBlock(array(4, 101, 81));
+    $this->addRsBlock(array(1, 80, 50, 4, 81, 51));
+    $this->addRsBlock(array(4, 50, 22, 4, 51, 23));
+    $this->addRsBlock(array(3, 36, 12, 8, 37, 13));
+    
+    // 12
+    $this->addRsBlock(array(2, 116, 92, 2, 117, 93));
+    $this->addRsBlock(array(6, 58, 36, 2, 59, 37));
+    $this->addRsBlock(array(4, 46, 20, 6, 47, 21));
+    $this->addRsBlock(array(7, 42, 14, 4, 43, 15));
+    
+    // 13
+    $this->addRsBlock(array(4, 133, 107));
+    $this->addRsBlock(array(8, 59, 37, 1, 60, 38));
+    $this->addRsBlock(array(8, 44, 20, 4, 45, 21));
+    $this->addRsBlock(array(12, 33, 11, 4, 34, 12));
+    
+    // 14
+    $this->addRsBlock(array(3, 145, 115, 1, 146, 116));
+    $this->addRsBlock(array(4, 64, 40, 5, 65, 41));
+    $this->addRsBlock(array(11, 36, 16, 5, 37, 17));
+    $this->addRsBlock(array(11, 36, 12, 5, 37, 13));
+    
+    // 15
+    $this->addRsBlock(array(5, 109, 87, 1, 110, 88));
+    $this->addRsBlock(array(5, 65, 41, 5, 66, 42));
+    $this->addRsBlock(array(5, 54, 24, 7, 55, 25));
+    $this->addRsBlock(array(11, 36, 12));
+    
+    // 16
+    $this->addRsBlock(array(5, 122, 98, 1, 123, 99));
+    $this->addRsBlock(array(7, 73, 45, 3, 74, 46));
+    $this->addRsBlock(array(15, 43, 19, 2, 44, 20));
+    $this->addRsBlock(array(3, 45, 15, 13, 46, 16));
+    
+    // 17
+    $this->addRsBlock(array(1, 135, 107, 5, 136, 108));
+    $this->addRsBlock(array(10, 74, 46, 1, 75, 47));
+    $this->addRsBlock(array(1, 50, 22, 15, 51, 23));
+    $this->addRsBlock(array(2, 42, 14, 17, 43, 15));
+    
+    // 18
+    $this->addRsBlock(array(5, 150, 120, 1, 151, 121));
+    $this->addRsBlock(array(9, 69, 43, 4, 70, 44));
+    $this->addRsBlock(array(17, 50, 22, 1, 51, 23));
+    $this->addRsBlock(array(2, 42, 14, 19, 43, 15));
+    
+    // 19
+    $this->addRsBlock(array(3, 141, 113, 4, 142, 114));
+    $this->addRsBlock(array(3, 70, 44, 11, 71, 45));
+    $this->addRsBlock(array(17, 47, 21, 4, 48, 22));
+    $this->addRsBlock(array(9, 39, 13, 16, 40, 14));
+    
+    // 20
+    $this->addRsBlock(array(3, 135, 107, 5, 136, 108));
+    $this->addRsBlock(array(3, 67, 41, 13, 68, 42));
+    $this->addRsBlock(array(15, 54, 24, 5, 55, 25));
+    $this->addRsBlock(array(15, 43, 15, 10, 44, 16));
+    
+    // 21
+    $this->addRsBlock(array(4, 144, 116, 4, 145, 117));
+    $this->addRsBlock(array(17, 68, 42));
+    $this->addRsBlock(array(17, 50, 22, 6, 51, 23));
+    $this->addRsBlock(array(19, 46, 16, 6, 47, 17));
+    
+    // 22
+    $this->addRsBlock(array(2, 139, 111, 7, 140, 112));
+    $this->addRsBlock(array(17, 74, 46));
+    $this->addRsBlock(array(7, 54, 24, 16, 55, 25));
+    $this->addRsBlock(array(34, 37, 13));
+    
+    // 23
+    $this->addRsBlock(array(4, 151, 121, 5, 152, 122));
+    $this->addRsBlock(array(4, 75, 47, 14, 76, 48));
+    $this->addRsBlock(array(11, 54, 24, 14, 55, 25));
+    $this->addRsBlock(array(16, 45, 15, 14, 46, 16));
+    
+    // 24
+    $this->addRsBlock(array(6, 147, 117, 4, 148, 118));
+    $this->addRsBlock(array(6, 73, 45, 14, 74, 46));
+    $this->addRsBlock(array(11, 54, 24, 16, 55, 25));
+    $this->addRsBlock(array(30, 46, 16, 2, 47, 17));
+    
+    // 25
+    $this->addRsBlock(array(8, 132, 106, 4, 133, 107));
+    $this->addRsBlock(array(8, 75, 47, 13, 76, 48));
+    $this->addRsBlock(array(7, 54, 24, 22, 55, 25));
+    $this->addRsBlock(array(22, 45, 15, 13, 46, 16));
+    
+    // 26
+    $this->addRsBlock(array(10, 142, 114, 2, 143, 115));
+    $this->addRsBlock(array(19, 74, 46, 4, 75, 47));
+    $this->addRsBlock(array(28, 50, 22, 6, 51, 23));
+    $this->addRsBlock(array(33, 46, 16, 4, 47, 17));
+    
+    // 27
+    $this->addRsBlock(array(8, 152, 122, 4, 153, 123));
+    $this->addRsBlock(array(22, 73, 45, 3, 74, 46));
+    $this->addRsBlock(array(8, 53, 23, 26, 54, 24));
+    $this->addRsBlock(array(12, 45, 15, 28, 46, 16));
+    
+    // 28
+    $this->addRsBlock(array(3, 147, 117, 10, 148, 118));
+    $this->addRsBlock(array(3, 73, 45, 23, 74, 46));
+    $this->addRsBlock(array(4, 54, 24, 31, 55, 25));
+    $this->addRsBlock(array(11, 45, 15, 31, 46, 16));
+    
+    // 29
+    $this->addRsBlock(array(7, 146, 116, 7, 147, 117));
+    $this->addRsBlock(array(21, 73, 45, 7, 74, 46));
+    $this->addRsBlock(array(1, 53, 23, 37, 54, 24));
+    $this->addRsBlock(array(19, 45, 15, 26, 46, 16));
+    
+    // 30
+    $this->addRsBlock(array(5, 145, 115, 10, 146, 116));
+    $this->addRsBlock(array(19, 75, 47, 10, 76, 48));
+    $this->addRsBlock(array(15, 54, 24, 25, 55, 25));
+    $this->addRsBlock(array(23, 45, 15, 25, 46, 16));
+    
+    // 31
+    $this->addRsBlock(array(13, 145, 115, 3, 146, 116));
+    $this->addRsBlock(array(2, 74, 46, 29, 75, 47));
+    $this->addRsBlock(array(42, 54, 24, 1, 55, 25));
+    $this->addRsBlock(array(23, 45, 15, 28, 46, 16));
+    
+    // 32
+    $this->addRsBlock(array(17, 145, 115));
+    $this->addRsBlock(array(10, 74, 46, 23, 75, 47));
+    $this->addRsBlock(array(42, 54, 24, 1, 55, 25));
+    $this->addRsBlock(array(23, 45, 15, 28, 46, 16));
+    
+    // 33
+    $this->addRsBlock(array(17, 145, 115, 1, 146, 116));
+    $this->addRsBlock(array(14, 74, 46, 21, 75, 47));
+    $this->addRsBlock(array(29, 54, 24, 19, 55, 25));
+    $this->addRsBlock(array(11, 45, 15, 46, 46, 16));
+    
+    // 34
+    $this->addRsBlock(array(13, 145, 115, 6, 146, 116));
+    $this->addRsBlock(array(14, 74, 46, 21, 75, 47));
+    $this->addRsBlock(array(44, 54, 24, 7, 55, 25));
+    $this->addRsBlock(array(59, 46, 16, 1, 47, 17));
+    
+    // 35
+    $this->addRsBlock(array(12, 151, 121, 7, 152, 122));
+    $this->addRsBlock(array(12, 75, 47, 26, 76, 48));
+    $this->addRsBlock(array(39, 54, 24, 14, 55, 25));
+    $this->addRsBlock(array(22, 45, 15, 41, 46, 16));
+    
+    // 36
+    $this->addRsBlock(array(6, 151, 121, 14, 152, 122));
+    $this->addRsBlock(array(6, 75, 47, 34, 76, 48));
+    $this->addRsBlock(array(46, 54, 24, 10, 55, 25));
+    $this->addRsBlock(array(2, 45, 15, 64, 46, 16));
+    
+    // 37
+    $this->addRsBlock(array(17, 152, 122, 4, 153, 123));
+    $this->addRsBlock(array(29, 74, 46, 14, 75, 47));
+    $this->addRsBlock(array(49, 54, 24, 10, 55, 25));
+    $this->addRsBlock(array(24, 45, 15, 46, 46, 16));
+    
+    // 38
+    $this->addRsBlock(array(4, 152, 122, 18, 153, 123));
+    $this->addRsBlock(array(13, 74, 46, 32, 75, 47));
+    $this->addRsBlock(array(48, 54, 24, 14, 55, 25));
+    $this->addRsBlock(array(42, 45, 15, 32, 46, 16));
+    
+    // 39
+    $this->addRsBlock(array(20, 147, 117, 4, 148, 118));
+    $this->addRsBlock(array(40, 75, 47, 7, 76, 48));
+    $this->addRsBlock(array(43, 54, 24, 22, 55, 25));
+    $this->addRsBlock(array(10, 45, 15, 67, 46, 16));
+    
+    // 40
+    $this->addRsBlock(array(19, 148, 118, 6, 149, 119));
+    $this->addRsBlock(array(18, 75, 47, 31, 76, 48));
+    $this->addRsBlock(array(34, 54, 24, 34, 55, 25));
+    $this->addRsBlock(array(20, 45, 15, 61, 46, 16));
+    
+    $this->saveBlockFile();
+  }
+  
+  /**
+   * Add a new block information to the block
+   * 
+   * @param array $block
+   */
+  private function addRsBlock($block)
+  {
+    array_push($this->RS_BLOCK_TABLE, $block);
+  }
+  
+  /**
+   * Return the absolute path to the block file
+   * @return string
+   */
+  private function getBlockFileAbsolute()
+  {
+    return sprintf("%s%s%s", dirname(__FILE__), DIRECTORY_SEPARATOR, $this->blockFileName);
+  }
+  
+  /**
+   * Try to load the block file
+   * 
+   * @return boolean
+   */
+  private function loadBlockFile()
+  {
+    $file = $this->getBlockFileAbsolute();
+    
+    if(!file_exists($file))
+    {
+      return false;
+    }
+    
+    $serialized = file_get_contents($file);
+    
+    if(!$serialized)
+    {
+      return false;
+    }
+    
+    $this->RS_BLOCK_TABLE = unserialize($serialized);
+    
+    if(!$this->RS_BLOCK_TABLE)
+    {
+      return false;
+    }
+    
+    return true;
+  }
+  
+  /**
+   * Try to save the block file
+   */
+  private function saveBlockFile()
+  {
+    $file = $this->getBlockFileAbsolute();
+    
+    if(file_exists($file))
+    {
+      unlink($file);
+    }
+    
+    file_put_contents($file, serialize($this->RS_BLOCK_TABLE));
+  }
+}

+ 464 - 0
resources/qr_code/QRUtil.php

@@ -0,0 +1,464 @@
+<?php
+/**
+ * This file is part of the phpQr package
+ *
+ * See @see QRCode class for description of package and license.
+ */
+
+/**
+ * Import necessary dependencies
+ */
+require_once 'QRCodeException.php';
+require_once 'QRPolynominal.php';
+
+/**
+ * Derived exception
+ *
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ */
+class QRUtilException extends QRCodeException {};
+
+/**
+ * Mask pattern enumeration
+ * 
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ */
+abstract class QRMaskPattern
+{
+  const PATTERN000 = 0;
+  const PATTERN001 = 1;
+  const PATTERN010 = 2;
+  const PATTERN011 = 3;
+  const PATTERN100 = 4;
+  const PATTERN101 = 5;
+  const PATTERN110 = 6;
+  const PATTERN111 = 7;
+}
+
+/**
+ * The purpose of this class is to provide some common utility
+ * functionality for the QRCode class and its parts.
+ *  
+ * @author Maik Greubel <[email protected]>
+ * @package phpQr
+ */
+class QRUtil
+{
+  /**
+   * Pattern position table
+   * 
+   * @var array
+   */
+  private $PATTERN_POSITION_TABLE = null;
+  
+  /**
+   * 
+   * @var int G15 pattern
+   */
+  private $G15;
+  
+  /**
+   * 
+   * @var int G18 pattern
+   */
+  private $G18;
+  
+  /**
+   * 
+   * @var int G15 mask pattern
+   */
+  private $G15_MASK;
+  
+  /**
+   * 
+   * @var QRUtil Singleton
+   */
+  private static $instance;
+  
+  /**
+   * Singleton pattern
+   * 
+   * @return QRUtil
+   */
+  public static function getInstance()
+  {
+    if(!self::$instance)
+    {
+      self::$instance = new self;
+    }
+    
+    return self::$instance;
+  }
+  
+  /**
+   * Create a new instance of QRUtil
+   */
+  private function __construct()
+  {
+    $this->init();
+    $this->G15 = ((1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0));
+    $this->G18 = ((1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0));
+    $this->G15_MASK = ((1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1));
+  }
+  
+  /**
+   * Retrieve the Bose-Chaudhuri-Hocquenghem code type info
+   * 
+   * @param array $data
+   * 
+   * @return int
+   */
+  public function getBCHTypeInfo($data)
+  {
+    $d = $data << 10;
+    while($this->getBCHDigit($d) - $this->getBCHDigit($this->G15) >= 0)
+    {
+      $d ^= ($this->G15 << ($this->getBCHDigit($d) - $this->getBCHDigit($this->G15)));
+    }
+    
+    return (($data << 10) | $d) ^ $this->G15_MASK;
+  }
+  
+  /**
+   * Retrieve the Bose-Chaudhuri-Hocquenghem code type number
+   * 
+   * @param array $data
+   * 
+   * @return int
+   */
+  public function getBCHTypeNumber($data)
+  {
+    $d = $data << 12;
+    while($this->getBCHDigit($d) - $this->getBCHDigit($this->G18) >= 0)
+    {
+      $d ^= ($this->G18 << ($this->getBCHDigit($d) - $this->getBCHDigit($this->G18)));
+    }
+    return ($data << 12) | $d;
+  }
+  
+  /**
+   * Retrieve the Bose-Chaudhuri-Hocquenghem digit
+   * 
+   * @param array $data
+   * 
+   * @return int
+   */
+  public function getBCHDigit($data)
+  {
+    $digit = 0;
+    while($data != 0)
+    {
+      $digit++;
+      $data = $data >> 1;
+    }
+    
+    return $digit;
+  }
+  
+  /**
+   * Return the pattern position
+   * 
+   * @param int $typeNumber
+   * @return array
+   */
+  public function getPatternPosition($typeNumber)
+  {
+    return $this->PATTERN_POSITION_TABLE[$typeNumber - 1];
+  }
+  
+  /**
+   * Return whether to mask a bit
+   * 
+   * @param int $maskPattern
+   * @param int $i
+   * @param int $j
+   * @throws QRUtilException
+   * @return boolean
+   */
+  public function getMask($maskPattern, $i, $j)
+  {
+    switch($maskPattern)
+    {
+      case QRMaskPattern::PATTERN000: return ($i + $j) % 2 == 0;
+      case QRMaskPattern::PATTERN001: return ($i % 2) == 0;
+      case QRMaskPattern::PATTERN010: return ($j % 3) == 0;
+      case QRMaskPattern::PATTERN011: return ($i + $j) % 3 == 0;
+      case QRMaskPattern::PATTERN100: return (floor($i / 2) + floor($j / 3)) % 2 == 0;
+      case QRMaskPattern::PATTERN101: return ($i * $j) % 2 + ($i * $j) % 3 == 0;
+      case QRMaskPattern::PATTERN110: return (($i * $j) % 2 + ($i * $j) % 3) % 2 == 0;
+      case QRMaskPattern::PATTERN111: return (($i * $j) % 3 + ($i + $j) % 2) % 2 == 0;
+      
+      default: throw new QRUtilException("Bad mask pattern " . $maskPattern); 
+    }
+  }
+  
+  /**
+   * Return error correction polynom
+   * 
+   * @param int $errorCorrectLength
+   * @return QRPolynominal
+   */
+  public function getErrorCorrectPolynominal($errorCorrectLength)
+  {
+    $a = new QRPolynominal(array(1), 0);
+    for($i = 0; $i < $errorCorrectLength; $i++)
+    {
+      $a = $a->multiply(new QRPolynominal(array(1, QRMath::getInstance()->gexp($i)), 0));
+    }
+    
+    return $a;
+  }
+  
+  /**
+   * Get the bitmap length in bits
+   * 
+   * @param int $mode
+   * @param int $type
+   * @throws QRUtilException
+   * @return int
+   */
+  public function getLengthInBits($mode, $type)
+  {
+    // 1 - 9
+    if(1 <= $type && $type < 10)
+    {
+      switch($mode)
+      {
+        case QRMode::MODE_NUMBER:     return 10;
+        case QRMode::MODE_ALPHA_NUM:  return 9;
+        case QRMode::MODE_8BIT_BYTE:  return 8;
+        case QRMode::MODE_KANJI:      return 8;
+        default: throw new QRUtilException("Bad mode " . $mode);
+      }
+    }
+    // 10 - 26
+    else if($type < 27)
+    {
+      switch($mode)
+      {
+        case QRMode::MODE_NUMBER:     return 12;
+        case QRMode::MODE_ALPHA_NUM:  return 11;
+        case QRMode::MODE_8BIT_BYTE:  return 16;
+        case QRMode::MODE_KANJI:      return 10;
+        default: throw new QRUtilException("Bad mode " . $mode);
+      }
+    }
+    // 27 - 40
+    else if($type < 41)
+    {
+      switch($mode)
+      {
+        case QRMode::MODE_NUMBER:     return 14;
+        case QRMode::MODE_ALPHA_NUM:  return 13;
+        case QRMode::MODE_8BIT_BYTE:  return 16;
+        case QRMode::MODE_KANJI:      return 12;
+        default: throw new QRUtilException("Bad mode " . $mode);
+        
+      }      
+    }
+    else
+    {
+      throw new QRUtilException("Bad type " . $type);
+    }
+  }
+  
+  /**
+   * Calculate the lost point
+   * 
+   * @param QRCode $qrCode
+   * 
+   * @return number
+   */
+  public function getLostPoint(QRCode $qrCode)
+  {
+    $moduleCount = $qrCode->getModuleCount();
+    
+    $lostPoint = 0;
+    
+    // Level 1
+    for($row = 0; $row < $moduleCount; $row++)
+    {
+      for($col = 0; $col < $moduleCount; $col++)
+      {
+        $sameCount = 0;
+        $dark = $qrCode->isDark($row, $col);
+        
+        for($r = -1; $r <= 1; $r++)
+        {
+          if($row + $r < 0 || $moduleCount <= $row + $r)
+          {
+            continue;
+          }
+          
+          for($c = -1; $c <= 1; $c++)
+          {
+            if($col + $c < 0 || $moduleCount <= $col + $c)
+            {
+              continue;
+            }
+            
+            if($r == 0 && $c == 0)
+            {
+              continue;
+            }
+            
+            if($dark == $qrCode->isDark($row + $r, $col + $c))
+            {
+              $sameCount++;
+            }
+          }
+        }
+        
+        if($sameCount > 5)
+        {
+          $lostPoint += (3 + $sameCount - 5);
+        }
+      }
+    }
+    
+    // Level 2
+    for($row = 0; $row < $moduleCount - 1; $row++)
+    {
+      for($col = 0; $col < $moduleCount - 1; $col++)
+      {
+        $count = 0;
+        if($qrCode->isDark($row,      $col    )) $count++;
+        if($qrCode->isDark($row + 1,  $col    )) $count++;
+        if($qrCode->isDark($row,      $col + 1)) $count++;
+        if($qrCode->isDark($row + 1,  $col + 1)) $count++;
+        if($count == 0 || $count == 4)
+        {
+          $lostPoint += 3;
+        }
+      }
+    }
+    
+    // Level 3
+    for($row = 0; $row < $moduleCount; $row++)
+    {
+      for($col = 0; $col < $moduleCount - 6; $col++)
+      {
+        if($qrCode->isDark($row, $col)
+          && !$qrCode->isDark($row, $col + 1)
+          &&  $qrCode->isDark($row, $col + 2)
+          &&  $qrCode->isDark($row, $col + 3)
+          &&  $qrCode->isDark($row, $col + 4)
+          && !$qrCode->isDark($row, $col + 5)
+          &&  $qrCode->isDark($row, $col + 6))
+        {
+          $lostPoint += 40;
+        }
+      }
+    }
+    
+    for($col = 0; $col < $moduleCount; $col++)
+    {
+      for($row = 0; $row < $moduleCount - 6; $row++)
+      {
+        if($qrCode->isDark($row, $col)
+          && !$qrCode->isDark($row + 1, $col)
+          &&  $qrCode->isDark($row + 2, $col)
+          &&  $qrCode->isDark($row + 3, $col)
+          &&  $qrCode->isDark($row + 4, $col)
+          && !$qrCode->isDark($row + 5, $col)
+          &&  $qrCode->isDark($row + 6, $col))
+        {
+          $lostPoint += 40;
+        }
+      }
+    }
+    
+    // Level 4
+    $darkCount = 0;
+    
+    for($col = 0; $col < $moduleCount; $col++)
+    {
+      for($row = 0; $row < $moduleCount; $row++)
+      {
+        if($qrCode->isDark($row, $col))
+        {
+          $darkCount++;
+        }
+      }
+    }
+    
+    $ratio = abs(100 * $darkCount / $moduleCount / $moduleCount - 50) / 5;
+    $lostPoint += $ratio * 10;
+    
+    return $lostPoint;
+  }
+  
+  /**
+   * Initialize the pattern position table
+   */
+  private function init()
+  {
+    $this->PATTERN_POSITION_TABLE = array();
+    
+    $this->addPattern(array());
+    $this->addPattern(array(6, 18));
+    $this->addPattern(array(6, 22));
+    $this->addPattern(array(6, 26));
+    $this->addPattern(array(6, 30));
+    $this->addPattern(array(6, 34));
+    $this->addPattern(array(6, 22, 38));
+    $this->addPattern(array(6, 24, 42));
+    $this->addPattern(array(6, 26, 46));
+    $this->addPattern(array(6, 28, 50));
+    $this->addPattern(array(6, 30, 54));
+    $this->addPattern(array(6, 32, 58));
+    $this->addPattern(array(6, 34, 62));
+    $this->addPattern(array(6, 26, 46, 66));
+    $this->addPattern(array(6, 26, 48, 70));
+    $this->addPattern(array(6, 26, 50, 74));
+    $this->addPattern(array(6, 30, 54, 78));
+    $this->addPattern(array(6, 30, 56, 82));
+    $this->addPattern(array(6, 30, 58, 86));
+    $this->addPattern(array(6, 34, 62, 90));
+    $this->addPattern(array(6, 28, 50, 72, 94));
+    $this->addPattern(array(6, 26, 50, 74, 98));
+    $this->addPattern(array(6, 30, 54, 78, 102));
+    $this->addPattern(array(6, 28, 54, 80, 106));
+    $this->addPattern(array(6, 32, 58, 84, 110));
+    $this->addPattern(array(6, 30, 58, 86, 114));
+    $this->addPattern(array(6, 34, 62, 90, 118));
+    $this->addPattern(array(6, 26, 50, 74, 98, 122));
+    $this->addPattern(array(6, 30, 54, 78, 102, 126));
+    $this->addPattern(array(6, 26, 52, 78, 104, 130));
+    $this->addPattern(array(6, 30, 56, 82, 108, 134));
+    $this->addPattern(array(6, 34, 60, 86, 112, 138));
+    $this->addPattern(array(6, 30, 58, 86, 114, 142));
+    $this->addPattern(array(6, 34, 62, 90, 118, 146));
+    $this->addPattern(array(6, 30, 54, 78, 102, 126, 150));
+    $this->addPattern(array(6, 24, 50, 76, 102, 128, 154));
+    $this->addPattern(array(6, 28, 54, 80, 106, 132, 158));
+    $this->addPattern(array(6, 32, 58, 84, 110, 136, 162));
+    $this->addPattern(array(6, 26, 54, 82, 110, 138, 166));
+    $this->addPattern(array(6, 30, 58, 86, 114, 142, 170));
+  }
+  
+  /**
+   * Add a pattern to the pattern position table
+   * 
+   * @param array $d
+   */
+  private function addPattern($d)
+  {
+    array_push($this->PATTERN_POSITION_TABLE, $d);
+  }
+  
+  /**
+   * Create an empty array of n elements
+   * 
+   * All elements are uninitialed.
+   * 
+   * @param int $numElements
+   * @return array
+   */
+  public function createEmptyArray($numElements)
+  {
+    return array_fill(0, $numElements, null);
+  }
+}

+ 30 - 0
resources/qr_code/README.md

@@ -0,0 +1,30 @@
+phpQr - A QRCode encoder class
+===
+
+by Maik Greubel ([email protected])
+
+The intention to create a basic qrcode encoder for PHP was a request on phpclasses.org.
+-
+
+The author studied multiple sources to get an idea how qrcode implementation works under the hood. 
+The best source was the JavaScript library jquery which provides a HTML Table based implementation.
+See source and documentation at  <https://github.com/jeromeetienne/jquery-qrcode>
+
+So the hard work was already done by Jerome Etienne. My part was only to port it to PHP code.
+
+Currently this package does not have the capability to read QRCodes.
+
+Further readings
+-
+For a detailed description of QRCode and its features please check  <http://www.qrcode.com/>
+
+Trademark information
+-
+
+QR Code is registered trademark of  
+DENSO WAVE INCORPORATED  <http://www.denso-wave.com/qrcode/faqpatent-e.html>
+
+License
+-
+All files in the package are published under the terms of the BSD 2 License.  <http://opensource.org/licenses/BSD-2-Clause>
+ 

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
resources/qr_code/rsblock.dat


+ 0 - 268
resources/recaptchalib.php

@@ -1,268 +0,0 @@
-<?php
-/*
- * This is a PHP library that handles calling reCAPTCHA.
- *    - Documentation and latest version
- *          http://recaptcha.net/plugins/php/
- *    - Get a reCAPTCHA API Key
- *          https://www.google.com/recaptcha/admin/create
- *    - Discussion group
- *          http://groups.google.com/group/recaptcha
- *
- * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
- * AUTHORS:
- *   Mike Crawford
- *   Ben Maurer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-/**
- * The reCAPTCHA server URL's
- */
-define("RECAPTCHA_API_SERVER", "http://www.google.com/recaptcha/api");
-define("RECAPTCHA_API_SECURE_SERVER", "https://www.google.com/recaptcha/api");
-define("RECAPTCHA_VERIFY_SERVER", "www.google.com");
-
-/**
- * Encodes the given data into a query string format
- * @param $data - array of string elements to be encoded
- * @return string - encoded request
- */
-function _recaptcha_qsencode ($data) {
-        $req = "";
-        foreach ( $data as $key => $value )
-                $req .= $key . '=' . urlencode( stripslashes($value) ) . '&';
-
-        // Cut the last '&'
-        $req=substr($req,0,strlen($req)-1);
-        return $req;
-}
-
-/**
- * Submits an HTTP POST to a reCAPTCHA server
- * @param string $host
- * @param string $path
- * @param array $data
- * @param int port
- * @return array response
- */
-function _recaptcha_http_post($host, $path, $data, $port = 80) {
-
-        $req = _recaptcha_qsencode ($data);
-
-        $http_request  = "POST $path HTTP/1.0\r\n";
-        $http_request .= "Host: $host\r\n";
-        $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
-        $http_request .= "Content-Length: " . strlen($req) . "\r\n";
-        $http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
-        $http_request .= "\r\n";
-        $http_request .= $req;
-
-        $response = '';
-        if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
-                die ('Could not open socket');
-        }
-
-        fwrite($fs, $http_request);
-
-        while ( !feof($fs) )
-                $response .= fgets($fs, 1160); // One TCP-IP packet
-        fclose($fs);
-        $response = explode("\r\n\r\n", $response, 2);
-
-        return $response;
-}
-
-/**
- * Gets the challenge HTML (javascript and non-javascript version).
- * This is called from the browser, and the resulting reCAPTCHA HTML widget
- * is embedded within the HTML form it was called from.
- * @param string $pubkey A public key for reCAPTCHA
- * @param string $error The error given by reCAPTCHA (optional, default is null)
- * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false)
-
- * @return string - The HTML to be embedded in the user's form.
- */
-function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false)
-{
-	if ($pubkey == null || $pubkey == '') {
-		require_once "resources/header.php";
-		echo "To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>";
-		require_once "resources/footer.php";
-		exit;
-	}
-
-	if ($use_ssl) {
-                $server = RECAPTCHA_API_SECURE_SERVER;
-        } else {
-                $server = RECAPTCHA_API_SERVER;
-        }
-
-        $errorpart = "";
-        if ($error) {
-           $errorpart = "&amp;error=" . $error;
-        }
-        return '<script type="text/javascript" src="'. $server . '/challenge?k=' . $pubkey . $errorpart . '"></script>
-
-	<noscript>
-  		<iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/>
-  		<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
-  		<input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
-	</noscript>';
-}
-
-/**
- * A ReCaptchaResponse is returned from recaptcha_check_answer()
- */
-class ReCaptchaResponse {
-        var $is_valid;
-        var $error;
-}
-
-/**
-  * Calls an HTTP POST function to verify if the user's guess was correct
-  * @param string $privkey
-  * @param string $remoteip
-  * @param string $challenge
-  * @param string $response
-  * @param array $extra_params an array of extra variables to post to the server
-  * @return ReCaptchaResponse
-  */
-function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array())
-{
-	if ($privkey == null || $privkey == '') {
-		die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
-	}
-
-	if ($remoteip == null || $remoteip == '') {
-		die ("For security reasons, you must pass the remote ip to reCAPTCHA");
-	}
-
-        //discard spam submissions
-        if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
-                $recaptcha_response = new ReCaptchaResponse();
-                $recaptcha_response->is_valid = false;
-                $recaptcha_response->error = 'incorrect-captcha-sol';
-                return $recaptcha_response;
-        }
-
-        $response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify",
-                                          array (
-                                                 'privatekey' => $privkey,
-                                                 'remoteip' => $remoteip,
-                                                 'challenge' => $challenge,
-                                                 'response' => $response
-                                                 ) + $extra_params
-                                          );
-
-        $answers = explode ("\n", $response [1]);
-        $recaptcha_response = new ReCaptchaResponse();
-
-        if (trim ($answers [0]) == 'true') {
-                $recaptcha_response->is_valid = true;
-        }
-        else {
-                $recaptcha_response->is_valid = false;
-                $recaptcha_response->error = $answers [1];
-        }
-        return $recaptcha_response;
-
-}
-
-/**
- * gets a URL where the user can sign up for reCAPTCHA. If your application
- * has a configuration page where you enter a key, you should provide a link
- * using this function.
- * @param string $_SESSION['domain_name'] The domain where the page is hosted
- * @param string $app_name The name of your application
- */
-function recaptcha_get_signup_url ($domain_name = null, $app_name = null) {
-	return "https://www.google.com/recaptcha/admin/create?" .  _recaptcha_qsencode (array ('domains' => $domain_name, 'app' => $app_name));
-}
-
-function _recaptcha_aes_pad($val) {
-	$block_size = 16;
-	$numpad = $block_size - (strlen ($val) % $block_size);
-	return str_pad($val, strlen ($val) + $numpad, chr($numpad));
-}
-
-/* Mailhide related code */
-
-function _recaptcha_aes_encrypt($val,$ky) {
-	if (! function_exists ("mcrypt_encrypt")) {
-		die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
-	}
-	$mode=MCRYPT_MODE_CBC;
-	$enc=MCRYPT_RIJNDAEL_128;
-	$val=_recaptcha_aes_pad($val);
-	return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
-}
-
-function _recaptcha_mailhide_urlbase64 ($x) {
-	return strtr(base64_encode ($x), '+/', '-_');
-}
-
-/* gets the reCAPTCHA Mailhide url for a given email, public key and private key */
-function recaptcha_mailhide_url($pubkey, $privkey, $email) {
-	if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) {
-		die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " .
-		     "you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey'>http://www.google.com/recaptcha/mailhide/apikey</a>");
-	}
-
-
-	$ky = pack('H*', $privkey);
-	$cryptmail = _recaptcha_aes_encrypt ($email, $ky);
-
-	return "http://www.google.com/recaptcha/mailhide/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail);
-}
-
-/**
- * gets the parts of the email to expose to the user.
- * eg, given johndoe@example,com return ["john", "example.com"].
- * the email is then displayed as [email protected]
- */
-function _recaptcha_mailhide_email_parts ($email) {
-	$arr = preg_split("/@/", $email );
-
-	if (strlen ($arr[0]) <= 4) {
-		$arr[0] = substr ($arr[0], 0, 1);
-	} else if (strlen ($arr[0]) <= 6) {
-		$arr[0] = substr ($arr[0], 0, 3);
-	} else {
-		$arr[0] = substr ($arr[0], 0, 4);
-	}
-	return $arr;
-}
-
-/**
- * Gets html to display an email address given a public an private key.
- * to get a key, go to:
- *
- * http://www.google.com/recaptcha/mailhide/apikey
- */
-function recaptcha_mailhide_html($pubkey, $privkey, $email) {
-	$emailparts = _recaptcha_mailhide_email_parts ($email);
-	$url = recaptcha_mailhide_url ($pubkey, $privkey, $email);
-
-	return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
-		"' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
-
-}
-
-?>

+ 110 - 0
resources/templates/engine/smarty/Autoloader.php

@@ -0,0 +1,110 @@
+<?php
+/**
+ * Smarty Autoloader
+ *
+ * @package Smarty
+ */
+
+/**
+ * Smarty Autoloader
+ *
+ * @package Smarty
+ * @author  Uwe Tews
+ *             Usage:
+ *                  require_once '...path/Autoloader.php';
+ *                  Smarty_Autoloader::register();
+ *             or
+ *                  include '...path/bootstrap.php';
+ *
+ *                  $smarty = new Smarty();
+ */
+class Smarty_Autoloader
+{
+    /**
+     * Filepath to Smarty root
+     *
+     * @var string
+     */
+    public static $SMARTY_DIR = null;
+
+    /**
+     * Filepath to Smarty internal plugins
+     *
+     * @var string
+     */
+    public static $SMARTY_SYSPLUGINS_DIR = null;
+
+    /**
+     * Array with Smarty core classes and their filename
+     *
+     * @var array
+     */
+    public static $rootClasses = array('smarty' => 'Smarty.class.php', 'smartybc' => 'SmartyBC.class.php',);
+
+    /**
+     * Registers Smarty_Autoloader backward compatible to older installations.
+     *
+     * @param bool $prepend Whether to prepend the autoloader or not.
+     */
+    public static function registerBC($prepend = false)
+    {
+        /**
+         * register the class autoloader
+         */
+        if (!defined('SMARTY_SPL_AUTOLOAD')) {
+            define('SMARTY_SPL_AUTOLOAD', 0);
+        }
+        if (SMARTY_SPL_AUTOLOAD
+            && set_include_path(get_include_path() . PATH_SEPARATOR . SMARTY_SYSPLUGINS_DIR) !== false
+        ) {
+            $registeredAutoLoadFunctions = spl_autoload_functions();
+            if (!isset($registeredAutoLoadFunctions[ 'spl_autoload' ])) {
+                spl_autoload_register();
+            }
+        } else {
+            self::register($prepend);
+        }
+    }
+
+    /**
+     * Registers Smarty_Autoloader as an SPL autoloader.
+     *
+     * @param bool $prepend Whether to prepend the autoloader or not.
+     */
+    public static function register($prepend = false)
+    {
+        self::$SMARTY_DIR = defined('SMARTY_DIR') ? SMARTY_DIR : dirname(__FILE__) . DIRECTORY_SEPARATOR;
+        self::$SMARTY_SYSPLUGINS_DIR = defined('SMARTY_SYSPLUGINS_DIR') ? SMARTY_SYSPLUGINS_DIR :
+            self::$SMARTY_DIR . 'sysplugins' . DIRECTORY_SEPARATOR;
+        if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
+            spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
+        } else {
+            spl_autoload_register(array(__CLASS__, 'autoload'));
+        }
+    }
+
+    /**
+     * Handles auto loading of classes.
+     *
+     * @param string $class A class name.
+     */
+    public static function autoload($class)
+    {
+        if ($class[ 0 ] !== 'S' && strpos($class, 'Smarty') !== 0) {
+            return;
+        }
+        $_class = strtolower($class);
+        if (isset(self::$rootClasses[ $_class ])) {
+            $file = self::$SMARTY_DIR . self::$rootClasses[ $_class ];
+            if (is_file($file)) {
+                include $file;
+            }
+        } else {
+            $file = self::$SMARTY_SYSPLUGINS_DIR . $_class . '.php';
+            if (is_file($file)) {
+                include $file;
+            }
+        }
+        return;
+    }
+}

+ 15 - 1
resources/templates/engine/smarty/Smarty.license.txt → resources/templates/engine/smarty/LICENSE

@@ -1,3 +1,17 @@
+Smarty: the PHP compiling template engine
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ See the GNU Lesser General Public License below for more details.
+
+
                    GNU LESSER GENERAL PUBLIC LICENSE
                        Version 3, 29 June 2007
 
@@ -162,4 +176,4 @@ General Public License ever published by the Free Software Foundation.
 whether future versions of the GNU Lesser General Public License shall
 apply, that proxy's public statement of acceptance of any version is
 permanent authorization for you to choose that version for the
-Library.
+Library.

+ 11 - 10
resources/templates/engine/smarty/README

@@ -1,4 +1,4 @@
-Smarty 3.1.15
+Smarty 3.x
 
 Author: Monte Ohrt <monte at ohrt dot com >
 Author: Uwe Tews
@@ -260,12 +260,12 @@ Example: {$object->method1($x)->method2($y)}
 {for} tag added for looping (replacement for {section} tag):
 {for $x=0, $y=count($foo); $x<$y; $x++}  ....  {/for}
 Any number of statements can be used separated by comma as the first
-inital expression at {for}.
+initial expression at {for}.
 
 {for $x = $start to $end step $step} ... {/for}is in the SVN now .
 You can use also
 {for $x = $start to $end} ... {/for}
-In this case the step value will be automaticall 1 or -1 depending on the start and end values.
+In this case the step value will be automatically 1 or -1 depending on the start and end values.
 Instead of $start and $end you can use any valid expression.
 Inside the loop the following special vars can be accessed:
 $x@iteration = number of iteration
@@ -460,19 +460,20 @@ included template.
 PLUGINS
 =======
 
-Smarty3 are following the same coding rules as in Smarty2.
-The only difference is that the template object is passed as additional third parameter.
+Smarty 3 plugins follow the same coding rules as in Smarty 2.
+The main difference is that the template object is now passed in place of the smarty object.
+The smarty object can be still be accessed through $template->smarty.
 
-smarty_plugintype_name (array $params, object $smarty, object $template)
+smarty_plugintype_name (array $params, Smarty_Internal_Template $template)
 
-The Smarty 2 plugins are still compatible as long as they do not make use of specific Smarty2 internals.
+The Smarty 2 plugins are still compatible as long as they do not make use of specific Smarty 2 internals.
 
 
 TEMPLATE INHERITANCE:
 =====================
 
 With template inheritance you can define blocks, which are areas that can be
-overriden by child templates, so your templates could look like this:
+overridden by child templates, so your templates could look like this:
 
 parent.tpl:
 <html>
@@ -507,8 +508,8 @@ grandchild.tpl:
 
 We redefined all the blocks here, however in the title block we used {$smarty.block.parent},
 which tells Smarty to insert the default content from the parent template in its place.
-The content block was overriden to display the image files, and page-title has also be
-overriden to display a completely different title.
+The content block was overridden to display the image files, and page-title has also be
+overridden to display a completely different title.
 
 If we render grandchild.tpl we will get this:
 <html>

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 359 - 426
resources/templates/engine/smarty/Smarty.class.php


+ 477 - 0
resources/templates/engine/smarty/SmartyBC.class.php

@@ -0,0 +1,477 @@
+<?php
+/**
+ * Project:     Smarty: the PHP compiling template engine
+ * File:        SmartyBC.class.php
+ * SVN:         $Id: $
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * For questions, help, comments, discussion, etc., please join the
+ * Smarty mailing list. Send a blank e-mail to
+ * [email protected]
+ *
+ * @link      http://www.smarty.net/
+ * @copyright 2008 New Digital Group, Inc.
+ * @author    Monte Ohrt <monte at ohrt dot com>
+ * @author    Uwe Tews
+ * @author    Rodney Rehm
+ * @package   Smarty
+ */
+/**
+ * @ignore
+ */
+require_once dirname(__FILE__) . '/Smarty.class.php';
+
+/**
+ * Smarty Backward Compatibility Wrapper Class
+ *
+ * @package Smarty
+ */
+class SmartyBC extends Smarty
+{
+    /**
+     * Smarty 2 BC
+     *
+     * @var string
+     */
+    public $_version = self::SMARTY_VERSION;
+
+    /**
+     * This is an array of directories where trusted php scripts reside.
+     *
+     * @var array
+     */
+    public $trusted_dir = array();
+
+    /**
+     * Initialize new SmartyBC object
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * wrapper for assign_by_ref
+     *
+     * @param string $tpl_var the template variable name
+     * @param mixed  &$value  the referenced value to assign
+     */
+    public function assign_by_ref($tpl_var, &$value)
+    {
+        $this->assignByRef($tpl_var, $value);
+    }
+
+    /**
+     * wrapper for append_by_ref
+     *
+     * @param string  $tpl_var the template variable name
+     * @param mixed   &$value  the referenced value to append
+     * @param boolean $merge   flag if array elements shall be merged
+     */
+    public function append_by_ref($tpl_var, &$value, $merge = false)
+    {
+        $this->appendByRef($tpl_var, $value, $merge);
+    }
+
+    /**
+     * clear the given assigned template variable.
+     *
+     * @param string $tpl_var the template variable to clear
+     */
+    public function clear_assign($tpl_var)
+    {
+        $this->clearAssign($tpl_var);
+    }
+
+    /**
+     * Registers custom function to be used in templates
+     *
+     * @param string $function      the name of the template function
+     * @param string $function_impl the name of the PHP function to register
+     * @param bool   $cacheable
+     * @param mixed  $cache_attrs
+     *
+     * @throws \SmartyException
+     */
+    public function register_function($function, $function_impl, $cacheable = true, $cache_attrs = null)
+    {
+        $this->registerPlugin('function', $function, $function_impl, $cacheable, $cache_attrs);
+    }
+
+    /**
+     * Unregister custom function
+     *
+     * @param string $function name of template function
+     */
+    public function unregister_function($function)
+    {
+        $this->unregisterPlugin('function', $function);
+    }
+
+    /**
+     * Registers object to be used in templates
+     *
+     * @param string  $object        name of template object
+     * @param object  $object_impl   the referenced PHP object to register
+     * @param array   $allowed       list of allowed methods (empty = all)
+     * @param boolean $smarty_args   smarty argument format, else traditional
+     * @param array   $block_methods list of methods that are block format
+     *
+     * @throws   SmartyException
+     * @internal param array $block_functs list of methods that are block format
+     */
+    public function register_object(
+        $object,
+        $object_impl,
+        $allowed = array(),
+        $smarty_args = true,
+        $block_methods = array()
+    ) {
+        settype($allowed, 'array');
+        settype($smarty_args, 'boolean');
+        $this->registerObject($object, $object_impl, $allowed, $smarty_args, $block_methods);
+    }
+
+    /**
+     * Unregister object
+     *
+     * @param string $object name of template object
+     */
+    public function unregister_object($object)
+    {
+        $this->unregisterObject($object);
+    }
+
+    /**
+     * Registers block function to be used in templates
+     *
+     * @param string $block      name of template block
+     * @param string $block_impl PHP function to register
+     * @param bool   $cacheable
+     * @param mixed  $cache_attrs
+     *
+     * @throws \SmartyException
+     */
+    public function register_block($block, $block_impl, $cacheable = true, $cache_attrs = null)
+    {
+        $this->registerPlugin('block', $block, $block_impl, $cacheable, $cache_attrs);
+    }
+
+    /**
+     * Unregister block function
+     *
+     * @param string $block name of template function
+     */
+    public function unregister_block($block)
+    {
+        $this->unregisterPlugin('block', $block);
+    }
+
+    /**
+     * Registers compiler function
+     *
+     * @param string $function      name of template function
+     * @param string $function_impl name of PHP function to register
+     * @param bool   $cacheable
+     *
+     * @throws \SmartyException
+     */
+    public function register_compiler_function($function, $function_impl, $cacheable = true)
+    {
+        $this->registerPlugin('compiler', $function, $function_impl, $cacheable);
+    }
+
+    /**
+     * Unregister compiler function
+     *
+     * @param string $function name of template function
+     */
+    public function unregister_compiler_function($function)
+    {
+        $this->unregisterPlugin('compiler', $function);
+    }
+
+    /**
+     * Registers modifier to be used in templates
+     *
+     * @param string $modifier      name of template modifier
+     * @param string $modifier_impl name of PHP function to register
+     *
+     * @throws \SmartyException
+     */
+    public function register_modifier($modifier, $modifier_impl)
+    {
+        $this->registerPlugin('modifier', $modifier, $modifier_impl);
+    }
+
+    /**
+     * Unregister modifier
+     *
+     * @param string $modifier name of template modifier
+     */
+    public function unregister_modifier($modifier)
+    {
+        $this->unregisterPlugin('modifier', $modifier);
+    }
+
+    /**
+     * Registers a resource to fetch a template
+     *
+     * @param string $type      name of resource
+     * @param array  $functions array of functions to handle resource
+     */
+    public function register_resource($type, $functions)
+    {
+        $this->registerResource($type, $functions);
+    }
+
+    /**
+     * Unregister a resource
+     *
+     * @param string $type name of resource
+     */
+    public function unregister_resource($type)
+    {
+        $this->unregisterResource($type);
+    }
+
+    /**
+     * Registers a prefilter function to apply
+     * to a template before compiling
+     *
+     * @param callable $function
+     *
+     * @throws \SmartyException
+     */
+    public function register_prefilter($function)
+    {
+        $this->registerFilter('pre', $function);
+    }
+
+    /**
+     * Unregister a prefilter function
+     *
+     * @param callable $function
+     */
+    public function unregister_prefilter($function)
+    {
+        $this->unregisterFilter('pre', $function);
+    }
+
+    /**
+     * Registers a postfilter function to apply
+     * to a compiled template after compilation
+     *
+     * @param callable $function
+     *
+     * @throws \SmartyException
+     */
+    public function register_postfilter($function)
+    {
+        $this->registerFilter('post', $function);
+    }
+
+    /**
+     * Unregister a postfilter function
+     *
+     * @param callable $function
+     */
+    public function unregister_postfilter($function)
+    {
+        $this->unregisterFilter('post', $function);
+    }
+
+    /**
+     * Registers an output filter function to apply
+     * to a template output
+     *
+     * @param callable $function
+     *
+     * @throws \SmartyException
+     */
+    public function register_outputfilter($function)
+    {
+        $this->registerFilter('output', $function);
+    }
+
+    /**
+     * Unregister an outputfilter function
+     *
+     * @param callable $function
+     */
+    public function unregister_outputfilter($function)
+    {
+        $this->unregisterFilter('output', $function);
+    }
+
+    /**
+     * load a filter of specified type and name
+     *
+     * @param string $type filter type
+     * @param string $name filter name
+     *
+     * @throws \SmartyException
+     */
+    public function load_filter($type, $name)
+    {
+        $this->loadFilter($type, $name);
+    }
+
+    /**
+     * clear cached content for the given template and cache id
+     *
+     * @param string $tpl_file   name of template file
+     * @param string $cache_id   name of cache_id
+     * @param string $compile_id name of compile_id
+     * @param string $exp_time   expiration time
+     *
+     * @return boolean
+     */
+    public function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null)
+    {
+        return $this->clearCache($tpl_file, $cache_id, $compile_id, $exp_time);
+    }
+
+    /**
+     * clear the entire contents of cache (all templates)
+     *
+     * @param string $exp_time expire time
+     *
+     * @return boolean
+     */
+    public function clear_all_cache($exp_time = null)
+    {
+        return $this->clearCache(null, null, null, $exp_time);
+    }
+
+    /**
+     * test to see if valid cache exists for this template
+     *
+     * @param string $tpl_file name of template file
+     * @param string $cache_id
+     * @param string $compile_id
+     *
+     * @return bool
+     * @throws \Exception
+     * @throws \SmartyException
+     */
+    public function is_cached($tpl_file, $cache_id = null, $compile_id = null)
+    {
+        return $this->isCached($tpl_file, $cache_id, $compile_id);
+    }
+
+    /**
+     * clear all the assigned template variables.
+     */
+    public function clear_all_assign()
+    {
+        $this->clearAllAssign();
+    }
+
+    /**
+     * clears compiled version of specified template resource,
+     * or all compiled template files if one is not specified.
+     * This function is for advanced use only, not normally needed.
+     *
+     * @param string $tpl_file
+     * @param string $compile_id
+     * @param string $exp_time
+     *
+     * @return boolean results of {@link smarty_core_rm_auto()}
+     */
+    public function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp_time = null)
+    {
+        return $this->clearCompiledTemplate($tpl_file, $compile_id, $exp_time);
+    }
+
+    /**
+     * Checks whether requested template exists.
+     *
+     * @param string $tpl_file
+     *
+     * @return bool
+     * @throws \SmartyException
+     */
+    public function template_exists($tpl_file)
+    {
+        return $this->templateExists($tpl_file);
+    }
+
+    /**
+     * Returns an array containing template variables
+     *
+     * @param string $name
+     *
+     * @return array
+     */
+    public function get_template_vars($name = null)
+    {
+        return $this->getTemplateVars($name);
+    }
+
+    /**
+     * Returns an array containing config variables
+     *
+     * @param string $name
+     *
+     * @return array
+     */
+    public function get_config_vars($name = null)
+    {
+        return $this->getConfigVars($name);
+    }
+
+    /**
+     * load configuration values
+     *
+     * @param string $file
+     * @param string $section
+     * @param string $scope
+     */
+    public function config_load($file, $section = null, $scope = 'global')
+    {
+        $this->ConfigLoad($file, $section, $scope);
+    }
+
+    /**
+     * return a reference to a registered object
+     *
+     * @param string $name
+     *
+     * @return object
+     */
+    public function get_registered_object($name)
+    {
+        return $this->getRegisteredObject($name);
+    }
+
+    /**
+     * clear configuration values
+     *
+     * @param string $var
+     */
+    public function clear_config($var = null)
+    {
+        $this->clearConfig($var);
+    }
+
+    /**
+     * trigger Smarty error
+     *
+     * @param string  $error_msg
+     * @param integer $error_type
+     */
+    public function trigger_error($error_msg, $error_type = E_USER_WARNING)
+    {
+        trigger_error("Smarty error: $error_msg", $error_type);
+    }
+}

+ 16 - 0
resources/templates/engine/smarty/bootstrap.php

@@ -0,0 +1,16 @@
+<?php
+/**
+ * This file is part of the Smarty package.
+ *
+ * (c) Sebastian Bergmann <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+/**
+ * Load and register Smarty Autoloader
+ */
+if (!class_exists('Smarty_Autoloader')) {
+    include dirname(__FILE__) . '/Autoloader.php';
+}
+Smarty_Autoloader::register(true);

+ 154 - 127
resources/templates/engine/smarty/debug.tpl

@@ -1,133 +1,160 @@
 {capture name='_smarty_debug' assign=debug_output}
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-<head>
-    <title>Smarty Debug Console</title>
-<style type="text/css">
-{literal}
-body, h1, h2, td, th, p {
-    font-family: sans-serif;
-    font-weight: normal;
-    font-size: 0.9em;
-    margin: 1px;
-    padding: 0;
-}
-
-h1 {
-    margin: 0;
-    text-align: left;
-    padding: 2px;
-    background-color: #f0c040;
-    color:  black;
-    font-weight: bold;
-    font-size: 1.2em;
- }
-
-h2 {
-    background-color: #9B410E;
-    color: white;
-    text-align: left;
-    font-weight: bold;
-    padding: 2px;
-    border-top: 1px solid black;
-}
-
-body {
-    background: black;
-}
-
-p, table, div {
-    background: #f0ead8;
-}
-
-p {
-    margin: 0;
-    font-style: italic;
-    text-align: center;
-}
-
-table {
-    width: 100%;
-}
-
-th, td {
-    font-family: monospace;
-    vertical-align: top;
-    text-align: left;
-    width: 50%;
-}
-
-td {
-    color: green;
-}
-
-.odd {
-    background-color: #eeeeee;
-}
-
-.even {
-    background-color: #fafafa;
-}
-
-.exectime {
-    font-size: 0.8em;
-    font-style: italic;
-}
-
-#table_assigned_vars th {
-    color: blue;
-}
-
-#table_config_vars th {
-    color: maroon;
-}
-{/literal}
-</style>
-</head>
-<body>
-
-<h1>Smarty Debug Console  -  {if isset($template_name)}{$template_name|debug_print_var nofilter}{else}Total Time {$execution_time|string_format:"%.5f"}{/if}</h1>
-
-{if !empty($template_data)}
-<h2>included templates &amp; config files (load time in seconds)</h2>
-
-<div>
-{foreach $template_data as $template}
-  <font color=brown>{$template.name}</font>
-  <span class="exectime">
-   (compile {$template['compile_time']|string_format:"%.5f"}) (render {$template['render_time']|string_format:"%.5f"}) (cache {$template['cache_time']|string_format:"%.5f"})
-  </span>
-  <br>
-{/foreach}
-</div>
-{/if}
-
-<h2>assigned template variables</h2>
-
-<table id="table_assigned_vars">
-    {foreach $assigned_vars as $vars}
-       <tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}">
-       <th>${$vars@key|escape:'html'}</th>
-       <td>{$vars|debug_print_var nofilter}</td></tr>
-    {/foreach}
-</table>
-
-<h2>assigned config file variables (outer template scope)</h2>
-
-<table id="table_config_vars">
-    {foreach $config_vars as $vars}
-       <tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}">
-       <th>{$vars@key|escape:'html'}</th>
-       <td>{$vars|debug_print_var nofilter}</td></tr>
-    {/foreach}
-
-</table>
-</body>
-</html>
+    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+    <head>
+        <title>Smarty Debug Console</title>
+        <style type="text/css">
+            {literal}
+            body, h1, h2, h3, td, th, p {
+                font-family: sans-serif;
+                font-weight: normal;
+                font-size: 0.9em;
+                margin: 1px;
+                padding: 0;
+            }
+
+            h1 {
+                margin: 0;
+                text-align: left;
+                padding: 2px;
+                background-color: #f0c040;
+                color: black;
+                font-weight: bold;
+                font-size: 1.2em;
+            }
+
+            h2 {
+                background-color: #9B410E;
+                color: white;
+                text-align: left;
+                font-weight: bold;
+                padding: 2px;
+                border-top: 1px solid black;
+            }
+            h3 {
+                text-align: left;
+                font-weight: bold;
+                color: black;
+                font-size: 0.7em;
+                padding: 2px;
+            }
+
+            body {
+                background: black;
+            }
+
+            p, table, div {
+                background: #f0ead8;
+            }
+
+            p {
+                margin: 0;
+                font-style: italic;
+                text-align: center;
+            }
+
+            table {
+                width: 100%;
+            }
+
+            th, td {
+                font-family: monospace;
+                vertical-align: top;
+                text-align: left;
+            }
+
+            td {
+                color: green;
+            }
+
+            .odd {
+                background-color: #eeeeee;
+            }
+
+            .even {
+                background-color: #fafafa;
+            }
+
+            .exectime {
+                font-size: 0.8em;
+                font-style: italic;
+            }
+
+            #bold div {
+                color: black;
+                font-weight: bold;
+            }
+            #blue h3 {
+                color: blue;
+            }
+            #normal div {
+                color: black;
+                font-weight: normal;
+            }
+            #table_assigned_vars th {
+                color: blue;
+                font-weight: bold;
+            }
+
+            #table_config_vars th {
+                color: maroon;
+            }
+
+            {/literal}
+        </style>
+    </head>
+    <body>
+
+    <h1>Smarty {Smarty::SMARTY_VERSION} Debug Console
+        -  {if isset($template_name)}{$template_name|debug_print_var nofilter} {/if}{if !empty($template_data)}Total Time {$execution_time|string_format:"%.5f"}{/if}</h1>
+
+    {if !empty($template_data)}
+        <h2>included templates &amp; config files (load time in seconds)</h2>
+        <div>
+            {foreach $template_data as $template}
+                <font color=brown>{$template.name}</font>
+                <br />&nbsp;&nbsp;<span class="exectime">
+                (compile {$template['compile_time']|string_format:"%.5f"}) (render {$template['render_time']|string_format:"%.5f"}) (cache {$template['cache_time']|string_format:"%.5f"})
+                 </span>
+                <br />
+            {/foreach}
+        </div>
+    {/if}
+
+    <h2>assigned template variables</h2>
+
+    <table id="table_assigned_vars">
+        {foreach $assigned_vars as $vars}
+            <tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}">
+                <td><h3><font color=blue>${$vars@key}</font></h3>
+                    {if isset($vars['nocache'])}<b>Nocache</b><br />{/if}
+                    {if isset($vars['scope'])}<b>Origin:</b> {$vars['scope']|debug_print_var nofilter}{/if}
+                </td>
+                <td><h3>Value</h3>{$vars['value']|debug_print_var:10:80 nofilter}</td>
+                <td>{if isset($vars['attributes'])}<h3>Attributes</h3>{$vars['attributes']|debug_print_var nofilter} {/if}</td>
+         {/foreach}
+    </table>
+
+    <h2>assigned config file variables</h2>
+
+    <table id="table_config_vars">
+        {foreach $config_vars as $vars}
+            <tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}">
+                <td><h3><font color=blue>#{$vars@key}#</font></h3>
+                    {if isset($vars['scope'])}<b>Origin:</b> {$vars['scope']|debug_print_var nofilter}{/if}
+                </td>
+                <td>{$vars['value']|debug_print_var:10:80 nofilter}</td>
+            </tr>
+        {/foreach}
+
+    </table>
+    </body>
+    </html>
 {/capture}
 <script type="text/javascript">
-{$id = $template_name|default:''|md5}
-    _smarty_console = window.open("","console{$id}","width=680,height=600,resizable,scrollbars=yes");
+    {$id = '__Smarty__'}
+    {if $display_mode}{$id = "$offset$template_name"|md5}{/if}
+    _smarty_console = window.open("", "console{$id}", "width=1024,height=600,left={$offset},top={$offset},resizable,scrollbars=yes");
     _smarty_console.document.write("{$debug_output|escape:'javascript' nofilter}");
     _smarty_console.document.close();
 </script>

+ 39 - 28
resources/templates/engine/smarty/plugins/block.textformat.php

@@ -2,42 +2,51 @@
 /**
  * Smarty plugin to format text blocks
  *
- * @package Smarty
+ * @package    Smarty
  * @subpackage PluginsBlock
  */
-
 /**
  * Smarty {textformat}{/textformat} block plugin
- *
- * Type:     block function<br>
- * Name:     textformat<br>
+ * Type:     block function
+ * Name:     textformat
  * Purpose:  format text a certain way with preset styles
- *           or custom wrap/indent settings<br>
+ *           or custom wrap/indent settings
  * Params:
- * <pre>
+ *
  * - style         - string (email)
  * - indent        - integer (0)
  * - wrap          - integer (80)
  * - wrap_char     - string ("\n")
  * - indent_char   - string (" ")
  * - wrap_boundary - boolean (true)
- * </pre>
  *
- * @link http://www.smarty.net/manual/en/language.function.textformat.php {textformat}
- *       (Smarty online manual)
+ * @link   http://www.smarty.net/manual/en/language.function.textformat.php {textformat}
+ *         (Smarty online manual)
+ *
  * @param array                    $params   parameters
  * @param string                   $content  contents of the block
  * @param Smarty_Internal_Template $template template object
  * @param boolean                  &$repeat  repeat flag
+ *
  * @return string content re-formatted
  * @author Monte Ohrt <monte at ohrt dot com>
+ * @throws \SmartyException
  */
-function smarty_block_textformat($params, $content, $template, &$repeat)
+function smarty_block_textformat($params, $content, Smarty_Internal_Template $template, &$repeat)
 {
     if (is_null($content)) {
         return;
     }
-
+    if (Smarty::$_MBSTRING) {
+        $template->_checkPlugins(
+            array(
+                array(
+                    'function' => 'smarty_modifier_mb_wordwrap',
+                    'file'     => SMARTY_PLUGINS_DIR . 'modifier.mb_wordwrap.php'
+                )
+            )
+        );
+    }
     $style = null;
     $indent = 0;
     $indent_first = 0;
@@ -46,52 +55,55 @@ function smarty_block_textformat($params, $content, $template, &$repeat)
     $wrap_char = "\n";
     $wrap_cut = false;
     $assign = null;
-
     foreach ($params as $_key => $_val) {
         switch ($_key) {
             case 'style':
             case 'indent_char':
             case 'wrap_char':
             case 'assign':
-                $$_key = (string) $_val;
+                $$_key = (string)$_val;
                 break;
-
             case 'indent':
             case 'indent_first':
             case 'wrap':
-                $$_key = (int) $_val;
+                $$_key = (int)$_val;
                 break;
-
             case 'wrap_cut':
-                $$_key = (bool) $_val;
+                $$_key = (bool)$_val;
                 break;
-
             default:
-                trigger_error("textformat: unknown attribute '$_key'");
+                trigger_error("textformat: unknown attribute '{$_key}'");
         }
     }
-
-    if ($style == 'email') {
+    if ($style === 'email') {
         $wrap = 72;
     }
     // split into paragraphs
     $_paragraphs = preg_split('![\r\n]{2}!', $content);
-    $_output = '';
-
     foreach ($_paragraphs as &$_paragraph) {
         if (!$_paragraph) {
             continue;
         }
         // convert mult. spaces & special chars to single space
-        $_paragraph = preg_replace(array('!\s+!' . Smarty::$_UTF8_MODIFIER, '!(^\s+)|(\s+$)!' . Smarty::$_UTF8_MODIFIER), array(' ', ''), $_paragraph);
+        $_paragraph =
+            preg_replace(
+                array(
+                    '!\s+!' . Smarty::$_UTF8_MODIFIER,
+                    '!(^\s+)|(\s+$)!' . Smarty::$_UTF8_MODIFIER
+                ),
+                array(
+                    ' ',
+                    ''
+                ),
+                $_paragraph
+            );
         // indent first line
         if ($indent_first > 0) {
             $_paragraph = str_repeat($indent_char, $indent_first) . $_paragraph;
         }
         // wordwrap sentences
         if (Smarty::$_MBSTRING) {
-            require_once(SMARTY_PLUGINS_DIR . 'shared.mb_wordwrap.php');
-            $_paragraph = smarty_mb_wordwrap($_paragraph, $wrap - $indent, $wrap_char, $wrap_cut);
+            $_paragraph = smarty_modifier_mb_wordwrap($_paragraph, $wrap - $indent, $wrap_char, $wrap_cut);
         } else {
             $_paragraph = wordwrap($_paragraph, $wrap - $indent, $wrap_char, $wrap_cut);
         }
@@ -101,7 +113,6 @@ function smarty_block_textformat($params, $content, $template, &$repeat)
         }
     }
     $_output = implode($wrap_char . $wrap_char, $_paragraphs);
-
     if ($assign) {
         $template->assign($assign, $_output);
     } else {

+ 31 - 45
resources/templates/engine/smarty/plugins/function.counter.php

@@ -1,76 +1,62 @@
 <?php
 /**
  * Smarty plugin
- * @package Smarty
+ *
+ * @package    Smarty
  * @subpackage PluginsFunction
  */
-
 /**
  * Smarty {counter} function plugin
- *
- * Type:     function<br>
- * Name:     counter<br>
+ * Type:     function
+ * Name:     counter
  * Purpose:  print out a counter value
  *
  * @author Monte Ohrt <monte at ohrt dot com>
- * @link http://www.smarty.net/manual/en/language.function.counter.php {counter}
- *       (Smarty online manual)
+ * @link   http://www.smarty.net/manual/en/language.function.counter.php {counter}
+ *         (Smarty online manual)
+ *
  * @param array                    $params   parameters
  * @param Smarty_Internal_Template $template template object
+ *
  * @return string|null
  */
 function smarty_function_counter($params, $template)
 {
     static $counters = array();
-
-    $name = (isset($params['name'])) ? $params['name'] : 'default';
-    if (!isset($counters[$name])) {
-        $counters[$name] = array(
-            'start'=>1,
-            'skip'=>1,
-            'direction'=>'up',
-            'count'=>1
-            );
+    $name = (isset($params[ 'name' ])) ? $params[ 'name' ] : 'default';
+    if (!isset($counters[ $name ])) {
+        $counters[ $name ] = array('start' => 1, 'skip' => 1, 'direction' => 'up', 'count' => 1);
     }
-    $counter =& $counters[$name];
-
-    if (isset($params['start'])) {
-        $counter['start'] = $counter['count'] = (int) $params['start'];
+    $counter =& $counters[ $name ];
+    if (isset($params[ 'start' ])) {
+        $counter[ 'start' ] = $counter[ 'count' ] = (int)$params[ 'start' ];
     }
-
-    if (!empty($params['assign'])) {
-        $counter['assign'] = $params['assign'];
+    if (!empty($params[ 'assign' ])) {
+        $counter[ 'assign' ] = $params[ 'assign' ];
     }
-
-    if (isset($counter['assign'])) {
-        $template->assign($counter['assign'], $counter['count']);
+    if (isset($counter[ 'assign' ])) {
+        $template->assign($counter[ 'assign' ], $counter[ 'count' ]);
     }
-
-    if (isset($params['print'])) {
-        $print = (bool) $params['print'];
+    if (isset($params[ 'print' ])) {
+        $print = (bool)$params[ 'print' ];
     } else {
-        $print = empty($counter['assign']);
+        $print = empty($counter[ 'assign' ]);
     }
-
     if ($print) {
-        $retval = $counter['count'];
+        $retval = $counter[ 'count' ];
     } else {
         $retval = null;
     }
-
-    if (isset($params['skip'])) {
-        $counter['skip'] = $params['skip'];
+    if (isset($params[ 'skip' ])) {
+        $counter[ 'skip' ] = $params[ 'skip' ];
+    }
+    if (isset($params[ 'direction' ])) {
+        $counter[ 'direction' ] = $params[ 'direction' ];
     }
-
-    if (isset($params['direction'])) {
-        $counter['direction'] = $params['direction'];
+    if ($counter[ 'direction' ] === 'down') {
+        $counter[ 'count' ] -= $counter[ 'skip' ];
+    } else {
+        $counter[ 'count' ] += $counter[ 'skip' ];
     }
-
-    if ($counter['direction'] == "down")
-        $counter['count'] -= $counter['skip'];
-    else
-        $counter['count'] += $counter['skip'];
-
     return $retval;
-
 }

+ 43 - 56
resources/templates/engine/smarty/plugins/function.cycle.php

@@ -2,19 +2,17 @@
 /**
  * Smarty plugin
  *
- * @package Smarty
+ * @package    Smarty
  * @subpackage PluginsFunction
  */
-
 /**
  * Smarty {cycle} function plugin
- *
- * Type:     function<br>
- * Name:     cycle<br>
- * Date:     May 3, 2002<br>
- * Purpose:  cycle through given values<br>
+ * Type:     function
+ * Name:     cycle
+ * Date:     May 3, 2002
+ * Purpose:  cycle through given values
  * Params:
- * <pre>
+ *
  * - name      - name of cycle (optional)
  * - values    - comma separated list of values to cycle, or an array of values to cycle
  *               (this can be left out for subsequent calls)
@@ -23,83 +21,72 @@
  * - advance   - boolean - whether or not to advance the cycle
  * - delimiter - the value delimiter, default is ","
  * - assign    - boolean, assigns to template var instead of printed.
- * </pre>
- * Examples:<br>
- * <pre>
+ *
+ * Examples:
+ *
  * {cycle values="#eeeeee,#d0d0d0d"}
  * {cycle name=row values="one,two,three" reset=true}
  * {cycle name=row}
- * </pre>
  *
- * @link http://www.smarty.net/manual/en/language.function.cycle.php {cycle}
- *       (Smarty online manual)
- * @author Monte Ohrt <monte at ohrt dot com>
- * @author credit to Mark Priatel <[email protected]>
- * @author credit to Gerard <[email protected]>
- * @author credit to Jason Sweat <[email protected]>
- * @version  1.3
+ * @link    http://www.smarty.net/manual/en/language.function.cycle.php {cycle}
+ *           (Smarty online manual)
+ * @author  Monte Ohrt <monte at ohrt dot com>
+ * @author  credit to Mark Priatel <[email protected]>
+ * @author  credit to Gerard <[email protected]>
+ * @author  credit to Jason Sweat <[email protected]>
+ * @version 1.3
+ *
  * @param array                    $params   parameters
  * @param Smarty_Internal_Template $template template object
+ *
  * @return string|null
  */
-
 function smarty_function_cycle($params, $template)
 {
     static $cycle_vars;
-
-    $name = (empty($params['name'])) ? 'default' : $params['name'];
-    $print = (isset($params['print'])) ? (bool) $params['print'] : true;
-    $advance = (isset($params['advance'])) ? (bool) $params['advance'] : true;
-    $reset = (isset($params['reset'])) ? (bool) $params['reset'] : false;
-
-    if (!isset($params['values'])) {
-        if (!isset($cycle_vars[$name]['values'])) {
-            trigger_error("cycle: missing 'values' parameter");
-
+    $name = (empty($params[ 'name' ])) ? 'default' : $params[ 'name' ];
+    $print = (isset($params[ 'print' ])) ? (bool)$params[ 'print' ] : true;
+    $advance = (isset($params[ 'advance' ])) ? (bool)$params[ 'advance' ] : true;
+    $reset = (isset($params[ 'reset' ])) ? (bool)$params[ 'reset' ] : false;
+    if (!isset($params[ 'values' ])) {
+        if (!isset($cycle_vars[ $name ][ 'values' ])) {
+            trigger_error('cycle: missing \'values\' parameter');
             return;
         }
     } else {
-        if(isset($cycle_vars[$name]['values'])
-            && $cycle_vars[$name]['values'] != $params['values'] ) {
-            $cycle_vars[$name]['index'] = 0;
+        if (isset($cycle_vars[ $name ][ 'values' ]) && $cycle_vars[ $name ][ 'values' ] !== $params[ 'values' ]) {
+            $cycle_vars[ $name ][ 'index' ] = 0;
         }
-        $cycle_vars[$name]['values'] = $params['values'];
+        $cycle_vars[ $name ][ 'values' ] = $params[ 'values' ];
     }
-
-    if (isset($params['delimiter'])) {
-        $cycle_vars[$name]['delimiter'] = $params['delimiter'];
-    } elseif (!isset($cycle_vars[$name]['delimiter'])) {
-        $cycle_vars[$name]['delimiter'] = ',';
+    if (isset($params[ 'delimiter' ])) {
+        $cycle_vars[ $name ][ 'delimiter' ] = $params[ 'delimiter' ];
+    } elseif (!isset($cycle_vars[ $name ][ 'delimiter' ])) {
+        $cycle_vars[ $name ][ 'delimiter' ] = ',';
     }
-
-    if (is_array($cycle_vars[$name]['values'])) {
-        $cycle_array = $cycle_vars[$name]['values'];
+    if (is_array($cycle_vars[ $name ][ 'values' ])) {
+        $cycle_array = $cycle_vars[ $name ][ 'values' ];
     } else {
-        $cycle_array = explode($cycle_vars[$name]['delimiter'],$cycle_vars[$name]['values']);
+        $cycle_array = explode($cycle_vars[ $name ][ 'delimiter' ], $cycle_vars[ $name ][ 'values' ]);
     }
-
-    if (!isset($cycle_vars[$name]['index']) || $reset ) {
-        $cycle_vars[$name]['index'] = 0;
+    if (!isset($cycle_vars[ $name ][ 'index' ]) || $reset) {
+        $cycle_vars[ $name ][ 'index' ] = 0;
     }
-
-    if (isset($params['assign'])) {
+    if (isset($params[ 'assign' ])) {
         $print = false;
-        $template->assign($params['assign'], $cycle_array[$cycle_vars[$name]['index']]);
+        $template->assign($params[ 'assign' ], $cycle_array[ $cycle_vars[ $name ][ 'index' ] ]);
     }
-
     if ($print) {
-        $retval = $cycle_array[$cycle_vars[$name]['index']];
+        $retval = $cycle_array[ $cycle_vars[ $name ][ 'index' ] ];
     } else {
         $retval = null;
     }
-
     if ($advance) {
-        if ( $cycle_vars[$name]['index'] >= count($cycle_array) -1 ) {
-            $cycle_vars[$name]['index'] = 0;
+        if ($cycle_vars[ $name ][ 'index' ] >= count($cycle_array) - 1) {
+            $cycle_vars[ $name ][ 'index' ] = 0;
         } else {
-            $cycle_vars[$name]['index']++;
+            $cycle_vars[ $name ][ 'index' ]++;
         }
     }
-
     return $retval;
 }

+ 65 - 80
resources/templates/engine/smarty/plugins/function.fetch.php

@@ -2,166 +2,156 @@
 /**
  * Smarty plugin
  *
- * @package Smarty
+ * @package    Smarty
  * @subpackage PluginsFunction
  */
-
 /**
  * Smarty {fetch} plugin
- *
- * Type:     function<br>
- * Name:     fetch<br>
+ * Type:     function
+ * Name:     fetch
  * Purpose:  fetch file, web or ftp data and display results
  *
- * @link http://www.smarty.net/manual/en/language.function.fetch.php {fetch}
- *       (Smarty online manual)
+ * @link   http://www.smarty.net/manual/en/language.function.fetch.php {fetch}
+ *         (Smarty online manual)
  * @author Monte Ohrt <monte at ohrt dot com>
+ *
  * @param array                    $params   parameters
  * @param Smarty_Internal_Template $template template object
+ *
+ * @throws SmartyException
  * @return string|null if the assign parameter is passed, Smarty assigns the result to a template variable
  */
 function smarty_function_fetch($params, $template)
 {
-    if (empty($params['file'])) {
-        trigger_error("[plugin] fetch parameter 'file' cannot be empty",E_USER_NOTICE);
-
+    if (empty($params[ 'file' ])) {
+        trigger_error('[plugin] fetch parameter \'file\' cannot be empty', E_USER_NOTICE);
         return;
     }
-
     // strip file protocol
-    if (stripos($params['file'], 'file://') === 0) {
-        $params['file'] = substr($params['file'], 7);
+    if (stripos($params[ 'file' ], 'file://') === 0) {
+        $params[ 'file' ] = substr($params[ 'file' ], 7);
     }
-
-    $protocol = strpos($params['file'], '://');
+    $protocol = strpos($params[ 'file' ], '://');
     if ($protocol !== false) {
-        $protocol = strtolower(substr($params['file'], 0, $protocol));
+        $protocol = strtolower(substr($params[ 'file' ], 0, $protocol));
     }
-
     if (isset($template->smarty->security_policy)) {
         if ($protocol) {
             // remote resource (or php stream, …)
-            if (!$template->smarty->security_policy->isTrustedUri($params['file'])) {
+            if (!$template->smarty->security_policy->isTrustedUri($params[ 'file' ])) {
                 return;
             }
         } else {
             // local file
-            if (!$template->smarty->security_policy->isTrustedResourceDir($params['file'])) {
+            if (!$template->smarty->security_policy->isTrustedResourceDir($params[ 'file' ])) {
                 return;
             }
         }
     }
-
     $content = '';
-    if ($protocol == 'http') {
+    if ($protocol === 'http') {
         // http fetch
-        if ($uri_parts = parse_url($params['file'])) {
+        if ($uri_parts = parse_url($params[ 'file' ])) {
             // set defaults
-            $host = $server_name = $uri_parts['host'];
+            $host = $server_name = $uri_parts[ 'host' ];
             $timeout = 30;
-            $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*";
-            $agent = "Smarty Template Engine ". Smarty::SMARTY_VERSION;
-            $referer = "";
-            $uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/';
-            $uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : '';
+            $accept = 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*';
+            $agent = 'Smarty Template Engine ' . Smarty::SMARTY_VERSION;
+            $referer = '';
+            $uri = !empty($uri_parts[ 'path' ]) ? $uri_parts[ 'path' ] : '/';
+            $uri .= !empty($uri_parts[ 'query' ]) ? '?' . $uri_parts[ 'query' ] : '';
             $_is_proxy = false;
-            if (empty($uri_parts['port'])) {
+            if (empty($uri_parts[ 'port' ])) {
                 $port = 80;
             } else {
-                $port = $uri_parts['port'];
+                $port = $uri_parts[ 'port' ];
             }
-            if (!empty($uri_parts['user'])) {
-                $user = $uri_parts['user'];
+            if (!empty($uri_parts[ 'user' ])) {
+                $user = $uri_parts[ 'user' ];
             }
-            if (!empty($uri_parts['pass'])) {
-                $pass = $uri_parts['pass'];
+            if (!empty($uri_parts[ 'pass' ])) {
+                $pass = $uri_parts[ 'pass' ];
             }
             // loop through parameters, setup headers
             foreach ($params as $param_key => $param_value) {
                 switch ($param_key) {
-                    case "file":
-                    case "assign":
-                    case "assign_headers":
+                    case 'file':
+                    case 'assign':
+                    case 'assign_headers':
                         break;
-                    case "user":
+                    case 'user':
                         if (!empty($param_value)) {
                             $user = $param_value;
                         }
                         break;
-                    case "pass":
+                    case 'pass':
                         if (!empty($param_value)) {
                             $pass = $param_value;
                         }
                         break;
-                    case "accept":
+                    case 'accept':
                         if (!empty($param_value)) {
                             $accept = $param_value;
                         }
                         break;
-                    case "header":
+                    case 'header':
                         if (!empty($param_value)) {
-                            if (!preg_match('![\w\d-]+: .+!',$param_value)) {
-                                trigger_error("[plugin] invalid header format '".$param_value."'",E_USER_NOTICE);
-
+                            if (!preg_match('![\w\d-]+: .+!', $param_value)) {
+                                trigger_error("[plugin] invalid header format '{$param_value}'", E_USER_NOTICE);
                                 return;
                             } else {
                                 $extra_headers[] = $param_value;
                             }
                         }
                         break;
-                    case "proxy_host":
+                    case 'proxy_host':
                         if (!empty($param_value)) {
                             $proxy_host = $param_value;
                         }
                         break;
-                    case "proxy_port":
+                    case 'proxy_port':
                         if (!preg_match('!\D!', $param_value)) {
-                            $proxy_port = (int) $param_value;
+                            $proxy_port = (int)$param_value;
                         } else {
-                            trigger_error("[plugin] invalid value for attribute '".$param_key."'",E_USER_NOTICE);
-
+                            trigger_error("[plugin] invalid value for attribute '{$param_key }'", E_USER_NOTICE);
                             return;
                         }
                         break;
-                    case "agent":
+                    case 'agent':
                         if (!empty($param_value)) {
                             $agent = $param_value;
                         }
                         break;
-                    case "referer":
+                    case 'referer':
                         if (!empty($param_value)) {
                             $referer = $param_value;
                         }
                         break;
-                    case "timeout":
+                    case 'timeout':
                         if (!preg_match('!\D!', $param_value)) {
-                            $timeout = (int) $param_value;
+                            $timeout = (int)$param_value;
                         } else {
-                            trigger_error("[plugin] invalid value for attribute '".$param_key."'",E_USER_NOTICE);
-
+                            trigger_error("[plugin] invalid value for attribute '{$param_key}'", E_USER_NOTICE);
                             return;
                         }
                         break;
                     default:
-                        trigger_error("[plugin] unrecognized attribute '".$param_key."'",E_USER_NOTICE);
-
+                        trigger_error("[plugin] unrecognized attribute '{$param_key}'", E_USER_NOTICE);
                         return;
                 }
             }
             if (!empty($proxy_host) && !empty($proxy_port)) {
                 $_is_proxy = true;
-                $fp = fsockopen($proxy_host,$proxy_port,$errno,$errstr,$timeout);
+                $fp = fsockopen($proxy_host, $proxy_port, $errno, $errstr, $timeout);
             } else {
-                $fp = fsockopen($server_name,$port,$errno,$errstr,$timeout);
+                $fp = fsockopen($server_name, $port, $errno, $errstr, $timeout);
             }
-
             if (!$fp) {
-                trigger_error("[plugin] unable to fetch: $errstr ($errno)",E_USER_NOTICE);
-
+                trigger_error("[plugin] unable to fetch: $errstr ($errno)", E_USER_NOTICE);
                 return;
             } else {
                 if ($_is_proxy) {
-                    fputs($fp, 'GET ' . $params['file'] . " HTTP/1.0\r\n");
+                    fputs($fp, 'GET ' . $params[ 'file' ] . " HTTP/1.0\r\n");
                 } else {
                     fputs($fp, "GET $uri HTTP/1.0\r\n");
                 }
@@ -179,40 +169,35 @@ function smarty_function_fetch($params, $template)
                 }
                 if (isset($extra_headers) && is_array($extra_headers)) {
                     foreach ($extra_headers as $curr_header) {
-                        fputs($fp, $curr_header."\r\n");
+                        fputs($fp, $curr_header . "\r\n");
                     }
                 }
                 if (!empty($user) && !empty($pass)) {
-                    fputs($fp, "Authorization: BASIC ".base64_encode("$user:$pass")."\r\n");
+                    fputs($fp, 'Authorization: BASIC ' . base64_encode("$user:$pass") . "\r\n");
                 }
-
                 fputs($fp, "\r\n");
                 while (!feof($fp)) {
-                    $content .= fgets($fp,4096);
+                    $content .= fgets($fp, 4096);
                 }
                 fclose($fp);
-                $csplit = preg_split("!\r\n\r\n!",$content,2);
-
-                $content = $csplit[1];
-
-                if (!empty($params['assign_headers'])) {
-                    $template->assign($params['assign_headers'],preg_split("!\r\n!",$csplit[0]));
+                $csplit = preg_split("!\r\n\r\n!", $content, 2);
+                $content = $csplit[ 1 ];
+                if (!empty($params[ 'assign_headers' ])) {
+                    $template->assign($params[ 'assign_headers' ], preg_split("!\r\n!", $csplit[ 0 ]));
                 }
             }
         } else {
-            trigger_error("[plugin fetch] unable to parse URL, check syntax",E_USER_NOTICE);
-
+            trigger_error("[plugin fetch] unable to parse URL, check syntax", E_USER_NOTICE);
             return;
         }
     } else {
-        $content = @file_get_contents($params['file']);
+        $content = @file_get_contents($params[ 'file' ]);
         if ($content === false) {
-            throw new SmartyException("{fetch} cannot read resource '" . $params['file'] ."'");
+            throw new SmartyException("{fetch} cannot read resource '" . $params[ 'file' ] . "'");
         }
     }
-
-    if (!empty($params['assign'])) {
-        $template->assign($params['assign'], $content);
+    if (!empty($params[ 'assign' ])) {
+        $template->assign($params[ 'assign' ], $content);
     } else {
         return $content;
     }

+ 147 - 96
resources/templates/engine/smarty/plugins/function.html_checkboxes.php

@@ -2,26 +2,24 @@
 /**
  * Smarty plugin
  *
- * @package Smarty
+ * @package    Smarty
  * @subpackage PluginsFunction
  */
-
 /**
  * Smarty {html_checkboxes} function plugin
- *
- * File:       function.html_checkboxes.php<br>
- * Type:       function<br>
- * Name:       html_checkboxes<br>
- * Date:       24.Feb.2003<br>
- * Purpose:    Prints out a list of checkbox input types<br>
+ * File:       function.html_checkboxes.php
+ * Type:       function
+ * Name:       html_checkboxes
+ * Date:       24.Feb.2003
+ * Purpose:    Prints out a list of checkbox input types
  * Examples:
- * <pre>
+ *
  * {html_checkboxes values=$ids output=$names}
  * {html_checkboxes values=$ids name='box' separator='<br>' output=$names}
  * {html_checkboxes values=$ids checked=$checked separator='<br>' output=$names}
- * </pre>
+ *
  * Params:
- * <pre>
+ *
  * - name       (optional) - string default "checkbox"
  * - values     (required) - array
  * - options    (optional) - associative array
@@ -30,22 +28,30 @@
  * - output     (optional) - the output next to each checkbox
  * - assign     (optional) - assign the output as an array to this variable
  * - escape     (optional) - escape the content (not value), defaults to true
- * </pre>
  *
- * @link http://www.smarty.net/manual/en/language.function.html.checkboxes.php {html_checkboxes}
- *      (Smarty online manual)
- * @author     Christopher Kvarme <[email protected]>
- * @author credits to Monte Ohrt <monte at ohrt dot com>
- * @version    1.0
- * @param array $params parameters
- * @param object $template template object
+ * @link    http://www.smarty.net/manual/en/language.function.html.checkboxes.php {html_checkboxes}
+ *             (Smarty online manual)
+ * @author  Christopher Kvarme <[email protected]>
+ * @author  credits to Monte Ohrt <monte at ohrt dot com>
+ * @version 1.0
+ *
+ * @param array                    $params   parameters
+ * @param Smarty_Internal_Template $template template object
+ *
  * @return string
- * @uses smarty_function_escape_special_chars()
+ * @uses    smarty_function_escape_special_chars()
+ * @throws \SmartyException
  */
-function smarty_function_html_checkboxes($params, $template)
+function smarty_function_html_checkboxes($params, Smarty_Internal_Template $template)
 {
-    require_once(SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php');
-
+    $template->_checkPlugins(
+        array(
+            array(
+                'function' => 'smarty_function_escape_special_chars',
+                'file'     => SMARTY_PLUGINS_DIR . 'shared.escape_special_chars.php'
+            )
+        )
+    );
     $name = 'checkbox';
     $values = null;
     $options = null;
@@ -55,181 +61,226 @@ function smarty_function_html_checkboxes($params, $template)
     $labels = true;
     $label_ids = false;
     $output = null;
-
     $extra = '';
-
     foreach ($params as $_key => $_val) {
         switch ($_key) {
             case 'name':
             case 'separator':
-                $$_key = (string) $_val;
+                $$_key = (string)$_val;
                 break;
-
             case 'escape':
             case 'labels':
             case 'label_ids':
-                $$_key = (bool) $_val;
+                $$_key = (bool)$_val;
                 break;
-
             case 'options':
-                $$_key = (array) $_val;
+                $$_key = (array)$_val;
                 break;
-
             case 'values':
             case 'output':
-                $$_key = array_values((array) $_val);
+                $$_key = array_values((array)$_val);
                 break;
-
             case 'checked':
             case 'selected':
                 if (is_array($_val)) {
                     $selected = array();
                     foreach ($_val as $_sel) {
                         if (is_object($_sel)) {
-                            if (method_exists($_sel, "__toString")) {
-                                $_sel = smarty_function_escape_special_chars((string) $_sel->__toString());
+                            if (method_exists($_sel, '__toString')) {
+                                $_sel = smarty_function_escape_special_chars((string)$_sel->__toString());
                             } else {
-                                trigger_error("html_checkboxes: selected attribute contains an object of class '". get_class($_sel) ."' without __toString() method", E_USER_NOTICE);
+                                trigger_error(
+                                    'html_checkboxes: selected attribute contains an object of class \'' .
+                                    get_class($_sel) . '\' without __toString() method',
+                                    E_USER_NOTICE
+                                );
                                 continue;
                             }
                         } else {
-                            $_sel = smarty_function_escape_special_chars((string) $_sel);
+                            $_sel = smarty_function_escape_special_chars((string)$_sel);
                         }
-                        $selected[$_sel] = true;
+                        $selected[ $_sel ] = true;
                     }
                 } elseif (is_object($_val)) {
-                    if (method_exists($_val, "__toString")) {
-                        $selected = smarty_function_escape_special_chars((string) $_val->__toString());
+                    if (method_exists($_val, '__toString')) {
+                        $selected = smarty_function_escape_special_chars((string)$_val->__toString());
                     } else {
-                        trigger_error("html_checkboxes: selected attribute is an object of class '". get_class($_val) ."' without __toString() method", E_USER_NOTICE);
+                        trigger_error(
+                            'html_checkboxes: selected attribute is an object of class \'' . get_class($_val) .
+                            '\' without __toString() method',
+                            E_USER_NOTICE
+                        );
                     }
                 } else {
-                    $selected = smarty_function_escape_special_chars((string) $_val);
+                    $selected = smarty_function_escape_special_chars((string)$_val);
                 }
                 break;
-
             case 'checkboxes':
-                trigger_error('html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', E_USER_WARNING);
-                $options = (array) $_val;
+                trigger_error(
+                    'html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead',
+                    E_USER_WARNING
+                );
+                $options = (array)$_val;
                 break;
-
             case 'assign':
                 break;
-
-            case 'strict': break;
-
+            case 'strict':
+                break;
             case 'disabled':
             case 'readonly':
-                if (!empty($params['strict'])) {
+                if (!empty($params[ 'strict' ])) {
                     if (!is_scalar($_val)) {
-                        trigger_error("html_options: $_key attribute must be a scalar, only boolean true or string '$_key' will actually add the attribute", E_USER_NOTICE);
+                        trigger_error(
+                            "html_options: {$_key} attribute must be a scalar, only boolean true or string '{$_key}' will actually add the attribute",
+                            E_USER_NOTICE
+                        );
                     }
-
                     if ($_val === true || $_val === $_key) {
                         $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_key) . '"';
                     }
-
                     break;
                 }
-                // omit break; to fall through!
-
+            // omit break; to fall through!
+            // no break
             default:
                 if (!is_array($_val)) {
-                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+                    $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"';
                 } else {
-                    trigger_error("html_checkboxes: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                    trigger_error("html_checkboxes: extra attribute '{$_key}' cannot be an array", E_USER_NOTICE);
                 }
                 break;
         }
     }
-
-    if (!isset($options) && !isset($values))
-        return ''; /* raise error here? */
-
+    if (!isset($options) && !isset($values)) {
+        return '';
+    } /* raise error here? */
     $_html_result = array();
-
     if (isset($options)) {
-        foreach ($options as $_key=>$_val) {
-            $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids, $escape);
+        foreach ($options as $_key => $_val) {
+            $_html_result[] =
+                smarty_function_html_checkboxes_output(
+                    $name,
+                    $_key,
+                    $_val,
+                    $selected,
+                    $extra,
+                    $separator,
+                    $labels,
+                    $label_ids,
+                    $escape
+                );
         }
     } else {
-        foreach ($values as $_i=>$_key) {
-            $_val = isset($output[$_i]) ? $output[$_i] : '';
-            $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids, $escape);
+        foreach ($values as $_i => $_key) {
+            $_val = isset($output[ $_i ]) ? $output[ $_i ] : '';
+            $_html_result[] =
+                smarty_function_html_checkboxes_output(
+                    $name,
+                    $_key,
+                    $_val,
+                    $selected,
+                    $extra,
+                    $separator,
+                    $labels,
+                    $label_ids,
+                    $escape
+                );
         }
     }
-
-    if (!empty($params['assign'])) {
-        $template->assign($params['assign'], $_html_result);
+    if (!empty($params[ 'assign' ])) {
+        $template->assign($params[ 'assign' ], $_html_result);
     } else {
         return implode("\n", $_html_result);
     }
-
 }
 
-function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels, $label_ids, $escape=true)
-{
+/**
+ * @param      $name
+ * @param      $value
+ * @param      $output
+ * @param      $selected
+ * @param      $extra
+ * @param      $separator
+ * @param      $labels
+ * @param      $label_ids
+ * @param bool $escape
+ *
+ * @return string
+ */
+function smarty_function_html_checkboxes_output(
+    $name,
+    $value,
+    $output,
+    $selected,
+    $extra,
+    $separator,
+    $labels,
+    $label_ids,
+    $escape = true
+) {
     $_output = '';
-
     if (is_object($value)) {
-        if (method_exists($value, "__toString")) {
-            $value = (string) $value->__toString();
+        if (method_exists($value, '__toString')) {
+            $value = (string)$value->__toString();
         } else {
-            trigger_error("html_options: value is an object of class '". get_class($value) ."' without __toString() method", E_USER_NOTICE);
-
+            trigger_error(
+                'html_options: value is an object of class \'' . get_class($value) .
+                '\' without __toString() method',
+                E_USER_NOTICE
+            );
             return '';
         }
     } else {
-        $value = (string) $value;
+        $value = (string)$value;
     }
-
     if (is_object($output)) {
-        if (method_exists($output, "__toString")) {
-            $output = (string) $output->__toString();
+        if (method_exists($output, '__toString')) {
+            $output = (string)$output->__toString();
         } else {
-            trigger_error("html_options: output is an object of class '". get_class($output) ."' without __toString() method", E_USER_NOTICE);
-
+            trigger_error(
+                'html_options: output is an object of class \'' . get_class($output) .
+                '\' without __toString() method',
+                E_USER_NOTICE
+            );
             return '';
         }
     } else {
-        $output = (string) $output;
+        $output = (string)$output;
     }
-
     if ($labels) {
         if ($label_ids) {
-            $_id = smarty_function_escape_special_chars(preg_replace('![^\w\-\.]!' . Smarty::$_UTF8_MODIFIER, '_', $name . '_' . $value));
+            $_id = smarty_function_escape_special_chars(
+                preg_replace(
+                    '![^\w\-\.]!' . Smarty::$_UTF8_MODIFIER,
+                    '_',
+                    $name . '_' . $value
+                )
+            );
             $_output .= '<label for="' . $_id . '">';
         } else {
             $_output .= '<label>';
         }
     }
-
     $name = smarty_function_escape_special_chars($name);
     $value = smarty_function_escape_special_chars($value);
     if ($escape) {
         $output = smarty_function_escape_special_chars($output);
     }
-
     $_output .= '<input type="checkbox" name="' . $name . '[]" value="' . $value . '"';
-
     if ($labels && $label_ids) {
         $_output .= ' id="' . $_id . '"';
     }
-
     if (is_array($selected)) {
-        if (isset($selected[$value])) {
+        if (isset($selected[ $value ])) {
             $_output .= ' checked="checked"';
         }
     } elseif ($value === $selected) {
         $_output .= ' checked="checked"';
     }
-
     $_output .= $extra . ' />' . $output;
     if ($labels) {
         $_output .= '</label>';
     }
-
-    $_output .=  $separator;
-
+    $_output .= $separator;
     return $_output;
 }

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно