2 /************************************************************************
3 * Mailer v0.2.1-FINAL Start: 06/30/2003 *
4 * =================== Last change: 11/27/2004 *
6 * -------------------------------------------------------------------- *
7 * File : admins_functions.php *
8 * -------------------------------------------------------------------- *
9 * Short description : Functions for the admins extension *
10 * -------------------------------------------------------------------- *
11 * Kurzbeschreibung : Funktionen fuer die admins-Erweiterung *
12 * -------------------------------------------------------------------- *
15 * $Tag:: 0.2.1-FINAL $ *
17 * -------------------------------------------------------------------- *
18 * Copyright (c) 2003 - 2009 by Roland Haeder *
19 * Copyright (c) 2009 - 2011 by Mailer Developer Team *
20 * For more information visit: http://www.mxchange.org *
22 * This program is free software; you can redistribute it and/or modify *
23 * it under the terms of the GNU General Public License as published by *
24 * the Free Software Foundation; either version 2 of the License, or *
25 * (at your option) any later version. *
27 * This program is distributed in the hope that it will be useful, *
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
30 * GNU General Public License for more details. *
32 * You should have received a copy of the GNU General Public License *
33 * along with this program; if not, write to the Free Software *
34 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, *
36 ************************************************************************/
38 // Some security stuff...
39 if (!defined('__SECURITY')) {
43 // Check ACL for menu combination
44 function adminsCheckAdminAcl ($action, $what) {
45 // If action is login or logout allow allways!
47 if (($action == 'login') || ($action == 'logout')) {
55 $adminId = getCurrentAdminId();
57 // Get admin's defult access right
58 $default = getAdminDefaultAcl($adminId);
61 // Check for parent menu:
62 // First get it's action value
63 $parent_action = getActionFromModuleWhat('admin', $what);
65 // Check with this function...
66 $parent = adminsCheckAdminAcl($parent_action, '');
68 // Anything else is true!
72 // Shall I test for a main or sub menu? (action or what?)
74 if ((isExtensionInstalledAndNewer('cache', '0.1.2')) && (isset($GLOBALS['cache_array']['admin_acls'])) && (count($GLOBALS['cache_array']['admin_acls']) > 0)) {
76 if ((!empty($action)) && (isset($GLOBALS['cache_array']['admin_acls']['action_menu'][$adminId])) & (in_array($action, $GLOBALS['cache_array']['admin_acls']['action_menu'][$adminId]))) {
78 $key = array_search($action, $GLOBALS['cache_array']['admin_acls']['action_menu'][$adminId]);
80 // Main menu line found
81 $aclMode = $GLOBALS['cache_array']['admin_acls']['access_mode'][$adminId][$key];
84 logDebugMessage(__FUNCTION__, __LINE__, 'action=' . $action . ',key=' . $key . ',acl_mode=' . $aclMode);
87 incrementStatsEntry('cache_hits');
88 } elseif ((!empty($what)) && (isset($GLOBALS['cache_array']['admin_acls']['what_menu'][$adminId])) && (in_array($what, $GLOBALS['cache_array']['admin_acls']['what_menu'][$adminId]))) {
90 $key = array_search($action, $GLOBALS['cache_array']['admin_acls']['what_menu'][$adminId]);
93 $aclMode = $GLOBALS['cache_array']['admin_acls']['access_mode'][$adminId][$key];
96 logDebugMessage(__FUNCTION__, __LINE__, 'what=' . $what . ',key=' . $key . ',acl_mode=' . $aclMode);
99 incrementStatsEntry('cache_hits');
101 } elseif (!isExtensionActive('cache')) {
102 // Old version, so load it from database
104 if (!empty($action)) {
106 $result = SQL_QUERY_ESC("SELECT `access_mode` FROM `{?_MYSQL_PREFIX?}_admins_acls` WHERE `admin_id`=%s AND `action_menu`='%s' LIMIT 1",
107 array(bigintval($adminId), $action), __FUNCTION__, __LINE__);
108 } elseif (!empty($what)) {
110 $result = SQL_QUERY_ESC("SELECT `access_mode` FROM `{?_MYSQL_PREFIX?}_admins_acls` WHERE `admin_id`=%s AND `what_menu`='%s' LIMIT 1",
111 array(bigintval($adminId), $what), __FUNCTION__, __LINE__);
114 // Is an entry found?
115 if (SQL_NUMROWS($result) == 1) {
117 list($aclMode) = SQL_FETCHROW($result);
121 SQL_FREERESULT($result);
124 // Check ACL and (maybe) allow
125 //* DEBUG: */ debugOutput('default='.$default.',acl_mode='.$aclMode.',parent='.intval($parent));
126 if ((($default == 'allow') && ($aclMode != 'deny')) || (($default == 'deny') && ($aclMode == 'allow')) || ($parent === true) || (($default == '***') && ($aclMode == 'failed') && ($parent === false))) {
132 //* DEBUG: */ debugOutput(__FUNCTION__.'['.__LINE__.']:act='.$action.',wht='.$what.',default='.$default.',aclMode='.$aclMode);
136 // Create email link to admins's account
137 function generateAdminEmailLink ($email, $mod = 'admin') {
139 if (strpos($email, '@') !== false) {
141 $result = SQL_QUERY_ESC("SELECT `id`
143 `{?_MYSQL_PREFIX?}_admins`
147 array($email), __FUNCTION__, __LINE__);
149 // Is there an entry?
150 if (SQL_NUMROWS($result) == 1) {
152 list($adminId) = SQL_FETCHROW($result);
154 // Rewrite email address to contact link
155 $email = '{%url=modules.php?module=' . $mod . '&what=admins_contct&admin=' . bigintval($adminId) . '%}';
159 SQL_FREERESULT($result);
160 } elseif ((is_int($email)) && ($email > 0)) {
162 $email = '{%url=modules.php?module=' . $mod . '&what=admins_contct&admin=' . bigintval($email) . '%}';
165 // Return rewritten (?) email address
169 // Change a lot admin account
170 function adminsChangeAdminAccount ($postData, $element = '') {
173 foreach ($postData['login'] as $id => $login) {
175 $id = bigintval($id);
177 // When both passwords match update admin account
178 if ((!empty($element)) && (isset($postData[$element]))) {
180 SQL_QUERY_ESC("UPDATE `{?_MYSQL_PREFIX?}_admins` SET `%s`='%s' WHERE `id`=%s LIMIT 1",
181 array($element, $postData[$element][$id], $id), __FUNCTION__, __LINE__);
183 // Admin account saved
184 $message = '{--ADMIN_ACCOUNT_SAVED--}';
185 } elseif ((isset($postData['pass1'])) && (isset($postData['pass2']))) {
186 // Update only if both passwords match
187 if (($postData['pass1'][$id] == $postData['pass2'][$id])) {
188 // Save only when both passwords are the same (also when they are empty)
189 $add = ''; $cache_update = 1;
192 $hash = generateHash($postData['pass1'][$id]);
194 // Save password when set
195 if (!empty($postData['pass1'][$id])) $add = sprintf(", `password`='%s'", SQL_ESCAPE($hash));
198 $adminId = getCurrentAdminId();
199 $salt = substr(getAdminHash(getAdminLogin($adminId)), 0, -40);
201 // Rewrite cookie when it's own account
202 if ($adminId == $id) {
203 // Set timeout cookie
204 setAdminLast(time());
206 if ($adminId != getCurrentAdminId()) {
207 // Update login cookie
208 setAdminId($adminId);
210 // Update password cookie as well?
214 } elseif (generateHash($postData['pass1'][$id], $salt) != getAdminMd5()) {
215 // Update password cookie
220 // Get default ACL from admin to check if we can allow him to change the default ACL
221 $default = getAdminDefaultAcl(getCurrentAdminId());
223 // Update admin account
224 if ($default == 'allow') {
225 // Allow changing default ACL
226 SQL_QUERY_ESC("UPDATE
227 `{?_MYSQL_PREFIX?}_admins`
229 `login`='%s'" . $add . ",
238 $postData['email'][$id],
239 $postData['mode'][$id],
240 $postData['la_mode'][$id],
242 ), __FUNCTION__, __LINE__);
244 // Do not allow it here
245 SQL_QUERY_ESC("UPDATE
246 `{?_MYSQL_PREFIX?}_admins`
248 `login`='%s'" . $add . ",
256 $postData['email'][$id],
257 $postData['la_mode'][$id],
259 ), __FUNCTION__, __LINE__);
262 // Admin account saved
263 $message = '{--ADMIN_ACCOUNT_SAVED--}';
265 // Passwords did not match
266 $message = '{--ADMIN_ADMINS_ERROR_PASS_MISMATCH--}';
269 // Update whole array
270 $SQL = 'UPDATE `{?_MYSQL_PREFIX?}_admins` SET ';
271 foreach ($postData as $entry => $value) {
272 // Skip login/id entry
273 if (in_array($entry, array('login', 'id'))) continue;
275 // Do we have a non-string (e.g. number, NULL, NOW() or back-tick at the beginning?
276 if (is_null($value[$id])) {
278 $SQL .= '`' . $entry . '`=NULL, ';
279 } elseif ((bigintval($value[$id], true, false) === $value[$id]) || ($value[$id] == 'NOW()') || (substr($value[$id], 0, 1) == '`')) {
280 // No need for ticks (')
281 $SQL .= '`' . $entry . '`=' . $value[$id] . ', ';
283 // Strings need ticks (') around them
284 $SQL .= '`' . $entry . "`='" . SQL_ESCAPE($value[$id]) . "', ";
288 // Remove last 2 chars and finish query
289 $SQL = substr($SQL, 0, -2) . ' WHERE `id`=%s LIMIT 1';
292 SQL_QUERY_ESC($SQL, array(bigintval($id)), __FUNCTION__, __LINE__);
297 if (!empty($message)) {
298 displayMessage($message);
302 runFilterChain('post_form_submited', postRequestArray());
305 // Make admin accounts editable
306 function adminsEditAdminAccount ($postData) {
307 // "Resolve" current's admin access mode
308 $currMode = getAdminDefaultAcl(getCurrentAdminId());
310 // Begin the edit loop
312 foreach ($postData['sel'] as $id => $selected) {
314 $id = bigintval($id);
316 // Get the admin's data
317 $result = SQL_QUERY_ESC("SELECT `login`, `email`, `default_acl` AS mode, `la_mode` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
318 array($id), __FUNCTION__, __LINE__);
319 if ((SQL_NUMROWS($result) == 1) && ($selected == 1)) {
321 $content = SQL_FETCHARRAY($result);
322 SQL_FREERESULT($result);
324 // Prepare some more data for the template
325 $content['id'] = $id;
327 // Shall we allow changing default ACL?
328 if ($currMode == 'allow') {
330 $content['mode'] = generateOptionList('/ARRAY/', array('allow', 'deny'), array('{--ADMIN_ADMINS_ACCESS_MODE_ALLOW--}', '{--ADMIN_ADMINS_ACCESS_MODE_DENY--}'), $content['mode']);
333 $content['mode'] = ' ';
335 $content['la_mode'] = generateOptionList('/ARRAY/', array('global', 'OLD', 'NEW'), array('{--ADMIN_ADMINS_LA_MODE_GLOBAL--}', '{--ADMIN_ADMINS_LA_MODE_OLD--}', '{--ADMIN_ADMINS_LA_MODE_NEW--}'), $content['la_mode']);
337 // Load row template and switch color
338 $OUT .= loadTemplate('admin_edit_admins_row', true, $content);
343 loadTemplate('admin_edit_admins', false, $OUT);
346 // Delete given admin accounts
347 function adminsDeleteAdminAccount ($postData) {
348 // Check if this account is the last one which cannot be deleted...
349 if (countSumTotalData('', 'admins', 'id', '', true) > 1) {
352 foreach ($postData['sel'] as $id => $selected) {
354 $id = bigintval($id);
356 // Get the admin's data
357 $result = SQL_QUERY_ESC("SELECT `login`, `email`, `default_acl` AS `mode`, `la_mode` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
358 array($id), __FUNCTION__, __LINE__);
360 // Do we have an entry?
361 if (SQL_NUMROWS($result) == 1) {
362 // Entry found, so load data
363 $content = SQL_FETCHARRAY($result);
364 $content['mode'] = '{--ADMIN_ADMINS_ACCESS_MODE_' . strtoupper($content['mode']) . '--}';
365 $content['la_mode'] = '{--ADMIN_ADMINS_LA_MODE_' . strtoupper($content['la_mode']) . '--}';
367 // Prepare some more data
368 $content['id'] = $id;
370 // Load row template and switch color
371 $OUT .= loadTemplate('admin_delete_admins_row', true, $content);
375 SQL_FREERESULT($result);
379 loadTemplate('admin_delete_admins', false, $OUT);
381 // Cannot delete last account!
382 displayMessage('{--ADMIN_ADMINS_CANNOT_DELETE_LAST--}');
386 // Remove the given accounts
387 function adminsRemoveAdminAccount ($postData) {
390 foreach ($postData['sel'] as $id => $del) {
392 $id = bigintval($id);
394 // Delete only when it's not your own account!
395 if (($del == 1) && (getCurrentAdminId() != $id)) {
396 // Rewrite his tasks to all admins
397 SQL_QUERY_ESC("UPDATE `{?_MYSQL_PREFIX?}_task_system` SET `assigned_admin`=NULL WHERE `assigned_admin`=%s",
398 array($id), __FUNCTION__, __LINE__);
401 SQL_QUERY_ESC("DELETE LOW_PRIORITY FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
402 array($id), __FUNCTION__, __LINE__);
406 // Remove cache if cache system is activated
407 runFilterChain('post_form_deleted', postRequestArray());
410 // List all admin accounts
411 function adminsListAdminAccounts() {
412 // Select all admin accounts
413 $result = SQL_QUERY('SELECT `id`, `login`, `email`, `default_acl` AS mode, `la_mode` FROM `{?_MYSQL_PREFIX?}_admins` ORDER BY `login` ASC', __FUNCTION__, __LINE__);
415 while ($content = SQL_FETCHARRAY($result)) {
416 // Compile some variables
417 $content['mode'] = '{--ADMIN_ADMINS_ACCESS_MODE_' . strtoupper($content['mode']) . '--}';
418 $content['la_mode'] = '{--ADMIN_ADMINS_LA_MODE_' . strtoupper($content['la_mode']) . '--}';
420 // Load row template and switch color
421 $OUT .= loadTemplate('admin_list_admins_row', true, $content);
425 SQL_FREERESULT($result);
428 loadTemplate('admin_list_admins', false, $OUT);
431 // Sends out mail to all administrators
432 // IMPORTANT: Please use sendAdminNotification() instead of calling this function directly
433 function sendAdminsEmails ($subj, $template, $content, $userid) {
434 // Trim template name
435 $template = trim($template);
437 // Load email template
438 $message = loadEmailTemplate($template, $content, $userid);
440 // Check which admin shall receive this mail
441 $result = SQL_QUERY_ESC("SELECT `admin_id` FROM `{?_MYSQL_PREFIX?}_admins_mails` WHERE `mail_template`='%s' ORDER BY `admin_id` ASC",
442 array($template), __FUNCTION__, __LINE__);
443 if (SQL_HASZERONUMS($result)) {
444 // Create new entry (to all admins)
445 SQL_QUERY_ESC("INSERT INTO `{?_MYSQL_PREFIX?}_admins_mails` (`admin_id`, `mail_template`) VALUES (0, '%s')",
446 array($template), __FUNCTION__, __LINE__);
449 // @TODO This can be, somehow, rewritten
451 while ($content = SQL_FETCHARRAY($result)) {
452 $adminIds[] = $content['admin_id'];
456 SQL_FREERESULT($result);
461 // "implode" ids and query string
462 $adminId = implode(',', $adminIds);
463 if ($adminId == '-1') {
464 if (isExtensionActive('events')) {
465 // Add line to user events
466 EVENTS_ADD_LINE($subj, $message, $userid);
468 // Log error for debug
469 logDebugMessage(__FUNCTION__, __LINE__, sprintf("Extension 'events' missing: tpl=%s,subj=%s,userid=%s",
475 } elseif (($adminId == '0') || (empty($adminId))) {
476 // Select all email adresses
477 $result = SQL_QUERY('SELECT `email` FROM `{?_MYSQL_PREFIX?}_admins` ORDER BY `id` ASC',
478 __FUNCTION__, __LINE__);
480 // If Admin-Id is not "to-all" select
481 $result = SQL_QUERY_ESC("SELECT `email` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id` IN (%s) ORDER BY `id` ASC",
482 array($adminId), __FUNCTION__, __LINE__);
486 // Load email addresses and send away
487 while ($content = SQL_FETCHARRAY($result)) {
488 sendEmail($content['email'], $subj, $message);
492 SQL_FREERESULT($result);
495 // "Getter" for current admin's expert settings
496 function getAminsExpertSettings () {
497 // Default is has not the right
498 $data['expert_settings'] = 'N';
500 // Get current admin Id
501 $adminId = getCurrentAdminId();
503 // Lookup settings in cache
504 if (isset($GLOBALS['cache_array']['admin']['expert_settings'][$adminId])) {
506 $data['expert_settings'] = $GLOBALS['cache_array']['admin']['expert_settings'][$adminId];
509 incrementStatsEntry('cache_hits');
510 } elseif (!isExtensionInstalled('cache')) {
511 // Load from database
512 $result = SQL_QUERY_ESC("SELECT `expert_settings` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
513 array($adminId), __FUNCTION__, __LINE__);
516 if (SQL_NUMROWS($result) == 1) {
518 $data = SQL_FETCHARRAY($result);
521 $GLOBALS['cache_array']['admin']['expert_settings'][$adminId] = $data['expert_settings'];
525 SQL_FREERESULT($result);
529 return $data['expert_settings'];
532 // "Getter" for current admin's expert warning (if he wants to see them or not
533 function getAminsExpertWarning () {
534 // Default is has not the right
535 $data['expert_warning'] = 'N';
537 // Get current admin id
538 $adminId = getCurrentAdminId();
540 // Lookup warning in cache
541 if (isset($GLOBALS['cache_array']['admin']['expert_warning'][$adminId])) {
543 $data['expert_warning'] = $GLOBALS['cache_array']['admin']['expert_warning'][$adminId];
546 incrementStatsEntry('cache_hits');
547 } elseif (!isExtensionInstalled('cache')) {
548 // Load from database
549 $result = SQL_QUERY_ESC("SELECT `expert_warning` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
550 array($adminId), __FUNCTION__, __LINE__);
553 if (SQL_NUMROWS($result) == 1) {
555 $data = SQL_FETCHARRAY($result);
558 $GLOBALS['cache_array']['admin']['expert_warning'][$adminId] = $data['expert_warning'];
562 SQL_FREERESULT($result);
566 return $data['expert_warning'];
569 // Get login_failures number from administrator's login name
570 function getAdminLoginFailures ($adminId) {
571 // Admin login should not be empty
572 if (empty($adminId)) {
573 debug_report_bug(__FUNCTION__, __LINE__, 'adminId is empty.');
576 // By default no admin is found
577 $data['login_failures'] = -1;
580 if (isset($GLOBALS['cache_array']['admin']['login_failures'][$adminId])) {
581 // Use it if found to save SQL queries
582 $data['login_failures'] = $GLOBALS['cache_array']['admin']['login_failures'][$adminId];
585 incrementStatsEntry('cache_hits');
586 } elseif (!isExtensionActive('cache')) {
587 // Load from database
588 $result = SQL_QUERY_ESC("SELECT `login_failures` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
589 array($adminId), __FUNCTION__, __LINE__);
591 // Do we have an entry?
592 if (SQL_NUMROWS($result) == 1) {
594 $data = SQL_FETCHARRAY($result);
598 SQL_FREERESULT($result);
601 // Return the login_failures
602 return $data['login_failures'];
605 // Get last_failure number from administrator's login name
606 function getAdminLastFailure ($adminId) {
607 // Admin login should not be empty
608 if (empty($adminId)) {
609 debug_report_bug(__FUNCTION__, __LINE__, 'adminId is empty.');
612 // By default no admin is found
613 $data['last_failure'] = -1;
616 if (isset($GLOBALS['cache_array']['admin']['last_failure'][$adminId])) {
617 // Use it if found to save SQL queries
618 $data['last_failure'] = $GLOBALS['cache_array']['admin']['last_failure'][$adminId];
621 incrementStatsEntry('cache_hits');
622 } elseif (!isExtensionActive('cache')) {
623 // Load from database
624 $result = SQL_QUERY_ESC("SELECT UNIX_TIMESTAMP(`last_failure`) AS `last_failure` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
625 array($adminId), __FUNCTION__, __LINE__);
627 // Do we have an entry?
628 if (SQL_NUMROWS($result) == 1) {
630 $data = SQL_FETCHARRAY($result);
634 SQL_FREERESULT($result);
637 // Return the last_failure
638 return $data['last_failure'];
641 // ---------------------------------------------------------------------------
643 // ---------------------------------------------------------------------------
645 // Wrapper function to check wether expert setting warning is enabled
646 function isAdminsExpertWarningEnabled () {
647 return (getAminsExpertWarning() == 'Y');