X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=inc%2Fmodules%2Fadmin%2Fadmin-inc.php;h=886fd1d07d9333245c4bba42df3e5b90cf4bc367;hb=00283a82c807a00d66bd5811d41992bb3b059996;hp=1041fabe3ffcb4eac27e1d76a5c9c0efc3aec778;hpb=3c0c6ad28a250c08b3fe8b166c589d0d49441ad3;p=mailer.git
diff --git a/inc/modules/admin/admin-inc.php b/inc/modules/admin/admin-inc.php
index 1041fabe3f..886fd1d07d 100644
--- a/inc/modules/admin/admin-inc.php
+++ b/inc/modules/admin/admin-inc.php
@@ -14,10 +14,9 @@
* $Date:: $ *
* $Tag:: 0.2.1-FINAL $ *
* $Author:: $ *
- * Needs to be in all Files and every File needs "svn propset *
- * svn:keywords Date Revision" (autoprobset!) at least!!!!!! *
* -------------------------------------------------------------------- *
* Copyright (c) 2003 - 2009 by Roland Haeder *
+ * Copyright (c) 2009 - 2011 by Mailer Developer Team *
* For more information visit: http://www.mxchange.org *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -42,22 +41,22 @@ if (!defined('__SECURITY')) {
} // END - if
// Register an administrator account
-function addAdminAccount ($user, $md5, $email) {
+function addAdminAccount ($adminLogin, $passHash, $adminEmail) {
// Login does already exist
$ret = 'already';
// Lookup the admin
$result = SQL_QUERY_ESC("SELECT `id` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `login`='%s' LIMIT 1",
- array($user), __FUNCTION__, __LINE__);
+ array($adminLogin), __FUNCTION__, __LINE__);
// Is the entry there?
- if (SQL_NUMROWS($result) == '0') {
+ if (SQL_HASZERONUMS($result)) {
// Ok, let's create the admin login
- SQL_QUERY_ESC("INSERT INTO `{?_MYSQL_PREFIX?}_admins` (`login`, `password`, `email`) VALUES ('%s', '%s', '%s')",
+ SQL_QUERY_ESC("INSERT INTO `{?_MYSQL_PREFIX?}_admins` (`login`,`password`,`email`) VALUES ('%s', '%s', '%s')",
array(
- $user,
- $md5,
- $email
+ $adminLogin,
+ $passHash,
+ $adminEmail
), __FUNCTION__, __LINE__);
// All done
@@ -71,169 +70,80 @@ function addAdminAccount ($user, $md5, $email) {
return $ret;
}
-// Only be executed on login procedure!
-function ifAdminLoginDataIsValid ($admin, $password) {
- // By default no admin is found
+// This function will be executed when the admin is not logged in and has submitted his login data
+function ifAdminLoginDataIsValid ($adminLogin, $adminPassword) {
+ // First of all, no admin login is found, so the admin hash is null
$ret = '404';
+ $adminHash = NULL;
- // Get admin id
- $adminId = getAdminId($admin);
-
- // Init array with admin id by default
- $data = array('admin_id' => $adminId);
-
- // Is the cache valid?
- if (isAdminHashSet($admin)) {
- // Get password from cache
- $data['password'] = getAdminHash($admin);
- $ret = 'pass';
- incrementStatsEntry('cache_hits');
-
- // Include more admins data?
- if ((isExtensionInstalledAndNewer('admins', '0.7.2')) && (isset($GLOBALS['cache_array']['admin']['login_failures'][$adminId]))) {
- // Load them here
- $data['login_failures'] = $GLOBALS['cache_array']['admin']['login_failures'][$adminId];
- $data['last_failure'] = $GLOBALS['cache_array']['admin']['last_failure'][$adminId];
- } // END - if
- } elseif (!isExtensionActive('cache')) {
- // Add extra data via filter now
- $add = runFilterChain('sql_admin_extra_data');
-
- // Get password from DB
- $result = SQL_QUERY_ESC("SELECT `password`" . $add . " FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
- array($adminId), __FUNCTION__, __LINE__);
-
- // Entry found?
- if (SQL_NUMROWS($result) == 1) {
- // Login password found
- $ret = 'pass';
-
- // Fetch data
- $data = SQL_FETCHARRAY($result);
- } // END - if
-
- // Free result
- SQL_FREERESULT($result);
- }
+ // Get admin id from login
+ $adminId = getAdminId($adminLogin);
- //* DEBUG: */ outputHtml("*".$data['password'].'/'.md5($password).'/'.$ret."
");
- if ((isset($data['password'])) && (strlen($data['password']) == 32) && ($data['password'] == md5($password))) {
- // Generate new hash
- $data['password'] = generateHash($password);
-
- // Is the sql_patches not installed, than we cannot have a valid hashed password here!
- if (($ret == 'pass') && ((isExtensionInstalledAndOlder('sql_patches', '0.3.6')) || (!isExtensionInstalled('sql_patches')))) $ret = 'done';
- } elseif ((isExtensionInstalledAndOlder('sql_patches', '0.3.6')) || (!isExtensionInstalled('sql_patches'))) {
- // Old hashing way
- return $ret;
- } elseif (!isset($data['password'])) {
- // Password not found, so no valid login!
- return $ret;
- }
+ // Continue only with found admin ids
+ if ($adminId > 0) {
+ // Then we need to lookup the login name by getting the admin hash
+ $adminHash = getAdminHash($adminId);
- // Generate salt of password
- $salt = substr($data['password'], 0, -40);
-
- // Check if password is same
- //* DEBUG: */ outputHtml("*".$ret.','.$data['password'].','.$password.','.$salt."*
");
- if (($ret == 'pass') && ($data['password'] == generateHash($password, $salt)) && ((!empty($salt))) || ($data['password'] == $password)) {
- // Re-hash the plain passord with new random salt
- $data['password'] = generateHash($password);
-
- // Do we have 0.7.0 of admins or later?
- // Remmeber login failures if available
- if ((isExtensionInstalledAndNewer('admins', '0.7.2')) && (isset($data['login_failures']))) {
- // Store it in session
- setSession('mxchange_admin_failures', $data['login_failures']);
- setSession('mxchange_admin_last_fail', $data['last_failure']);
-
- // Update password and reset login failures
- SQL_QUERY_ESC("UPDATE `{?_MYSQL_PREFIX?}_admins` SET `password`='%s',`login_failures`=0,`last_failure`='0000-00-00 00:00:00' WHERE `id`=%s LIMIT 1",
- array($data['password'], $adminId), __FUNCTION__, __LINE__);
- } else {
- // Update password
- SQL_QUERY_ESC("UPDATE `{?_MYSQL_PREFIX?}_admins` SET `password`='%s' WHERE `id`=%s LIMIT 1",
- array($data['password'], $adminId), __FUNCTION__, __LINE__);
- }
+ // If this is fine, we can continue
+ if ($adminHash != '-1') {
+ // Get admin id and set it as current
+ setCurrentAdminId($adminId);
- // Rebuild cache
- rebuildCacheFile('admin', 'admin');
+ // Now, we need to encode the password in the same way the one is encoded in database
+ $testHash = generateHash($adminPassword, $adminHash);
- // Login has failed by default... ;-)
- $ret = 'failed1';
-
- // Password matches so login here
- if (doAdminLogin($admin, $data['password'])) {
- // All done now
- $ret = 'done';
- } // END - if
- } elseif ((empty($salt)) && ($ret == 'pass')) {
- // Something bad went wrong
- $ret = 'failed_salt';
- } elseif ($ret == 'done') {
- // Try to login here if we have the old hashing way (sql_patches not installed?)
- if (!doAdminLogin($admin, $data['password'])) {
- // Something went wrong
- $ret = 'failed2';
+ // If they both match, the login data is valid
+ if ($testHash == $adminHash) {
+ // All fine
+ $ret = 'done';
+ } else {
+ // Did not match!
+ $ret = 'password';
+ }
} // END - if
- }
-
- // Count login failure if admins extension version is 0.7.0+
- if (($ret == 'pass') && (getExtensionVersion('admins') >= '0.7.0')) {
- // Update counter
- SQL_QUERY_ESC("UPDATE `{?_MYSQL_PREFIX?}_admins` SET login_failures`=`login_failures`+1,`last_failure`=NOW() WHERE `id`=%s LIMIT 1",
- array($adminId), __FUNCTION__, __LINE__);
-
- // Rebuild cache
- rebuildCacheFile('admin', 'admin');
} // END - if
- // Return the result
- //* DEBUG: */ die('RETURN=' . $ret);
- return $ret;
-}
-
-// Try to login the admin by setting some session/cookie variables
-function doAdminLogin ($adminLogin, $passHash) {
- // Reset failure counter on matching admins version
- if ((isExtensionInstalledAndNewer('admins', '0.7.0')) && ((isExtensionOlder('sql_patches', '0.3.6')) || (!isExtensionInstalled('sql_patches')))) {
- // Reset counter on out-dated sql_patches version
- SQL_QUERY_ESC("UPDATE `{?_MYSQL_PREFIX?}_admins` SET `login_failures`=0, `last_failure`='0000-00-00 00:00:00' WHERE `login`='%s' LIMIT 1",
- array($adminLogin), __FUNCTION__, __LINE__);
+ // Prepare data array
+ $data = array(
+ 'id' => $adminId,
+ 'login' => $adminLogin,
+ 'plain_pass' => $adminPassword,
+ 'pass_hash' => $adminHash
+ );
- // Rebuild cache
- rebuildCacheFile('admin', 'admin');
- } // END - if
+ // Run a special filter
+ runFilterChain('do_admin_login_' . $ret, $data);
- // Now set all session variables and return the result
- return ((
- setSession('admin_md5', generatePassString($passHash))
- ) && (
- setSession('admin_login', $adminLogin)
- ) && (
- setSession('admin_last', time())
- ));
+ // Return status
+ return $ret;
}
// Only be executed on cookie checking
-function ifAdminCookiesAreValid ($admin, $password) {
- // By default no admin cookies are found
- $ret = '404';
- $pass = '';
+function ifAdminCookiesAreValid ($adminLogin, $passHash) {
+ // First of all, no admin login is found
+ $ret = '404';
- // Get hash
- $pass = getAdminHash($admin);
- if ($pass != '-1') $ret = 'pass';
+ // Then we need to lookup the login name by getting the admin hash
+ $adminHash = getAdminHash($adminLogin);
- //* DEBUG: */ outputHtml(__FUNCTION__."(".__LINE__."):".generatePassString($pass).'('.strlen($pass).")/".$password.'('.strlen($password).")
");
+ // If this is fine, we can continue
+ if ($adminHash != '-1') {
+ // Now, we need to encode the password in the same way the one is encoded in database
+ $testHash = encodeHashForCookie($adminHash);
+ //* DEBUG: */ debugOutput('adminLogin=' . $adminLogin . ',passHash='.$passHash.',adminHash='.$adminHash.',testHash='.$testHash);
- // Check if password matches
- if (($ret == 'pass') && ((generatePassString($pass) == $password) || ($pass == $password) || ((strlen($pass) == 32) && (md5($password) == $pass))) && (isAdmin())) {
- // Passwords matches!
- $ret = 'done';
+ // If they both match, the login data is valid
+ if ($testHash == $passHash) {
+ // All fine
+ $ret = 'done';
+ } else {
+ // Set status
+ $ret = 'password';
+ }
} // END - if
- // Return result
+ // Return status
+ //* DEBUG: */ debugOutput('ret='.$ret);
return $ret;
}
@@ -242,7 +152,7 @@ function doAdminAction () {
// Get default what
$what = getWhat();
- //* DEBUG: */ outputHtml(__LINE__."*".$what.'/'.getModule().'/'.getAction().'/'.getWhat()."*
");
+ //* DEBUG: */ debugOutput(__LINE__.'*'.$what.'/'.getModule().'/'.getAction().'/'.getWhat().'*');
// Remove any spaces from variable
if (empty($what)) {
@@ -254,18 +164,18 @@ function doAdminAction () {
}
// Get action value
- $action = getModeAction(getModule(), $what);
+ $action = getActionFromModuleWhat(getModule(), $what);
- // Define admin login name and id number
- $content['login'] = getSession('admin_login');
- $content['id'] = getCurrentAdminId();
-
- // Preload templates
+ // Load welcome template
if (isExtensionActive('admins')) {
- $content['welcome'] = loadTemplate('admin_welcome_admins', true, $content);
+ // @TODO This and the next getCurrentAdminId() call might be moved into the templates?
+ $content['welcome'] = loadTemplate('admin_welcome_admins', true, getCurrentAdminId());
} else {
- $content['welcome'] = loadTemplate('admin_welcome', true, $content);
+ $content['welcome'] = loadTemplate('admin_welcome', true, getCurrentAdminId());
}
+
+ // Load header, footer, render menu
+ $content['header'] = loadTemplate('admin_header' , true, $content);
$content['footer'] = loadTemplate('admin_footer' , true, $content);
$content['menu'] = addAdminMenu($action, $what, true);
@@ -306,14 +216,14 @@ LIMIT 1",
loadInclude($inc);
} elseif ($GLOBALS['acl_allow'] === false) {
// Access denied
- loadTemplate('admin_menu_failed', false, sprintf(getMessage('ADMIN_ACCESS_DENIED'), $what));
+ loadTemplate('admin_menu_failed', false, '{%message,ADMIN_ACCESS_DENIED=' . $what . '%}');
} else {
- // Include file not found! :-(
- loadTemplate('admin_menu_failed', false, sprintf(getMessage('ADMIN_ACTION_404'), $action));
+ // Include file not found :-(
+ loadTemplate('admin_menu_failed', false, '{%message,ADMIN_ACTION_404=' . $action . '%}');
}
} else {
- // Invalid action/what pair found!
- loadTemplate('admin_menu_failed', false, sprintf(getMessage('ADMIN_ACTION_INVALID'), $action . '/' . $what));
+ // Invalid action/what pair found
+ loadTemplate('admin_menu_failed', false, '{%message,ADMIN_ACTION_INVALID=' . $action . '/' . $what . '%}');
}
// Free memory
@@ -323,8 +233,22 @@ LIMIT 1",
loadTemplate('admin_main_footer', false, $content);
}
+// Checks wether current admin is allowed to access given action/what combination
+// (only one is allowed to be null!)
+function isAdminAllowedAccessMenu ($action, $what = NULL) {
+ // Do we have cache?
+ if (!isset($GLOBALS[__FUNCTION__][$action][$what])) {
+ // ACL is always 'allow' when no ext-admins is installed
+ // @TODO This can be rewritten into a filter
+ $GLOBALS[__FUNCTION__][$action][$what] = ((!isExtensionInstalledAndNewer('admins', '0.2.0')) || (isAdminsAllowedByAcl($action, $what)));
+ } // END - if
+
+ // Return the cached value
+ return $GLOBALS[__FUNCTION__][$action][$what];
+}
+
// Adds an admin menu
-function addAdminMenu ($action, $what, $return=false) {
+function addAdminMenu ($action, $what, $return = false) {
// Init variables
$SUB = false;
$OUT = '';
@@ -335,7 +259,7 @@ function addAdminMenu ($action, $what, $return=false) {
// Build main menu
$result_main = SQL_QUERY("SELECT
- `action`, `title`, `descr`
+ `action`,`title`,`descr`
FROM
`{?_MYSQL_PREFIX?}_admin_menu`
WHERE
@@ -345,61 +269,54 @@ ORDER BY
`id` DESC", __FUNCTION__, __LINE__);
// Do we have entries?
- if (SQL_NUMROWS($result_main) > 0) {
- $OUT = "
'.print_r($listType,true).',tableName
'.print_r($tableName,true).',columns=
'.print_r($columns,true).',filterFunctions=
'.print_r($filterFunctions,true).',extraValues=
'.print_r($extraValues,true).',idColumn=
'.print_r($idColumn,true).',userIdColumn=
'.print_r($userIdColumn,true).',rawUserId=
'.print_r($rawUserId,true).''); + foreach (postRequestParameter($idColumn[0]) as $id => $selected) { // Secure id number $id = bigintval($id); // Get result from a given column array and table name - $result = SQL_RESULT_FROM_ARRAY($table, $columns, $idColumn, $id, __FUNCTION__, __LINE__); + $result = SQL_RESULT_FROM_ARRAY($tableName[0], $columns, $idColumn[0], $id, __FUNCTION__, __LINE__); // Is there one entry? if (SQL_NUMROWS($result) == 1) { @@ -862,27 +831,36 @@ function adminListBuilder ($listType, $IDs, $table, $columns, $filterFunctions, $idx = array_search($key, $columns, true); //Â Do we have a userid? - if ($key == 'userid') { + //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',userIdColumn=' . $userIdColumn[0]); + if ($key == $userIdColumn[0]) { // Add it again as raw id - $content['userid'] = bigintval($value); + //* DEBUG: */ debug_report_bug(__FUNCTION__, __LINE__, 'key=' . $key . ',userIdColumn=' . $userIdColumn[0]); + $content[$userIdColumn[0]] = bigintval($value); + $content[$userIdColumn[0] . '_raw'] = $content[$userIdColumn[0]]; + } // END - if + + // If the key matches the idColumn variable, we need to temporary remember it + //* DEBUG: */ debugOutput('key=' . $key . ',idColumn=' . $idColumn[0] . ',value=' . $value); + if ($key == $idColumn[0]) { + // Found, so remember it + $GLOBALS['admin_list_builder_id_value'] = $value; } // END - if // Handle the call in external function - $content[$key] = handleExtraValues($filterFunctions[$idx], $value, $extraValues[$idx]); + //* DEBUG: */ debugOutput('key=' . $key . ',fucntion=' . $filterFunctions[$idx] . ',value=' . $value); + $content[$key] = handleExtraValues( + $filterFunctions[$idx], + $value, + $extraValues[$idx] + ); } // END - foreach - // Add color switching - $content['sw'] = $SW; - // Then list it $OUT .= loadTemplate(sprintf("admin_%s_%s_row", - $listType, - $table - ), true, $content + $listType, + $tableName[0] + ), true, $content ); - - // Switch color - $SW = 3 - $SW; } // END - if // Free the result @@ -891,24 +869,40 @@ function adminListBuilder ($listType, $IDs, $table, $columns, $filterFunctions, // Load master template loadTemplate(sprintf("admin_%s_%s", - $listType, - $table - ), false, $OUT + $listType, + $tableName[0] + ), false, $OUT ); } // Change status of "build" list -function adminBuilderStatusHandler ($mode, $IDs, $table, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn, $statusArray) { +function adminBuilderStatusHandler ($mode, $tableName, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn, $statusArray, $rawUserId = array('userid')) { + // $tableName must be an array + if ((!is_array($tableName)) || (count($tableName) != 1)) { + // No tableName specified + debug_report_bug(__FUNCTION__, __LINE__, 'tableName is not given. Please fix your XML,tableName[]=' . gettype($tableName) . '!=array'); + } elseif (!is_array($idColumn)) { + // $idColumn is no array + debug_report_bug(__FUNCTION__, __LINE__, 'idColumn[]=' . gettype($idColumn) . '!=array'); + } elseif ((!is_array($userIdColumn)) || (count($userIdColumn) != 1)) { + // $tableName is no array + debug_report_bug(__FUNCTION__, __LINE__, 'userIdColumn[]=' . gettype($userIdColumn) . '!=array'); + } // END - if + // All valid entries? (We hope so here!) - if ((is_array($IDs)) && (count($IDs) > 0) && (count($columns) == count($filterFunctions)) && (count($columns) == count($extraValues)) && (count($statusArray) > 0)) { + if ((count($columns) == count($filterFunctions)) && (count($columns) == count($extraValues)) && (count($statusArray) > 0)) { // "Walk" through all entries - foreach ($IDs as $id => $sel) { + foreach (postRequestParameter($idColumn[0]) as $id => $sel) { // Construct SQL query - $sql = sprintf("UPDATE `{?_MYSQL_PREFIX?}_%s` SET", SQL_ESCAPE($table)); + $sql = sprintf("UPDATE `{?_MYSQL_PREFIX?}_%s` SET", SQL_ESCAPE($tableName[0])); // Load data of entry - $result = SQL_QUERY_ESC("SELECT * FROM `{?_MYSQL_PREFIX?}_%s` WHERE %s=%s LIMIT 1", - array($table, $idColumn, $id), __FUNCTION__, __LINE__); + $result = SQL_QUERY_ESC("SELECT * FROM `{?_MYSQL_PREFIX?}_%s` WHERE `%s`=%s LIMIT 1", + array( + $tableName[0], + $idColumn[0], + $id + ), __FUNCTION__, __LINE__); // Fetch the data $content = SQL_FETCHARRAY($result); @@ -924,7 +918,7 @@ function adminBuilderStatusHandler ($mode, $IDs, $table, $columns, $filterFuncti // Does the entry exist? if ((isset($content[$column])) && (isset($statusInfo[$content[$column]]))) { // Add these entries for update - $sql .= sprintf(" %s='%s',", SQL_ESCAPE($column), SQL_ESCAPE($statusInfo[$content[$column]])); + $sql .= sprintf(" `%s`='%s',", SQL_ESCAPE($column), SQL_ESCAPE($statusInfo[$content[$column]])); // Remember status if ($statusColumn == 'unknown') { @@ -935,31 +929,37 @@ function adminBuilderStatusHandler ($mode, $IDs, $table, $columns, $filterFuncti } // END - if } elseif (isset($content[$column])) { // Unfinished! - app_die(__FUNCTION__, __LINE__, ":UNFINISHED: id={$id}/{$column}[".gettype($statusInfo)."] = {$content[$column]}"); + debug_report_bug(__FUNCTION__, __LINE__, ':UNFINISHED: id=' . $id . ',column=' . $column . '[' . gettype($statusInfo) . '] = ' . $content[$column]); } } // END - foreach // Add other columns as well foreach (postRequestArray() as $key => $entries) { + // Debug message + logDebugMessage(__FUNCTION__, __LINE__, 'Found entry: ' . $key); + // Skip id, raw userid and 'do_$mode' - if (!in_array($key, array($idColumn, 'userid_raw', ('do_'.$mode)))) { + if (!in_array($key, array($idColumn[0], $rawUserId[0], ('do_' . $mode)))) { // Are there brackets () at the end? - if (substr($entries[$id], -2, 2) == "()") { + if (substr($entries[$id], -2, 2) == '()') { // Direct SQL command found - $sql .= sprintf(" %s=%s,", SQL_ESCAPE($key), SQL_ESCAPE($entries[$id])); + $sql .= sprintf(" `%s`=%s,", SQL_ESCAPE($key), SQL_ESCAPE($entries[$id])); } else { // Add regular entry - $sql .= sprintf(" %s='%s',", SQL_ESCAPE($key), SQL_ESCAPE($entries[$id])); + $sql .= sprintf(" `%s`='%s',", SQL_ESCAPE($key), SQL_ESCAPE($entries[$id])); // Add entry $content[$key] = $entries[$id]; } - } // END - if + } else { + // Skipped entry + logDebugMessage(__FUNCTION__, __LINE__, 'Skipped: ' . $key); + } } // END - foreach // Finish SQL statement $sql = substr($sql, 0, -1) . sprintf(" WHERE `%s`=%s AND `%s`='%s' LIMIT 1", - $idColumn, + $idColumn[0], bigintval($id), $statusColumn, $oldStatus @@ -975,28 +975,47 @@ function adminBuilderStatusHandler ($mode, $IDs, $table, $columns, $filterFuncti } // END - if // Send "build mails" out - sendAdminBuildMails($mode, $table, $content, $id, $statusInfo[$content[$column]]); + sendAdminBuildMails($mode, $tableName, $content, $id, $statusInfo[$content[$column]], $userIdColumn); } // END - foreach } // END - if } // Delete rows by given id numbers -function adminDeleteEntriesConfirm ($IDs, $table, $columns=array(), $filterFunctions=array(), $extraValues=array(), $deleteNow=false, $idColumn='id', $userIdColumn='userid') { +function adminDeleteEntriesConfirm ($tableName, $columns = array(), $filterFunctions = array(), $extraValues = array(), $deleteNow = array(false), $idColumn = array('id'), $userIdColumn = array('userid'), $rawUserId = array('userid')) { + // $tableName must be an array + if ((!is_array($tableName)) || (count($tableName) != 1)) { + // No tableName specified + debug_report_bug(__FUNCTION__, __LINE__, 'tableName is not given. Please fix your XML,tableName[]=' . gettype($tableName) . '!=array'); + } elseif (!is_array($idColumn)) { + // $idColumn is no array + debug_report_bug(__FUNCTION__, __LINE__, 'idColumn[]=' . gettype($idColumn) . '!=array'); + } elseif (!is_array($userIdColumn)) { + // $userIdColumn is no array + debug_report_bug(__FUNCTION__, __LINE__, 'userIdColumn[]=' . gettype($userIdColumn) . '!=array'); + } elseif (!is_array($deleteNow)) { + // $deleteNow is no array + debug_report_bug(__FUNCTION__, __LINE__, 'deleteNow[]=' . gettype($deleteNow) . '!=array'); + } // END - if + // All valid entries? (We hope so here!) - if ((is_array($IDs)) && (count($IDs) > 0) && (count($columns) == count($filterFunctions)) && (count($columns) == count($extraValues))) { + if ((count($columns) == count($filterFunctions)) && (count($columns) == count($extraValues))) { // Shall we delete here or list for deletion? - if ($deleteNow === true) { + if ($deleteNow[0] === true) { // The base SQL command: - $sql = "DELETE LOW_PRIORITY FROM `{?_MYSQL_PREFIX?}_%s` WHERE %s IN (%s)"; + $sql = "DELETE LOW_PRIORITY FROM `{?_MYSQL_PREFIX?}_%s` WHERE `%s` IN (%s)"; // Delete them all $idList = ''; - foreach ($IDs as $id => $sel) { + foreach (postRequestParameter($idColumn[0]) as $id => $sel) { // Is there a userid? - if (isPostRequestElementSet('userid_raw', $id)) { + if (isPostRequestParameterSet($rawUserId[0], $id)) { // Load all data from that id - $result = SQL_QUERY_ESC("SELECT * FROM `{?_MYSQL_PREFIX?}_%s` WHERE %s=%s LIMIT 1", - array($table, $idColumn, $id), __FUNCTION__, __LINE__); + $result = SQL_QUERY_ESC("SELECT * FROM `{?_MYSQL_PREFIX?}_%s` WHERE `%s`=%s LIMIT 1", + array( + $tableName[0], + $idColumn[0], + $id + ), __FUNCTION__, __LINE__); // Fetch the data $content = SQL_FETCHARRAY($result); @@ -1005,7 +1024,7 @@ function adminDeleteEntriesConfirm ($IDs, $table, $columns=array(), $filterFunct SQL_FREERESULT($result); // Send "build mails" out - sendAdminBuildMails('del', $table, $content, $id); + sendAdminBuildMails('delete', $tableName, $content, $id, '', $userIdColumn); } // END - if // Add id number @@ -1013,48 +1032,64 @@ function adminDeleteEntriesConfirm ($IDs, $table, $columns=array(), $filterFunct } // END - foreach // Run the query - SQL_QUERY($sql, array($table, $idColumn, substr($idList, 0, -1)), __FUNCTION__, __LINE__); + SQL_QUERY_ESC($sql, array($tableName[0], $idColumn[0], substr($idList, 0, -1)), __FUNCTION__, __LINE__); // Was this fine? - if (SQL_AFFECTEDROWS() == count($IDs)) { + if (SQL_AFFECTEDROWS() == count(postRequestParameter($idColumn[0]))) { // All deleted - loadTemplate('admin_settings_saved', false, getMessage('ADMIN_ALL_ENTRIES_REMOVED')); + displayMessage('{--ADMIN_ALL_ENTRIES_REMOVED--}'); } else { // Some are still there :( - loadTemplate('admin_settings_saved', false, sprintf(getMessage('ADMIN_SOME_ENTRIES_NOT_DELETED'), SQL_AFFECTEDROWS(), count($IDs))); + displayMessage(sprintf(getMessage('ADMIN_SOME_ENTRIES_NOT_DELETED'), SQL_AFFECTEDROWS(), count(postRequestParameter($idColumn[0])))); } } else { // List for deletion confirmation - adminListBuilder('del', $IDs, $table, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn); + adminListBuilder('delete', $tableName, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn); } } // END - if } // Edit rows by given id numbers -function adminEditEntriesConfirm ($IDs, $table, $columns=array(), $filterFunctions=array(), $extraValues=array(), $editNow=false, $idColumn='id', $userIdColumn='userid') { +function adminEditEntriesConfirm ($tableName, $columns = array(), $filterFunctions = array(), $extraValues = array(), $editNow = array(false), $idColumn = array('id'), $userIdColumn = array('userid'), $rawUserId = array('userid')) { + // $tableName must be an array + if ((!is_array($tableName)) || (count($tableName) != 1)) { + // No tableName specified + debug_report_bug(__FUNCTION__, __LINE__, 'tableName is not given. Please fix your XML,tableName[]=' . gettype($tableName) . '!=array'); + } elseif (!is_array($idColumn)) { + // $idColumn is no array + debug_report_bug(__FUNCTION__, __LINE__, 'idColumn[]=' . gettype($idColumn) . '!=array'); + } elseif (!is_array($userIdColumn)) { + // $userIdColumn is no array + debug_report_bug(__FUNCTION__, __LINE__, 'userIdColumn[]=' . gettype($userIdColumn) . '!=array'); + } elseif (!is_array($editNow)) { + // $editNow is no array + debug_report_bug(__FUNCTION__, __LINE__, 'editNow[]=' . gettype($editNow) . '!=array'); + } // END - if + // All valid entries? (We hope so here!) - if ((is_array($IDs)) && (count($IDs) > 0) && (count($columns) == count($filterFunctions)) && (count($columns) == count($extraValues))) { + //* DEBUG: */ debug_report_bug(__FUNCTION__, __LINE__, 'idColumn=
'.print_r($idColumn,true).',tableName
'.print_r($tableName,true).',columns=
'.print_r($columns,true).',filterFunctions=
'.print_r($filterFunctions,true).',extraValues=
'.print_r($extraValues,true).',editNow=
'.print_r($editNow,true).',userIdColumn=
'.print_r($userIdColumn,true).',rawUserId=
'.print_r($rawUserId,true).''); + if ((count($columns) == count($filterFunctions)) && (count($columns) == count($extraValues))) { // Shall we change here or list for editing? - if ($editNow === true) { + if ($editNow[0] === true) { // Change them all $affected = '0'; - foreach ($IDs as $id => $sel) { + foreach (postRequestParameter($idColumn[0]) as $id => $sel) { // Prepare content array (new values) $content = array(); // Prepare SQL for this row $sql = sprintf("UPDATE `{?_MYSQL_PREFIX?}_%s` SET", - SQL_ESCAPE($table) + SQL_ESCAPE($tableName[0]) ); foreach (postRequestArray() as $key => $entries) { // Skip raw userid which is always invalid - if ($key == 'userid_raw') { + if ($key == $rawUserId[0]) { // Continue with next field continue; } // END - if // Is entries an array? - if (($key != $idColumn) && (is_array($entries)) && (isset($entries[$id]))) { + if (($key != $idColumn[0]) && (is_array($entries)) && (isset($entries[$id]))) { // Add this entry to content $content[$key] = $entries[$id]; @@ -1066,10 +1101,10 @@ function adminEditEntriesConfirm ($IDs, $table, $columns=array(), $filterFunctio // Then add this value $sql .= sprintf(" `%s`='%s',", - SQL_ESCAPE($key), - SQL_ESCAPE($entries[$id]) + SQL_ESCAPE($key), + SQL_ESCAPE($entries[$id]) ); - } elseif (($key != $idColumn) && (!is_array($entries))) { + } elseif (($key != $idColumn[0]) && (!is_array($entries))) { // Add normal entries as well! $content[$key] = $entries; } @@ -1082,7 +1117,7 @@ function adminEditEntriesConfirm ($IDs, $table, $columns=array(), $filterFunctio } // END - foreach // Finish SQL command - $sql = substr($sql, 0, -1) . " WHERE `".$idColumn."`=".bigintval($id)." LIMIT 1"; + $sql = substr($sql, 0, -1) . " WHERE `" . $idColumn[0] . "`=" . bigintval($id) . " LIMIT 1"; // Run this query SQL_QUERY($sql, __FUNCTION__, __LINE__); @@ -1092,7 +1127,11 @@ function adminEditEntriesConfirm ($IDs, $table, $columns=array(), $filterFunctio // Load all data from that id $result = SQL_QUERY_ESC("SELECT * FROM `{?_MYSQL_PREFIX?}_%s` WHERE `%s`=%s LIMIT 1", - array($table, $idColumn, $id), __FUNCTION__, __LINE__); + array( + $tableName[0], + $idColumn[0], + $id + ), __FUNCTION__, __LINE__); // Fetch the data and merge it into $content $content = merge_array($content, SQL_FETCHARRAY($result)); @@ -1101,52 +1140,253 @@ function adminEditEntriesConfirm ($IDs, $table, $columns=array(), $filterFunctio SQL_FREERESULT($result); // Send "build mails" out - sendAdminBuildMails('edit', $table, $content, $id); + sendAdminBuildMails('edit', $tableName, $content, $id, '', $userIdColumn); } // END - foreach // Was this fine? - if ($affected == count($IDs)) { + if ($affected == count(postRequestParameter($idColumn[0]))) { // All deleted - loadTemplate('admin_settings_saved', false, getMessage('ADMIN_ALL_ENTRIES_EDITED')); + displayMessage('{--ADMIN_ALL_ENTRIES_EDITED--}'); } else { // Some are still there :( - loadTemplate('admin_settings_saved', false, sprintf(getMessage('ADMIN_SOME_ENTRIES_NOT_EDITED'), $affected, count($IDs))); + displayMessage(sprintf(getMessage('ADMIN_SOME_ENTRIES_NOT_EDITED'), $affected, count(postRequestParameter($idColumn[0])))); } } else { // List for editing - adminListBuilder('edit', $IDs, $table, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn); + adminListBuilder('edit', $tableName, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn); } - } // END - if + } else { + // Maybe some invalid parameters + debug_report_bug(__FUNCTION__, __LINE__, 'tableName=' . $tableName[0] . ',columns[]=' . gettype($columns) . ',filterFunctions[]=' . gettype($filterFunctions) . ',extraValues[]=' . gettype($extraValues) . ',idColumn=' . $idColumn[0] . ',userIdColumn=' . $userIdColumn[0] . ' - INVALID!'); + } } // Un-/lock rows by given id numbers -function adminLockEntriesConfirm ($IDs, $table, $columns=array(), $filterFunctions=array(), $extraValues=array(), $statusArray=array(), $lockNow=false, $idColumn='id', $userIdColumn='userid') { +function adminLockEntriesConfirm ($tableName, $columns = array(), $filterFunctions = array(), $extraValues = array(), $statusArray = array(), $lockNow = array(false), $idColumn = array('id'), $userIdColumn = array('userid')) { + // $tableName must be an array + if ((!is_array($tableName)) || (count($tableName) != 1)) { + // No tableName specified + debug_report_bug(__FUNCTION__, __LINE__, 'tableName is not given. Please fix your XML,tableName[]=' . gettype($tableName) . '!=array'); + } elseif (!is_array($idColumn)) { + // $idColumn is no array + debug_report_bug(__FUNCTION__, __LINE__, 'idColumn[]=' . gettype($idColumn) . '!=array'); + } elseif (!is_array($lockNow)) { + // $lockNow is no array + debug_report_bug(__FUNCTION__, __LINE__, 'lockNow[]=' . gettype($lockNow) . '!=array'); + } // END - if + // All valid entries? (We hope so here!) - if ((is_array($IDs)) && (count($IDs) > 0) && (count($columns) == count($filterFunctions)) && (count($columns) == count($extraValues)) && (($lockNow === false) || (count($statusArray) == 1))) { + if ((count($columns) == count($filterFunctions)) && (count($columns) == count($extraValues)) && (($lockNow[0] === false) || (count($statusArray) == 1))) { // Shall we un-/lock here or list for locking? - if ($lockNow === true) { + if ($lockNow[0] === true) { // Un-/lock entries - adminBuilderStatusHandler("lock", $IDs, $table, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn, $statusArray); + adminBuilderStatusHandler('lock', $tableName, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn, $statusArray); } else { // List for editing - adminListBuilder("lock", $IDs, $table, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn); + adminListBuilder('lock', $tableName, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn); } } // END - if } // Undelete rows by given id numbers -function adminUndeleteEntriesConfirm ($IDs, $table, $columns=array(), $filterFunctions=array(), $extraValues=array(), $statusArray=array(), $undeleteNow=false, $idColumn='id', $userIdColumn='userid') { +function adminUndeleteEntriesConfirm ($tableName, $columns = array(), $filterFunctions = array(), $extraValues = array(), $statusArray = array(), $undeleteNow = array(false), $idColumn = array('id'), $userIdColumn = array('userid')) { + // $tableName must be an array + if ((!is_array($tableName)) || (count($tableName) != 1)) { + // No tableName specified + debug_report_bug(__FUNCTION__, __LINE__, 'tableName is not given. Please fix your XML,tableName[]=' . gettype($tableName) . '!=array'); + } elseif (!is_array($idColumn)) { + // $idColumn is no array + debug_report_bug(__FUNCTION__, __LINE__, 'idColumn[]=' . gettype($idColumn) . '!=array'); + } elseif (!is_array($undeleteNow)) { + // $undeleteNow is no array + debug_report_bug(__FUNCTION__, __LINE__, 'undeleteNow[]=' . gettype($undeleteNow) . '!=array'); + } // END - if + // All valid entries? (We hope so here!) - if ((is_array($IDs)) && (count($IDs) > 0) && (count($columns) == count($filterFunctions)) && (count($columns) == count($extraValues)) && (($undeleteNow === false) || (count($statusArray) == 1))) { + if ((count($columns) == count($filterFunctions)) && (count($columns) == count($extraValues)) && (($undeleteNow[0] === false) || (count($statusArray) == 1))) { // Shall we un-/lock here or list for locking? - if ($undeleteNow === true) { + if ($undeleteNow[0] === true) { // Undelete entries - adminBuilderStatusHandler("undelete", $IDs, $table, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn, $statusArray); + adminBuilderStatusHandler('undelete', $tableName, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn, $statusArray); } else { // List for editing - adminListBuilder("undelete", $IDs, $table, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn); + adminListBuilder('undelete', $tableName, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn); + } + } // END - if +} + +// Adds a given entry to the database +function adminAddEntries ($tableName, $columns = array(), $filterFunctions = array(), $extraValues = array()) { + //* DEBUG: */ die('columns=
'.print_r($columns,true).',filterFunctions=
'.print_r($filterFunctions,true).',extraValues=
'.print_r($extraValues,true).',POST=
'.print_r($_POST,true).''); + // Verify that tableName and columns are not empty + if ((!is_array($tableName)) || (count($tableName) != 1)) { + // No tableName specified + debug_report_bug(__FUNCTION__, __LINE__, 'tableName is not given. Please fix your XML,tableName[]=' . gettype($tableName) . '!=array'); + } elseif (count($columns) == 0) { + // No columns specified + debug_report_bug(__FUNCTION__, __LINE__, 'columns is not given. Please fix your XML.'); + } + + // Init columns and value elements + $sqlColumns = array(); + $sqlValues = array(); + + // Add columns and values + foreach ($columns as $key=>$columnName) { + // Copy entry to final arrays + $sqlColumns[$key] = $columnName; + $sqlValues[$key] = postRequestParameter($columnName); + //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key='.$key.',columnName='.$columnName.',filterFunctions='.$filterFunctions[$key].',extraValues='.intval(isset($extraValues[$key])).',extraValuesName='.intval(isset($extraValues[$columnName . '_list'])).'
'.print_r($args, true).''); + // @TODO If we can rewrite the EL sub-system to support more than one parameter, this call_user_func_array() can be avoided + $content[$columnName] = call_user_func_array($callbackFunction, $args); + } // END - foreach + + // Load row template + $OUT .= loadTemplate(trim($rowTemplate[0]), true, $content); + } // END - while + + // Load main template + loadTemplate(trim($tableTemplate[0]), false, $OUT); + } else { + // No URLs in surfbar + displayMessage('{--' .$noEntryMessageId[0] . '--}'); + } + + // Free result + SQL_FREERESULT($result); } // Checks proxy settins by fetching check-updates3.php from www.mxchange.org @@ -1158,7 +1398,7 @@ function adminTestProxySettings ($settingsArray) { $content = sendGetRequest('check-updates3.php'); // Is the first line with "200 OK"? - $valid = (strpos($content[0], '200 OK') !== false); + $valid = isInString('200 OK', $content[0]); // Return result return $valid; @@ -1170,13 +1410,13 @@ function sendAdminPasswordResetLink ($email) { $OUT = ''; //Â Look up administator login - $result = SQL_QUERY_ESC("SELECT `id`, `login`, `password` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `email`='%s' LIMIT 1", + $result = SQL_QUERY_ESC("SELECT `id`,`login`,`password` FROM `{?_MYSQL_PREFIX?}_admins` WHERE '%s' REGEXP `email` LIMIT 1", array($email), __FUNCTION__, __LINE__); // Is there an account? - if (SQL_NUMROWS($result) == '0') { - // No account found! - return getMessage('ADMIN_NO_LOGIN_WITH_EMAIL'); + if (SQL_HASZERONUMS($result)) { + // No account found + return '{--ADMIN_NO_LOGIN_WITH_EMAIL--}'; } // END - if // Load all data @@ -1186,7 +1426,7 @@ function sendAdminPasswordResetLink ($email) { SQL_FREERESULT($result); // Generate hash for reset link - $content['hash'] = generateHash(getConfig('URL').':'.$content['id'].':'.$content['login'].':'.$content['password'], substr($content['password'], 10)); + $content['hash'] = generateHash(getUrl() . getEncryptSeperator() . $content['id'] . getEncryptSeperator() . $content['login'] . getEncryptSeperator() . $content['password'], substr($content['password'], getSaltLength())); // Remove some data unset($content['id']); @@ -1196,10 +1436,10 @@ function sendAdminPasswordResetLink ($email) { $mailText = loadEmailTemplate('admin_reset_password', $content); // Send it out - sendEmail($email, getMessage('ADMIN_RESET_PASS_LINK_SUBJ'), $mailText); + sendEmail($email, '{--ADMIN_RESET_PASSWORD_LINK_SUBJECT--}', $mailText); // Prepare output - return getMessage('ADMIN_RESET_LINK_SENT'); + return '{--ADMIN_RESET_PASSWORD_LINK_SENT--}'; } // Validate hash and login for password reset @@ -1208,7 +1448,7 @@ function adminResetValidateHashLogin ($hash, $login) { $valid = false; // Then try to find that user - $result = SQL_QUERY_ESC("SELECT `id`, `password`, `email` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `login`='%s' LIMIT 1", + $result = SQL_QUERY_ESC("SELECT `id`,`password`,`email` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `login`='%s' LIMIT 1", array($login), __FUNCTION__, __LINE__); // Is an account here? @@ -1217,7 +1457,7 @@ function adminResetValidateHashLogin ($hash, $login) { $content = SQL_FETCHARRAY($result); // Generate hash again - $hashFromData = generateHash(getConfig('URL') . ':' . $content['id'] . ':' . $login . ':' . $content['password'], substr($content['password'], 10)); + $hashFromData = generateHash(getUrl() . getEncryptSeperator() . $content['id'] . getEncryptSeperator() . $login . getEncryptSeperator() . $content['password'], substr($content['password'], getSaltLength())); // Does both match? $valid = ($hash == $hashFromData); @@ -1232,27 +1472,23 @@ function adminResetValidateHashLogin ($hash, $login) { // Reset the password for the login. Do NOT call this function without calling above function first! function doResetAdminPassword ($login, $password) { - // Init hash - $passHash = ''; + // Generate hash (we already check for sql_patches in generateHash()) + $passHash = generateHash($password); - // Now check if we have sql_patches installed - if (isExtensionInstalledAndNewer('sql_patches', '0.3.6')) { - // Use new way of hashing - $passHash = generateHash($password); - } else { - // Old MD5 method - $passHash = md5($password); - } + // Prepare fake POST data + $postData = array( + 'login' => array(getAdminId($login) => $login), + 'password' => array(getAdminId($login) => $passHash), + ); // Update database - SQL_QUERY_ESC("UPDATE `{?_MYSQL_PREFIX?}_admins` SET `password`='%s' WHERE `login`='%s' LIMIT 1", - array($passHash, $login), __FUNCTION__, __LINE__); + $message = adminsChangeAdminAccount($postData, '', false); // Run filters - runFilterChain('post_admin_reset_pass', array('login' => $login, 'hash' => $passHash)); + runFilterChain('post_form_reset_pass', array('login' => $login, 'hash' => $passHash, 'message' => $message)); // Return output - return getMessage('ADMIN_PASSWORD_RESET_DONE'); + return '{--ADMIN_PASSWORD_RESET_DONE--}'; } // Solves a task by given id number @@ -1269,16 +1505,13 @@ function adminDeleteTask ($id) { // Function to update task data function adminUpdateTaskData ($id, $row, $data) { - // Should be admin! + // Should be admin and valid id if (!isAdmin()) { // Not an admin so redirect better - redirectToUrl('index.php'); - } // END - if - - // Is the id not set, then we need a backtrace here... :( - if ($id <= 0) { + debug_report_bug(__FUNCTION__, __LINE__, 'id=' . $id . ',row=' . $row . ',data=' . $data . ' - isAdmin()=false'); + } elseif ($id <= 0) { // Initiate backtrace - debug_report_bug(sprintf("id is invalid: %s. row=%s, data=%s", + debug_report_bug(__FUNCTION__, __LINE__, sprintf("id is invalid: %s. row=%s, data=%s", $id, $row, $data @@ -1287,17 +1520,24 @@ function adminUpdateTaskData ($id, $row, $data) { // Update the task SQL_QUERY_ESC("UPDATE `{?_MYSQL_PREFIX?}_task_system` SET `%s`='%s' WHERE `id`=%s LIMIT 1", - array($row, $data, bigintval($id)), __FUNCTION__, __LINE__); + array( + $row, + $data, + bigintval($id) + ), __FUNCTION__, __LINE__); } // Checks wether if the admin menu has entries function ifAdminMenuHasEntries ($action) { return ( (( + // Is the entry set? isset($GLOBALS['admin_menu_has_entries'][$action]) ) && ( + // And do we have a menu for this action? $GLOBALS['admin_menu_has_entries'][$action] === true )) || ( + // Login has always a menu $action == 'login' ) ); @@ -1311,19 +1551,19 @@ function setAdminMenuHasEntries ($action, $hasEntries) { // Creates a link to the user's admin-profile function adminCreateUserLink ($userid) { // Is the userid set correctly? - if ($userid > 0) { + if (isValidUserId($userid)) { // Create a link to that profile - return '{?URL?}/modules.php?module=admin&what=list_user&userid='.bigintval($userid); + return '{%url=modules.php?module=admin&what=list_user&userid=' . bigintval($userid) . '%}'; } // END - if // Return a link to the user list - return '{?URL?}/modules.php?module=admin&what=list_user'; + return '{%url=modules.php?module=admin&what=list_user%}'; } // Generate a "link" for the given admin id (admin_id) function generateAdminLink ($adminId) { // No assigned admin is default - $adminLink = "{--ADMIN_NO_ADMIN_ASSIGNED--}"; + $adminLink = '{--ADMIN_NO_ADMIN_ASSIGNED--}'; // Zero? = Not assigned if (bigintval($adminId) > 0) { @@ -1335,14 +1575,14 @@ function generateAdminLink ($adminId) { // Is the extension there? if (isExtensionActive('admins')) { // Admin found - $adminLink = "" . $login.""; + $adminLink = '' . $login . ''; } else { // Extension not found - $adminLink = sprintf(getMessage('EXTENSION_PROBLEM_NOT_INSTALLED'), 'admins'); + $adminLink = '{%message,ADMIN_TASK_ROW_EXTENSION_NOT_INSTALLED=admins%}'; } } else { // Maybe deleted? - $adminLink = "