Missing li-tag added to avoid XHTML error
[mailer.git] / inc / modules / admin / admin-inc.php
1 <?php
2 /************************************************************************
3  * MXChange v0.2.1                                    Start: 08/31/2003 *
4  * ===============                              Last change: 11/23/2004 *
5  *                                                                      *
6  * -------------------------------------------------------------------- *
7  * File              : admin-inc.php                                    *
8  * -------------------------------------------------------------------- *
9  * Short description : Administrative related functions                 *
10  * -------------------------------------------------------------------- *
11  * Kurzbeschreibung  : Fuer die Administration benoetigte Funktionen    *
12  * -------------------------------------------------------------------- *
13  * $Revision::                                                        $ *
14  * $Date::                                                            $ *
15  * $Tag:: 0.2.1-FINAL                                                 $ *
16  * $Author::                                                          $ *
17  * Needs to be in all Files and every File needs "svn propset           *
18  * svn:keywords Date Revision" (autoprobset!) at least!!!!!!            *
19  * -------------------------------------------------------------------- *
20  * Copyright (c) 2003 - 2008 by Roland Haeder                           *
21  * For more information visit: http://www.mxchange.org                  *
22  *                                                                      *
23  * This program is free software; you can redistribute it and/or modify *
24  * it under the terms of the GNU General Public License as published by *
25  * the Free Software Foundation; either version 2 of the License, or    *
26  * (at your option) any later version.                                  *
27  *                                                                      *
28  * This program is distributed in the hope that it will be useful,      *
29  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
30  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
31  * GNU General Public License for more details.                         *
32  *                                                                      *
33  * You should have received a copy of the GNU General Public License    *
34  * along with this program; if not, write to the Free Software          *
35  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,               *
36  * MA  02110-1301  USA                                                  *
37  ************************************************************************/
38
39 // Some security stuff...
40 if (!defined('__SECURITY')) {
41         $INC = substr(dirname(__FILE__), 0, strpos(dirname(__FILE__), '/inc') + 4) . '/security.php';
42         require($INC);
43 }
44
45 // Register an administrator account
46 function REGISTER_ADMIN ($user, $md5, $email) {
47         // Login does already exist
48         $ret = "already";
49
50         // Lookup the admin
51         $result = SQL_QUERY_ESC("SELECT `id` FROM `{!_MYSQL_PREFIX!}_admins` WHERE login='%s' LIMIT 1",
52         array($user), __FUNCTION__, __LINE__);
53
54         // Is the entry there?
55         if (SQL_NUMROWS($result) == 0) {
56                 // Ok, let's create the admin login
57                 SQL_QUERY_ESC("INSERT INTO `{!_MYSQL_PREFIX!}_admins` (login, password, email) VALUES ('%s', '%s', '%s')",
58                 array($user, $md5, $email), __FUNCTION__, __LINE__);
59                 $ret = 'done';
60         } // END - if
61
62         // Free memory
63         SQL_FREERESULT($result);
64
65         // Return result
66         return $ret;
67 }
68
69 // Only be executed on login procedure!
70 function CHECK_ADMIN_LOGIN ($admin_login, $password) {
71         // By default no admin is found
72         $ret = '404';
73
74         // Get admin id
75         $aid = GET_ADMIN_ID($admin_login);
76
77         // Init array with admin id by default
78         $data = array('aid' => $aid);
79
80         // Is the cache valid?
81         if (isset($GLOBALS['cache_array']['admins']['password'][$aid])) {
82                 // Get password from cache
83                 $data['password'] = $GLOBALS['cache_array']['admins']['password'][$aid];
84                 $ret = 'pass';
85                 incrementConfigEntry('cache_hits');
86
87                 // Include more admins data?
88                 if (GET_EXT_VERSION('admins') >= '0.7.2') {
89                         // Load them here
90                         $data['login_failures'] = $GLOBALS['cache_array']['admins']['login_failures'][$aid];
91                         $data['last_failure']   = $GLOBALS['cache_array']['admins']['last_failure'][$aid];
92                 } // END - if
93         } elseif (!EXT_IS_ACTIVE('cache')) {
94                 // Add extra data via filter now
95                 $add = runFilterChain('sql_admin_extra_data');
96
97                 // Get password from DB
98                 $result = SQL_QUERY_ESC("SELECT password".$add." FROM `{!_MYSQL_PREFIX!}_admins` WHERE `id`=%s LIMIT 1",
99                 array($aid), __FUNCTION__, __LINE__);
100
101                 // Entry found?
102                 if (SQL_NUMROWS($result) == 1) {
103                         // Login password found
104                         $ret = 'pass';
105
106                         // Fetch data
107                         $data = SQL_FETCHARRAY($result);
108                 } // END - if
109
110                 // Free result
111                 SQL_FREERESULT($result);
112         }
113
114         //* DEBUG: */ echo "*".$data['password'].'/'.md5($password).'/'.$ret."<br />";
115         if ((isset($data['password'])) && (strlen($data['password']) == 32) && ($data['password'] == md5($password))) {
116                 // Generate new hash
117                 $data['password'] = generateHash($password);
118
119                 // Is the sql_patches not installed, than we cannot have a valid hashed password here!
120                 if (($ret == 'pass') && ((EXT_VERSION_IS_OLDER('sql_patches', '0.3.6')) || (GET_EXT_VERSION('sql_patches') == ''))) $ret = 'done';
121         } elseif ((EXT_VERSION_IS_OLDER('sql_patches', '0.3.6')) || (GET_EXT_VERSION('sql_patches') == '')) {
122                 // Old hashing way
123                 return $ret;
124         } elseif (!isset($data['password'])) {
125                 // Password not found, so no valid login!
126                 return $ret;
127         }
128
129         // Generate salt of password
130         define('__SALT', substr($data['password'], 0, -40));
131         $salt = __SALT;
132
133         // Check if password is same
134         //* DEBUG: */ echo "*".$ret.','.$data['password'].','.$password.','.$salt."*<br >\n";
135         if (($ret == 'pass') && ($data['password'] == generateHash($password, $salt)) && ((!empty($salt))) || ($data['password'] == $password)) {
136                 // Re-hash the plain passord with new random salt
137                 $data['password'] = generateHash($password);
138
139                 // Do we have 0.7.0 of admins or later?
140                 // Remmeber login failures if available
141                 if (GET_EXT_VERSION('admins') >= '0.7.2') {
142                         // Store it in session
143                         setSession('mxchange_admin_failures', $data['login_failures']);
144                         setSession('mxchange_admin_last_fail', $data['last_failure']);
145
146                         // Update password and reset login failures
147                         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",
148                         array($data['password'], $aid), __FUNCTION__, __LINE__);
149                 } else {
150                         // Update password
151                         SQL_QUERY_ESC("UPDATE `{!_MYSQL_PREFIX!}_admins` SET password='%s' WHERE `id`=%s LIMIT 1",
152                         array($data['password'], $aid), __FUNCTION__, __LINE__);
153                 }
154
155                 // Rebuild cache
156                 rebuildCacheFiles('admins', 'admin');
157
158                 // Login has failed by default... ;-)
159                 $ret = "failed";
160
161                 // Password matches so login here
162                 if (LOGIN_ADMIN($admin_login, $data['password'])) {
163                         // All done now
164                         $ret = 'done';
165                 } // END - if
166         } elseif ((empty($salt)) && ($ret == 'pass')) {
167                 // Something bad went wrong
168                 $ret = "failed";
169         } elseif ($ret == 'done') {
170                 // Try to login here if we have the old hashing way (sql_patches not installed?)
171                 if (!LOGIN_ADMIN($admin_login, $data['password'])) {
172                         // Something went wrong
173                         $ret = "failed";
174                 } // END - if
175         }
176
177         // Count login failure if admins extension version is 0.7.0+
178         if (($ret == 'pass') && (GET_EXT_VERSION('admins') >= '0.7.0')) {
179                 // Update counter
180                 SQL_QUERY_ESC("UPDATE `{!_MYSQL_PREFIX!}_admins` SET login_failures=login_failures+1,last_failure=NOW() WHERE `id`=%s LIMIT 1",
181                 array($aid), __FUNCTION__, __LINE__);
182
183                 // Rebuild cache
184                 rebuildCacheFiles('admins', 'admin');
185         } // END - if
186
187         // Return the result
188         //* DEBUG: */ die("RETURN=".$ret);
189         return $ret;
190 }
191
192 // Try to login the admin by setting some session/cookie variables
193 function LOGIN_ADMIN ($adminLogin, $passHash) {
194         // Reset failure counter on matching admins version
195         if ((GET_EXT_VERSION('admins') >= '0.7.0') && ((EXT_VERSION_IS_OLDER('sql_patches', '0.3.6')) || (GET_EXT_VERSION('sql_patches') == ''))) {
196                 // Reset counter on out-dated sql_patches version
197                 SQL_QUERY_ESC("UPDATE `{!_MYSQL_PREFIX!}_admins` SET login_failures=0,last_failure='0000-00-00 00:00:00' WHERE login='%s' LIMIT 1",
198                 array($adminLogin), __FUNCTION__, __LINE__);
199
200                 // Rebuild cache
201                 rebuildCacheFiles('admins', 'admin');
202         } // END - if
203
204         // Now set all session variables and return the result
205         return (
206         (
207         setSession('admin_md5', generatePassString($passHash))
208         ) && (
209         setSession('admin_login', $adminLogin)
210         ) && (
211         setSession('admin_last', time())
212         ) && (
213         setSession('admin_to', bigintval(REQUEST_POST('timeout')))
214         )
215         );
216 }
217
218 // Only be executed on cookie checking
219 function CHECK_ADMIN_COOKIES ($admin_login, $password) {
220         // By default no admin cookies are found
221         $ret = '404'; $pass = '';
222
223         // Get hash
224         $pass = GET_ADMIN_HASH(GET_ADMIN_ID($admin_login));
225         if ($pass != '-1') $ret = 'pass';
226
227         //* DEBUG: */ print __FUNCTION__."(<font color=\"#0000aa\">".__LINE__."</font>):".generatePassString($pass).'('.strlen($pass).")/".$password.'('.strlen($password).")<br />\n";
228
229         // Check if password matches
230         if (($ret == 'pass') && ((generatePassString($pass) == $password) || ($pass == $password) || ((strlen($pass) == 32) && (md5($password) == $pass)))) {
231                 // Passwords matches!
232                 $ret = 'done';
233         }
234
235         // Return result
236         return $ret;
237 }
238
239 //
240 function ADMIN_DO_ACTION ($wht) {
241         global $DATA;
242         //* DEBUG: */ echo __LINE__."*".$wht.'/'.$GLOBALS['module'].'/'.$GLOBALS['action'].'/'.$GLOBALS['what']."*<br />\n";
243
244         // Remove any spaces from variable
245         if (empty($wht)) {
246                 // Default admin action is the overview page
247                 $wht = "overview";
248         } else {
249                 // Compile out some chars
250                 $wht = COMPILE_CODE($wht, false, false, false);
251         }
252
253         // Get action value
254         $act = getModeAction($GLOBALS['module'], $wht);
255
256         // Define admin login name and ID number
257         define('__ADMIN_LOGIN', getSession('admin_login'));
258         define('__ADMIN_ID'   , getCurrentAdminId());
259
260         // Preload templates
261         if (EXT_IS_ACTIVE('admins')) {
262                 define('__ADMIN_WELCOME', LOAD_TEMPLATE("admin_welcome_admins", true));
263         } else {
264                 define('__ADMIN_WELCOME', LOAD_TEMPLATE("admin_welcome", true));
265         }
266         define('__ADMIN_FOOTER' , LOAD_TEMPLATE("admin_footer" , true));
267         define('__ADMIN_MENU'   , ADD_ADMIN_MENU($act, $wht, true));
268
269         // Tableset header
270         LOAD_TEMPLATE("admin_main_header");
271
272         // Check if action/what pair is valid
273         $result_action = SQL_QUERY_ESC("SELECT `id` FROM `{!_MYSQL_PREFIX!}_admin_menu`
274 WHERE `action`='%s' AND ((`what`='%s' AND what != 'overview') OR ((`what`='' OR `what` IS NULL) AND '%s'='overview'))
275 LIMIT 1", array($act, $wht, $wht), __FUNCTION__, __LINE__);
276         if (SQL_NUMROWS($result_action) == 1) {
277                 // Is valid but does the inlcude file exists?
278                 $INC = sprintf("inc/modules/admin/action-%s.php", $act);
279                 if ((isIncludeReadable($INC)) && (isMenuActionValid('admin', $act, $wht)) && ($GLOBALS['acl_allow'] === true)) {
280                         // Ok, we finally load the admin action module
281                         loadInclude($INC);
282                 } elseif ($GLOBALS['acl_allow'] === false) {
283                         // Access denied
284                         LOAD_TEMPLATE("admin_menu_failed", false, getMessage('ADMIN_ACCESS_DENIED'));
285                         addFatalMessage(__FUNCTION__, __LINE__, getMessage('ADMIN_ACCESS_DENIED'));
286                 } else {
287                         // Include file not found! :-(
288                         LOAD_TEMPLATE("admin_menu_failed", false, sprintf(getMessage('ADMIN_ACTION_404'), $act));
289                         addFatalMessage(__FUNCTION__, __LINE__, getMessage('ADMIN_ACTION_404'), $act);
290                 }
291         } else {
292                 // Invalid action/what pair found!
293                 LOAD_TEMPLATE("admin_menu_failed", false, sprintf(getMessage('ADMIN_ACTION_INVALID'), $act.'/'.$wht));
294                 addFatalMessage(__FUNCTION__, __LINE__, getMessage('ADMIN_ACTION_INVALID'), $act.'/'.$wht);
295         }
296
297         // Free memory
298         SQL_FREERESULT($result_action);
299
300         // Tableset footer
301         LOAD_TEMPLATE("admin_main_footer");
302 }
303
304 //
305 function ADD_ADMIN_MENU ($act, $wht, $return=false) {
306         // Init variables
307         $SUB = false;
308         $OUT = '';
309
310         // Menu descriptions
311         $GLOBALS['menu']['description'] = array();
312         $GLOBALS['menu']['title'] = array();
313
314         // Is there a cache instance?
315         if ((isCacheInstanceValid()) && (getConfig('cache_admin_menu') == 'Y')) {
316                 // Create cache name
317                 $cacheName = "admin_".$act."_".$wht."_".getLanguage()."_".strtolower(getSession('admin_login'));
318
319                 // Is that cache there?
320                 if ($GLOBALS['cache_instance']->loadCacheFile($cacheName)) {
321                         // Then load it
322                         $data = $GLOBALS['cache_instance']->getArrayFromCache();
323
324                         // Extract all parts
325                         $OUT = base64_decode($data['output'][0]);
326                         $GLOBALS['menu']['title'] = unserialize(base64_decode($data['title'][0]));
327                         $GLOBALS['menu']['description'] = unserialize(base64_decode($data['descr'][0]));
328
329                         // Return or output content?
330                         if ($return === true) {
331                                 return $OUT;
332                         } else {
333                                 OUTPUT_HTML($OUT);
334                         }
335                 } // END - if
336         } // END - if
337
338         // Build main menu
339         $result_main = SQL_QUERY("SELECT action, title, descr FROM `{!_MYSQL_PREFIX!}_admin_menu` WHERE (`what`='' OR `what` IS NULL) ORDER BY `sort`, id DESC", __FUNCTION__, __LINE__);
340         if (SQL_NUMROWS($result_main) > 0) {
341                 $OUT = "<div style=\"height:7px\" class=\"seperator\">&nbsp;</div>\n";
342                 $OUT .= "<ul class=\"admin_menu_main\">\n";
343                 // @TODO Rewrite this to $content = SQL_FETCHARRAY()
344                 while (list($menu, $title, $descr) = SQL_FETCHROW($result_main)) {
345                         if ((EXT_IS_ACTIVE('admins')) && (GET_EXT_VERSION('admins') > '0.2.0')) {
346                                 $ACL = adminsCheckAdminAcl($menu, '');
347                         } else {
348                                 // ACL is "allow"... hmmm
349                                 $ACL = true;
350                         }
351
352                         if ($ACL === true) {
353                                 if (!$SUB) {
354                                         // Insert compiled menu title and description
355                                         $GLOBALS['menu']['title'][$menu]      = $title;
356                                         $GLOBALS['menu']['description'][$menu] = $descr;
357                                 }
358                                 $OUT .= "<li class=\"admin_menu\">
359                 <div class=\"nobr\"><strong>&middot;</strong>&nbsp;";
360
361                                 if (($menu == $act) && (empty($wht))) {
362                                         $OUT .= "<strong>";
363                                 } else {
364                                         $OUT .= "[<a href=\"{!URL!}/modules.php?module=admin&amp;action=".$menu."\">";
365                                 }
366
367                                 $OUT .= $title;
368
369                                 if (($menu == $act) && (empty($wht))) {
370                                         $OUT .= "</strong>";
371                                 } else {
372                                         $OUT .= "</a>]";
373                                 }
374
375                                 $OUT .= "</div>
376 </li>\n";
377
378                                 // Check for menu entries
379                                 $result_what = SQL_QUERY_ESC("SELECT what, title, descr FROM `{!_MYSQL_PREFIX!}_admin_menu` WHERE `action`='%s' AND `what` != '' AND `what` IS NOT NULL ORDER BY `sort`, id DESC",
380                                         array($menu), __FUNCTION__, __LINE__);
381
382                                 // Remember the count for later checks
383                                 setAdminMenuHasEntries($menu, ((SQL_NUMROWS($result_what) > 0) && ($act == $menu)));
384
385                                 // Do we have entries?
386                                 if ((ifAdminMenuHasEntries($menu)) && (SQL_NUMROWS($result_what) > 0)) {
387                                         $GLOBALS['menu']['description'] = array();
388                                         $GLOBALS['menu']['title'] = array(); $SUB = true;
389                                         $OUT .= "<li class=\"admin_menu_sub\"><ul class=\"admin_menu_sub\">\n";
390                                         // @TODO Rewrite this to $content = SQL_FETCHARRAY()
391                                         while (list($wht_sub, $title_what, $desc_what) = SQL_FETCHROW($result_what)) {
392                                                 // Check for access level
393                                                 if ((EXT_IS_ACTIVE('admins')) && (GET_EXT_VERSION('admins') > '0.2.0')) {
394                                                         $ACL = adminsCheckAdminAcl('', $wht_sub);
395                                                 } else {
396                                                         // ACL is "allow"... hmmm
397                                                         $ACL = true;
398                                                 }
399
400                                                 // Filename
401                                                 $INC = sprintf("inc/modules/admin/what-%s.php", $wht_sub);
402
403                                                 // Is the file readable?
404                                                 $readable = isIncludeReadable($INC);
405
406                                                 // Access allowed?
407                                                 if ($ACL === true) {
408                                                         // Insert compiled title and description
409                                                         $GLOBALS['menu']['title'][$wht_sub]      = $title_what;
410                                                         $GLOBALS['menu']['description'][$wht_sub] = $desc_what;
411                                                         $OUT .= "<li class=\"admin_menu\">
412                 <div class=\"nobr\"><strong>--&gt;</strong>&nbsp;";
413                                                         if ($readable === true) {
414                                                                 if ($wht == $wht_sub) {
415                                                                         $OUT .= "<strong>";
416                                                                 } else {
417                                                                         $OUT .= "[<a href=\"{!URL!}/modules.php?module=admin&amp;what=".$wht_sub."\">";
418                                                                 }
419                                                         } else {
420                                                                 $OUT .= "<em class=\"admin_note\">";
421                                                         }
422
423                                                         $OUT .= $title_what;
424
425                                                         if ($readable === true) {
426                                                                 if ($wht == $wht_sub) {
427                                                                         $OUT .= "</strong>";
428                                                                 } else {
429                                                                         $OUT .= "</a>]";
430                                                                 }
431                                                         } else {
432                                                                 $OUT .= "</em>";
433                                                         }
434                                                         $OUT .= "</div>
435 </li>\n";
436                                                 }
437                                         }
438
439                                         // Free memory
440                                         SQL_FREERESULT($result_what);
441                                         $OUT .= "       </ul>
442 </li>\n";
443                                 }
444
445                                 $OUT .= "<li style=\"height:7px\" class=\"seperator\">&nbsp;</li>\n";
446                         }
447                 }
448
449                 // Free memory
450                 SQL_FREERESULT($result_main);
451                 $OUT .= "</ul>\n";
452         }
453
454         // Is there a cache instance again?
455         if ((isCacheInstanceValid()) && (getConfig('cache_admin_menu') == 'Y')) {
456                 // Init cache
457                 $GLOBALS['cache_instance']->init($cacheName);
458
459                 // Prepare cache data
460                 $data = array(
461                         'output' => base64_encode($OUT),
462                         'title'  => $GLOBALS['menu']['title'],
463                         'descr'  => $GLOBALS['menu']['description']
464                 );
465
466                 // Write the data away
467                 $GLOBALS['cache_instance']->addRow($data);
468
469                 // Close cache
470                 $GLOBALS['cache_instance']->finalize();
471         } // END - if
472
473         // Return or output content?
474         if ($return === true) {
475                 return $OUT;
476         } else {
477                 OUTPUT_HTML($OUT);
478         }
479 }
480
481 // Create member selection box
482 function ADD_MEMBER_SELECTION_BOX ($def='0', $add_all=false, $return=false, $none=false, $field='userid') {
483         // Output selection form with all confirmed user accounts listed
484         $result = SQL_QUERY("SELECT userid, surname, family FROM `{!_MYSQL_PREFIX!}_user_data` ORDER BY `userid` ASC", __FUNCTION__, __LINE__);
485
486         // Default output
487         $OUT = '';
488
489         // USe this only for adding points (e.g. adding refs really makes no sence ;-) )
490         if ($add_all === true)   $OUT = "      <option value=\"all\">{--ALL_MEMBERS--}</option>\n";
491         elseif ($none === true) $OUT = "      <option value=\"0\">{--SELECT_NONE--}</option>\n";
492
493         while ($content = SQL_FETCHARRAY($result)) {
494                 $OUT .= "      <option value=\"".bigintval($content['userid'])."\"";
495                 if ($def == $content['userid']) $OUT .= ' selected="selected"';
496                 $OUT .= ">".$content['surname']." ".$content['family']." (".bigintval($content['userid']).")</option>\n";
497         } // END - while
498
499         // Free memory
500         SQL_FREERESULT($result);
501
502         if (!$return) {
503                 // Remeber options in constant
504                 // @TODO Rewrite these both constants
505                 define('_MEMBER_SELECTION', $OUT);
506
507                 // Display selection box
508                 define('__LANG_VALUE', getLanguage());
509
510                 // Load template
511                 LOAD_TEMPLATE("admin_member_selection_box", false, $GLOBALS['what']);
512         } else {
513                 // Return content in selection frame
514                 return "<select class=\"admin_select\" name=\"".$field."\" size=\"1\">\n".$OUT."</select>\n";
515         }
516 }
517
518 // Create a menu selection box for given menu system
519 function ADMIN_MENU_SELECTION ($mode, $default = '', $defid = '') {
520         $wht = "`what` != ''";
521         if ($mode == "action") $wht = "(`what`='' OR `what` IS NULL) AND action !='login'";
522         $result = SQL_QUERY_ESC("SELECT %s, title FROM `{!_MYSQL_PREFIX!}_admin_menu` WHERE ".$wht." ORDER BY `sort`",
523         array($mode), __FUNCTION__, __LINE__);
524         if (SQL_NUMROWS($result) > 0) {
525                 // Load menu as selection
526                 $OUT = "<select name=\"".$mode."_menu";
527                 if ((!empty($defid)) || ($defid == '0')) $OUT .= "[".$defid."]";
528                 $OUT .= "\" size=\"1\" class=\"admin_select\">
529         <option value=\"\">{--SELECT_NONE--}</option>\n";
530                 // @TODO Try to rewrite this to $content = SQL_FETCHARRAY(). Please look some lines above for the dynamic query
531                 while (list($menu, $title) = SQL_FETCHROW($result)) {
532                         $OUT .= "  <option value=\"".$menu."\"";
533                         if ((!empty($default)) && ($default == $menu)) $OUT .= ' selected="selected"';
534                         $OUT .= ">".$title."</option>\n";
535                 } // END - while
536
537                 // Free memory
538                 SQL_FREERESULT($result);
539                 $OUT .= "</select>\n";
540         } else {
541                 // No menus???
542                 $OUT = getMessage('ADMIN_PROBLEM_NO_MENU');
543         }
544
545         // Return output
546         return $OUT;
547 }
548
549 // Wrapper for $_POST and ADMIN_SAVE_SETTINGS
550 function ADMIN_SAVE_SETTINGS_POST () {
551         // Get the array
552         $POST = REQUEST_POST_ARRAY();
553
554         // Call the lower function
555         ADMIN_SAVE_SETTINGS($POST);
556 }
557
558 // Save settings to the database
559 function ADMIN_SAVE_SETTINGS (&$POST, $tableName = "_config", $whereStatement = "config=0", $translateComma = array(), $alwaysAdd = false) {
560         // Prepare all arrays, variables
561         $DATA = array();
562         $skip = false;
563
564         // Now, walk through all entries and prepare them for saving
565         foreach ($POST as $id => $val) {
566                 // Process only formular field but not submit buttons ;)
567                 if ($id != "ok") {
568                         // Do not save the ok value
569                         convertSelectionsToTimestamp($POST, $DATA, $id, $skip);
570
571                         // Shall we process this ID? It muss not be empty, of course
572                         if ((!$skip) && (!empty($id))) {
573                                 // Save this entry
574                                 $val = COMPILE_CODE($val);
575
576                                 // Translate the value? (comma to dot!)
577                                 if ((is_array($translateComma)) && (in_array($id, $translateComma))) {
578                                         // Then do it here... :)
579                                         $val = convertCommaToDot($val);
580                                 } // END - if
581
582                                 // Shall we add numbers or strings?
583                                 $test = (float)$val;
584                                 if ("".$val."" == ''.$test."") {
585                                         // Add numbers
586                                         $DATA[] = sprintf("`%s`=%s", $id, $test);
587                                 } else {
588                                         // Add strings
589                                         $DATA[] = sprintf("`%s`='%s'", $id, trim($val));
590                                 }
591
592                                 // Update current configuration
593                                 setConfigEntry($id, $val);
594                         } // END - if
595                 } // END - if
596         } // END - foreach
597
598         // Check if entry does exist
599         $result = false;
600         if (!$alwaysAdd) {
601                 if (!empty($whereStatement)) {
602                         $result = SQL_QUERY("SELECT * FROM `{!_MYSQL_PREFIX!}".$tableName."` WHERE ".$whereStatement." LIMIT 1", __FUNCTION__, __LINE__);
603                 } else {
604                         $result = SQL_QUERY("SELECT * FROM `{!_MYSQL_PREFIX!}".$tableName."` LIMIT 1", __FUNCTION__, __LINE__);
605                 }
606         } // END - if
607
608         if (SQL_NUMROWS($result) == 1) {
609                 // "Implode" all data to single string
610                 $DATA_UPDATE = implode(", ", $DATA);
611
612                 // Generate SQL string
613                 $sql = sprintf("UPDATE `{!_MYSQL_PREFIX!}%s` SET %s WHERE %s LIMIT 1",
614                 $tableName,
615                 $DATA_UPDATE,
616                 $whereStatement
617                 );
618         } else {
619                 // Add Line (does only work with auto_increment!
620                 $KEYs = array(); $values = array();
621                 foreach ($DATA as $entry) {
622                         // Split up
623                         $line = explode('=', $entry);
624                         $KEYs[] = $line[0]; $values[] = $line[1];
625                 } // END - foreach
626
627                 // Add both in one line
628                 $KEYs = implode(", ", $KEYs);
629                 $values = implode(", ", $values);
630
631                 // Generate SQL string
632                 $sql = sprintf("INSERT INTO {!_MYSQL_PREFIX!}%s (%s) VALUES (%s)",
633                 $tableName,
634                 $KEYs,
635                 $values
636                 );
637         }
638
639         // Free memory
640         SQL_FREERESULT($result);
641
642         // Simply run generated SQL string
643         SQL_QUERY($sql, __FUNCTION__, __LINE__);
644
645         // Rebuild cache
646         rebuildCacheFiles("config", "config");
647
648         // Settings saved
649         LOAD_TEMPLATE('admin_settings_saved', false, getMessage('SETTINGS_SAVED'));
650 }
651
652 // Generate a selection box
653 function ADMIN_MAKE_MENU_SELECTION ($menu, $type, $name, $default = '') {
654         // Open the requested menu directory
655         $menuArray = getArrayFromDirectory(sprintf("inc/modules/%s/", $menu), '', false, false);
656
657         // Init the selection box
658         $OUT = "<select name=\"".$name."\" class=\"admin_select\" size=\"1\">
659         <option value=\"\">{--IS_TOP_MENU--}</option>\n";
660
661         // Walk through all files
662         foreach ($menuArray as $file) {
663                 // Is this a PHP script?
664                 if ((!isDirectory($file)) && (strpos($file, "".$type.'-') > -1) && (strpos($file, '.php') > 0)) {
665                         // Then test if the file is readable
666                         $test = sprintf("%sinc/modules/%s/%s", constant('PATH'), $menu, $file);
667
668                         // Is the file there?
669                         if (isFileReadable($test)) {
670                                 // Extract the value for what=xxx
671                                 $part = substr($file, (strlen($type) + 1));
672                                 $part = substr($part, 0, -4);
673
674                                 // Is that part different from the overview?
675                                 if ($part != "overview") {
676                                         $OUT .= "       <option value=\"".$part."\"";
677                                         if ($part == $default) $OUT .= ' selected="selected"';
678                                         $OUT .= ">".$part."</option>\n";
679                                 } // END - if
680                         } // END - if
681                 } // END - if
682         } // END - foreach
683
684         // Close selection box
685         $OUT .= "</select>\n";
686
687         // Return contents
688         return $OUT;
689 }
690
691 // Creates a user-profile link for the admin. This function can also be used for many other purposes
692 function generateUserProfileLink ($uid, $title = '', $wht="list_user") {
693         if (($title == '') && ($title != '0')) {
694                 // Set userid as title
695                 $title = $uid;
696         } // END - if
697
698         if (($title == '0') && ($wht == "list_refs")) {
699                 // Return title again
700                 return $title;
701         } // END - if
702
703         //* DEBUG: */ echo "a:".$title."<br />";
704         // Return link
705         return "<a href=\"{!URL!}/modules.php?module=admin&amp;what=".$wht."&amp;uid=".$uid."\" title=\"{--ADMIN_USER_PROFILE_TITLE--}\">".$title."</a>";
706 }
707
708 // Check "logical-area-mode"
709 function ADMIN_CHECK_MENU_MODE () {
710         // Set the global mode as the mode for all admins
711         $mode = getConfig('admin_menu');
712         $ADMIN = $mode;
713
714         // Get admin id
715         $aid = getCurrentAdminId();
716
717         // Check individual settings of current admin
718         if (isset($GLOBALS['cache_array']['admins']['la_mode'][$aid])) {
719                 // Load from cache
720                 $ADMIN = $GLOBALS['cache_array']['admins']['la_mode'][$aid];
721                 incrementConfigEntry('cache_hits');
722         } elseif (GET_EXT_VERSION('admins') >= '0.6.7') {
723                 // Load from database when version of 'admins' is enough
724                 $result = SQL_QUERY_ESC("SELECT la_mode FROM `{!_MYSQL_PREFIX!}_admins` WHERE `id`=%s LIMIT 1",
725                 array($aid), __FUNCTION__, __LINE__);
726                 if (SQL_NUMROWS($result) == 1) {
727                         // Load data
728                         list($ADMIN) = SQL_FETCHROW($result);
729                 }
730
731                 // Free memory
732                 SQL_FREERESULT($result);
733         }
734
735         // Check what the admin wants and set it when it's not the global mode
736         if ($ADMIN != "global") $mode = $ADMIN;
737
738         // Return admin-menu's mode
739         return $mode;
740 }
741
742 // Change activation status
743 function ADMIN_CHANGE_ACTIVATION_STATUS ($IDs, $table, $row, $idRow = 'id') {
744         $cnt = 0; $newStatus = 'Y';
745         if ((is_array($IDs)) && (count($IDs) > 0)) {
746                 // "Walk" all through and count them
747                 foreach ($IDs as $id => $selected) {
748                         // Secure the ID number
749                         $id = bigintval($id);
750
751                         // Should always be set... ;-)
752                         if (!empty($selected)) {
753                                 // Determine new status
754                                 $result = SQL_QUERY_ESC("SELECT %s FROM `{!_MYSQL_PREFIX!}_%s` WHERE %s=%s LIMIT 1",
755                                 array($row, $table, $idRow, $id), __FUNCTION__, __LINE__);
756
757                                 // Row found?
758                                 if (SQL_NUMROWS($result) == 1) {
759                                         // Load the status
760                                         list($currStatus) = SQL_FETCHROW($result);
761
762                                         // And switch it N<->Y
763                                         if ($currStatus == 'Y') $newStatus = 'N'; else $newStatus = 'Y';
764
765                                         // Change this status
766                                         SQL_QUERY_ESC("UPDATE `{!_MYSQL_PREFIX!}_%s` SET %s='%s' WHERE %s=%s LIMIT 1",
767                                         array($table, $row, $newStatus, $idRow, $id), __FUNCTION__, __LINE__);
768
769                                         // Count up affected rows
770                                         $cnt += SQL_AFFECTEDROWS();
771                                 } // END - if
772
773                                 // Free the result
774                                 SQL_FREERESULT($result);
775                         } // END - if
776                 } // END - foreach
777
778                 // Output status
779                 LOAD_TEMPLATE('admin_settings_saved', false, sprintf(getMessage('ADMIN_STATUS_CHANGED'), $cnt, count($IDs)));
780         } else {
781                 // Nothing selected!
782                 LOAD_TEMPLATE('admin_settings_saved', false, getMessage('ADMIN_NOTHING_SELECTED_CHANGE'));
783         }
784 }
785
786 // Send mails for del/edit/lock build modes
787 function ADMIN_SEND_BUILD_MAILS ($mode, $table, $content, $id, $subjectPart = '') {
788         // Default subject is the subject part
789         $subject = $subjectPart;
790
791         // Is the subject part not set?
792         if (empty($subjectPart)) {
793                 // Then use it from the mode
794                 $subject = strtoupper($mode);
795         } // END - if
796
797         // Is the raw userid set?
798         if (REQUEST_POST('uid_raw', $id) > 0) {
799                 // Generate subject
800                 $subjectLine = getMessage('MEMBER_'.strtoupper($subject).'_'.strtoupper($table).'_SUBJECT');
801
802                 // Load email template
803                 if (!empty($subjectPart)) {
804                         $mail = LOAD_EMAIL_TEMPLATE("member_".$mode."_".strtolower($subjectPart)."_".$table, $content);
805                 } else {
806                         $mail = LOAD_EMAIL_TEMPLATE("member_".$mode."_".$table, $content);
807                 }
808
809                 // Send email out
810                 sendEmail(REQUEST_POST('uid_raw', $id), $subjectLine, $mail);
811         } // END - if
812
813         // Generate subject
814         $subjectLine = getMessage('ADMIN_'.strtoupper($subject).'_'.strtoupper($table).'_SUBJECT');
815
816         // Send admin notification out
817         if (!empty($subjectPart)) {
818                 sendAdminNotification($subjectLine, "admin_".$mode."_".strtolower($subjectPart)."_".$table, $content, REQUEST_POST('uid_raw', $id));
819         } else {
820                 sendAdminNotification($subjectLine, "admin_".$mode."_".$table, $content, REQUEST_POST('uid_raw', $id));
821         }
822 }
823
824 // Build a special template list
825 function ADMIN_BUILD_LIST ($listType, $IDs, $table, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn) {
826         $OUT = ''; $SW = 2;
827
828         // "Walk" through all entries
829         foreach ($IDs as $id => $selected) {
830                 // Secure ID number
831                 $id = bigintval($id);
832
833                 // Get result from a given column array and table name
834                 $result = SQL_RESULT_FROM_ARRAY($table, $columns, $idColumn, $id, __FUNCTION__, __LINE__);
835
836                 // Is there one entry?
837                 if (SQL_NUMROWS($result) == 1) {
838                         // Load all data
839                         $content = SQL_FETCHARRAY($result);
840
841                         // Filter all data
842                         foreach ($content as $key => $value) {
843                                 // Search index
844                                 $idx = array_search($key, $columns, true);
845
846                                 // Do we have a userid?
847                                 if ($key == 'userid') {
848                                         // Add it again as raw id
849                                         $content['uid'] = bigintval($value);
850                                 } // END - if
851
852                                 // Handle the call in external function
853                                 $content[$key] = handleExtraValues($filterFunctions[$idx], $value, $extraValues[$idx]);
854                         } // END - foreach
855
856                         // Add color switching
857                         $content['sw'] = $SW;
858
859                         // Then list it
860                         $OUT .= LOAD_TEMPLATE(sprintf("admin_%s_%s_row",
861                         $listType,
862                         $table
863                         ), true, $content
864                         );
865
866                         // Switch color
867                         $SW = 3 - $SW;
868                 } // END - if
869
870                 // Free the result
871                 SQL_FREERESULT($result);
872         } // END - foreach
873
874         // Load master template
875         LOAD_TEMPLATE(sprintf("admin_%s_%s",
876         $listType,
877         $table
878         ), false, $OUT
879         );
880 }
881
882 // Change status of "build" list
883 function ADMIN_BUILD_STATUS_HANDLER ($mode, $IDs, $table, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn, $statusArray) {
884         // All valid entries? (We hope so here!)
885         if ((is_array($IDs)) && (count($IDs) > 0) && (count($columns) == count($filterFunctions)) && (count($columns) == count($extraValues)) && (count($statusArray) > 0)) {
886                 // "Walk" through all entries
887                 foreach ($IDs as $id => $sel) {
888                         // Construct SQL query
889                         $sql = sprintf("UPDATE `{!_MYSQL_PREFIX!}_%s` SET",
890                         SQL_ESCAPE($table)
891                         );
892
893                         // Load data of entry
894                         $result = SQL_QUERY_ESC("SELECT * FROM `{!_MYSQL_PREFIX!}_%s` WHERE %s=%s LIMIT 1",
895                         array($table, $idColumn, $id), __FUNCTION__, __LINE__);
896
897                         // Fetch the data
898                         $content = SQL_FETCHARRAY($result);
899
900                         // Free the result
901                         SQL_FREERESULT($result);
902
903                         // Add all status entries (e.g. status column last_updated or so)
904                         $newStatus = "UNKNOWN";
905                         $oldStatus = "UNKNOWN";
906                         $statusColumn = "unknown";
907                         foreach ($statusArray as $column => $statusInfo) {
908                                 // Does the entry exist?
909                                 if ((isset($content[$column])) && (isset($statusInfo[$content[$column]]))) {
910                                         // Add these entries for update
911                                         $sql .= sprintf(" %s='%s',", SQL_ESCAPE($column), SQL_ESCAPE($statusInfo[$content[$column]]));
912
913                                         // Remember status
914                                         if ($statusColumn == "unknown") {
915                                                 // Always (!!!) change status column first!
916                                                 $oldStatus = $content[$column];
917                                                 $newStatus = $statusInfo[$oldStatus];
918                                                 $statusColumn = $column;
919                                         } // END - if
920                                 } elseif (isset($content[$column])) {
921                                         // Unfinished!
922                                         app_die(__FUNCTION__, __LINE__, ":UNFINISHED: id={$id}/{$column}[".gettype($statusInfo)."] = {$content[$column]}");
923                                 }
924                         } // END - foreach
925
926                         // Add other columns as well
927                         foreach (REQUEST_POST_ARRAY() as $key => $entries) {
928                                 // Skip id, raw userid and 'do_$mode'
929                                 if (!in_array($key, array($idColumn, 'uid_raw', ('do_'.$mode)))) {
930                                         // Are there brackets () at the end?
931                                         if (substr($entries[$id], -2, 2) == "()") {
932                                                 // Direct SQL command found
933                                                 $sql .= sprintf(" %s=%s,", SQL_ESCAPE($key), SQL_ESCAPE($entries[$id]));
934                                         } else {
935                                                 // Add regular entry
936                                                 $sql .= sprintf(" %s='%s',", SQL_ESCAPE($key), SQL_ESCAPE($entries[$id]));
937
938                                                 // Add entry
939                                                 $content[$key] = $entries[$id];
940                                         }
941                                 } // END - if
942                         } // END - foreach
943
944                         // Finish SQL statement
945                         $sql = substr($sql, 0, -1) . sprintf(" WHERE `%s`=%s AND `%s`='%s' LIMIT 1",
946                         $idColumn,
947                         bigintval($id),
948                         $statusColumn,
949                         $oldStatus
950                         );
951
952                         // Run the SQL
953                         SQL_QUERY($sql, __FUNCTION__, __LINE__);
954
955                         // Do we have an URL?
956                         if (isset($content['url'])) {
957                                 // Then add a framekiller test as well
958                                 $content['frametester'] = FRAMETESTER($content['url']);
959                         } // END - if
960
961                         // Send "build mails" out
962                         ADMIN_SEND_BUILD_MAILS($mode, $table, $content, $id, $statusInfo[$content[$column]]);
963                 } // END - foreach
964         } // END - if
965 }
966
967 // Delete rows by given ID numbers
968 function ADMIN_DELETE_ENTRIES_CONFIRM ($IDs, $table, $columns=array(), $filterFunctions=array(), $extraValues=array(), $deleteNow=false, $idColumn='id', $userIdColumn='userid') {
969         // All valid entries? (We hope so here!)
970         if ((is_array($IDs)) && (count($IDs) > 0) && (count($columns) == count($filterFunctions)) && (count($columns) == count($extraValues))) {
971                 // Shall we delete here or list for deletion?
972                 if ($deleteNow) {
973                         // The base SQL command:
974                         $sql = "DELETE LOW_PRIORITY FROM `{!_MYSQL_PREFIX!}_%s` WHERE %s IN (%s)";
975
976                         // Delete them all
977                         $idList = '';
978                         foreach ($IDs as $id => $sel) {
979                                 // Is there a userid?
980                                 if (REQUEST_ISSET_POST('uid_raw', $id)) {
981                                         // Load all data from that id
982                                         $result = SQL_QUERY_ESC("SELECT * FROM `{!_MYSQL_PREFIX!}_%s` WHERE %s=%s LIMIT 1",
983                                         array($table, $idColumn, $id), __FUNCTION__, __LINE__);
984
985                                         // Fetch the data
986                                         $content = SQL_FETCHARRAY($result);
987
988                                         // Free the result
989                                         SQL_FREERESULT($result);
990
991                                         // Send "build mails" out
992                                         ADMIN_SEND_BUILD_MAILS('del', $table, $content, $id);
993                                 } // END - if
994
995                                 // Add id number
996                                 $idList .= $id . ',';
997                         } // END - foreach
998
999                         // Run the query
1000                         SQL_QUERY($sql, array($table, $idColumn, substr($idList, 0, -1)), __FUNCTION__, __LINE__);
1001
1002                         // Was this fine?
1003                         if (SQL_AFFECTEDROWS() == count($IDs)) {
1004                                 // All deleted
1005                                 LOAD_TEMPLATE('admin_settings_saved', false, getMessage('ADMIN_ALL_ENTRIES_REMOVED'));
1006                         } else {
1007                                 // Some are still there :(
1008                                 LOAD_TEMPLATE('admin_settings_saved', false, sprintf(getMessage('ADMIN_SOME_ENTRIES_NOT_DELETED'), SQL_AFFECTEDROWS(), count($IDs)));
1009                         }
1010                 } else {
1011                         // List for deletion confirmation
1012                         ADMIN_BUILD_LIST('del', $IDs, $table, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn);
1013                 }
1014         } // END - if
1015 }
1016
1017 // Edit rows by given ID numbers
1018 function ADMIN_EDIT_ENTRIES_CONFIRM ($IDs, $table, $columns=array(), $filterFunctions=array(), $extraValues=array(), $editNow=false, $idColumn='id', $userIdColumn='userid') {
1019         // All valid entries? (We hope so here!)
1020         if ((is_array($IDs)) && (count($IDs) > 0) && (count($columns) == count($filterFunctions)) && (count($columns) == count($extraValues))) {
1021                 // Shall we change here or list for editing?
1022                 if ($editNow) {
1023                         // Change them all
1024                         $affected = 0;
1025                         foreach ($IDs as $id => $sel) {
1026                                 // Prepare content array (new values)
1027                                 $content = array();
1028
1029                                 // Prepare SQL for this row
1030                                 $sql = sprintf("UPDATE `{!_MYSQL_PREFIX!}_ SET",
1031                                 SQL_ESCAPE($table)
1032                                 );
1033                                 foreach (REQUEST_POST_ARRAY() as $key => $entries) {
1034                                         // Skip raw userid which is always invalid
1035                                         if ($key == "uid_raw") {
1036                                                 // Continue with next field
1037                                                 continue;
1038                                         } // END - if
1039
1040                                         // Is entries an array?
1041                                         if (($key != $idColumn) && (is_array($entries)) && (isset($entries[$id]))) {
1042                                                 // Add this entry to content
1043                                                 $content[$key] = $entries[$id];
1044
1045                                                 // Send data through the filter function if found
1046                                                 if ((isset($filterFunctions[$key])) && (isset($extraValues[$key]))) {
1047                                                         // Filter function set!
1048                                                         $entries[$id] = handleExtraValues($filterFunctions[$key], $entries[$id], $extraValues[$key]);
1049                                                 } // END - if
1050
1051                                                 // Then add this value
1052                                                 $sql .= sprintf(" %s='%s',",
1053                                                 SQL_ESCAPE($key),
1054                                                 SQL_ESCAPE($entries[$id])
1055                                                 );
1056                                         } elseif (($key != $idColumn) && (!is_array($entries))) {
1057                                                 // Add normal entries as well!
1058                                                 $content[$key] =  $entries;
1059                                         }
1060
1061                                         // Do we have an URL?
1062                                         if ($key == "url") {
1063                                                 // Then add a framekiller test as well
1064                                                 $content['frametester'] = FRAMETESTER($content[$key]);
1065                                         } // END - if
1066                                 } // END - foreach
1067
1068                                 // Finish SQL command
1069                                 $sql = substr($sql, 0, -1) . " WHERE `".$idColumn."`=".bigintval($id)." LIMIT 1";
1070
1071                                 // Run this query
1072                                 SQL_QUERY($sql, __FUNCTION__, __LINE__);
1073
1074                                 // Add affected rows
1075                                 $affected += SQL_AFFECTEDROWS();
1076
1077                                 // Load all data from that id
1078                                 $result = SQL_QUERY_ESC("SELECT * FROM `{!_MYSQL_PREFIX!}_%s` WHERE `%s`=%s LIMIT 1",
1079                                 array($table, $idColumn, $id), __FUNCTION__, __LINE__);
1080
1081                                 // Fetch the data
1082                                 global $DATA;
1083                                 $DATA = SQL_FETCHARRAY($result);
1084
1085                                 // Free the result
1086                                 SQL_FREERESULT($result);
1087
1088                                 // Send "build mails" out
1089                                 ADMIN_SEND_BUILD_MAILS('edit', $table, $content, $id);
1090                         } // END - foreach
1091
1092                         // Was this fine?
1093                         if ($affected == count($IDs)) {
1094                                 // All deleted
1095                                 LOAD_TEMPLATE('admin_settings_saved', false, getMessage('ADMIN_ALL_ENTRIES_EDITED'));
1096                         } else {
1097                                 // Some are still there :(
1098                                 LOAD_TEMPLATE('admin_settings_saved', false, sprintf(getMessage('ADMIN_SOME_ENTRIES_NOT_EDITED'), $affected, count($IDs)));
1099                         }
1100                 } else {
1101                         // List for editing
1102                         ADMIN_BUILD_LIST('edit', $IDs, $table, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn);
1103                 }
1104         } // END - if
1105 }
1106
1107 // Un-/lock rows by given ID numbers
1108 function ADMIN_LOCK_ENTRIES_CONFIRM ($IDs, $table, $columns=array(), $filterFunctions=array(), $extraValues=array(), $statusArray=array(), $lockNow=false, $idColumn='id', $userIdColumn='userid') {
1109         // All valid entries? (We hope so here!)
1110         if ((is_array($IDs)) && (count($IDs) > 0) && (count($columns) == count($filterFunctions)) && (count($columns) == count($extraValues)) && ((!$lockNow) || (count($statusArray) == 1))) {
1111                 // Shall we un-/lock here or list for locking?
1112                 if ($lockNow) {
1113                         // Un-/lock entries
1114                         ADMIN_BUILD_STATUS_HANDLER("lock", $IDs, $table, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn, $statusArray);
1115                 } else {
1116                         // List for editing
1117                         ADMIN_BUILD_LIST("lock", $IDs, $table, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn);
1118                 }
1119         } // END - if
1120 }
1121
1122 // Undelete rows by given ID numbers
1123 function ADMIN_UNDELETE_ENTRIES_CONFIRM ($IDs, $table, $columns=array(), $filterFunctions=array(), $extraValues=array(), $statusArray=array(), $lockNow=false, $idColumn='id', $userIdColumn='userid') {
1124         // All valid entries? (We hope so here!)
1125         if ((is_array($IDs)) && (count($IDs) > 0) && (count($columns) == count($filterFunctions)) && (count($columns) == count($extraValues)) && ((!$lockNow) || (count($statusArray) == 1))) {
1126                 // Shall we un-/lock here or list for locking?
1127                 if ($lockNow) {
1128                         // Undelete entries
1129                         ADMIN_BUILD_STATUS_HANDLER("undelete", $IDs, $table, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn, $statusArray);
1130                 } else {
1131                         // List for editing
1132                         ADMIN_BUILD_LIST("undelete", $IDs, $table, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn);
1133                 }
1134         } // END - if
1135 }
1136
1137 // Checks proxy settins by fetching check-updates3.php from www.mxchange.org
1138 function ADMIN_TEST_PROXY_SETTINGS ($settingsArray) {
1139         // Set temporary the new settings
1140         mergeConfig($settingsArray);
1141
1142         // Now get the test URL
1143         $content = sendGetRequest('check-updates3.php');
1144
1145         // Is the first line with "200 OK"?
1146         $valid = (strpos($content[0], '200 OK') !== false);
1147
1148         // Return result
1149         return $valid;
1150 }
1151
1152 // Sends out a link to the given email adress so the admin can reset his/her password
1153 function ADMIN_SEND_PASSWORD_RESET_LINK ($email) {
1154         // Init output
1155         $OUT = '';
1156
1157         // Compile out security characters (must be for looking up!)
1158         $email = COMPILE_CODE($email);
1159
1160         // Look up administator login
1161         $result = SQL_QUERY_ESC("SELECT id, login, password FROM `{!_MYSQL_PREFIX!}_admins` WHERE email='%s' LIMIT 1",
1162         array($email), __FUNCTION__, __LINE__);
1163
1164         // Is there an account?
1165         if (SQL_NUMROWS($result) == 0) {
1166                 // No account found!
1167                 return getMessage('ADMIN_NO_LOGIN_WITH_EMAIL');
1168         } // END - if
1169
1170         // Load all data
1171         $content = SQL_FETCHARRAY($result);
1172
1173         // Free result
1174         SQL_FREERESULT($result);
1175
1176         // Generate hash for reset link
1177         $content['hash'] = generateHash(URL.':'.$content['id'].':'.$content['login'].':'.$content['password'], substr($content['password'], 10));
1178
1179         // Remove some data
1180         unset($content['id']);
1181         unset($content['password']);
1182
1183         // Prepare email
1184         $mailText = LOAD_EMAIL_TEMPLATE("admin_reset_password", $content);
1185
1186         // Send it out
1187         sendEmail($email, getMessage('ADMIN_RESET_PASS_LINK_SUBJ'), $mailText);
1188
1189         // Prepare output
1190         return getMessage('ADMIN_RESET_LINK_SENT');
1191 }
1192
1193 // Validate hash and login for password reset
1194 function ADMIN_VALIDATE_RESET_LINK_HASH_LOGIN ($hash, $login) {
1195         // By default nothing validates... ;)
1196         $valid = false;
1197
1198         // Compile the login for lookup
1199         $login = COMPILE_CODE($login);
1200
1201         // Then try to find that user
1202         $result = SQL_QUERY_ESC("SELECT id, password, email FROM `{!_MYSQL_PREFIX!}_admins` WHERE login='%s' LIMIT 1",
1203         array($login), __FUNCTION__, __LINE__);
1204
1205         // Is an account here?
1206         if (SQL_NUMROWS($result) == 1) {
1207                 // Load all data
1208                 $content = SQL_FETCHARRAY($result);
1209
1210                 // Generate hash again
1211                 $hashFromData = generateHash(URL.':'.$content['id'].':'.$login.':'.$content['password'], substr($content['password'], 10));
1212
1213                 // Does both match?
1214                 $valid = ($hash == $hashFromData);
1215         } // END - if
1216
1217         // Free result
1218         SQL_FREERESULT($result);
1219
1220         // Return result
1221         return $valid;
1222 }
1223
1224 // Reset the password for the login. Do NOT call this function without calling above function first!
1225 function ADMIN_RESET_PASSWORD ($login, $password) {
1226         // Init hash
1227         $passHash = '';
1228
1229         // Now check if we have sql_patches installed
1230         if (GET_EXT_VERSION('sql_patches') >= '0.3.6') {
1231                 // Use new way of hashing
1232                 $passHash = generateHash($password);
1233         } else {
1234                 // Old MD5 method
1235                 $passHash = md5($password);
1236         }
1237
1238         // Update database
1239         SQL_QUERY_ESC("UPDATE `{!_MYSQL_PREFIX!}_admins` SET password='%s' WHERE login='%s' LIMIT 1",
1240         array($passHash, $login), __FUNCTION__, __LINE__);
1241
1242         // Run filters
1243         runFilterChain('post_admin_reset_pass', array('login' => $login, 'hash' => $passHash));
1244
1245         // Return output
1246         return ADMIN_PASSWORD_RESET_DONE;
1247 }
1248
1249 // Solves a task by given id number
1250 function ADMIN_SOLVE_TASK ($id) {
1251         // Update the task data
1252         ADMIN_UPDATE_TASK_DATA($id, 'status', "SOLVED");
1253 }
1254
1255 // Marks a given task as deleted
1256 function ADMIN_DELETE_TASK ($id) {
1257         // Update the task data
1258         ADMIN_UPDATE_TASK_DATA($id, 'status', "DELETED");
1259 }
1260
1261 // Function to update task data
1262 function ADMIN_UPDATE_TASK_DATA ($id, $row, $data) {
1263         // Is the id not set, then we need a backtrace here... :(
1264         if ($id <= 0) {
1265                 // Initiate backtrace
1266                 debug_report_bug(sprintf("id is invalid: %s. row=%s, data=%s",
1267                 $id,
1268                 $row,
1269                 $data
1270                 ));
1271         } // END - if
1272
1273         // Update the task
1274         SQL_QUERY_ESC("UPDATE `{!_MYSQL_PREFIX!}_task_system` SET %s='%s' WHERE `id`=%s LIMIT 1",
1275         array($row, $data, bigintval($id)), __FUNCTION__, __LINE__);
1276 }
1277
1278 // Checks wether if the admin menu has entries
1279 function ifAdminMenuHasEntries ($action) {
1280         return (
1281         ((
1282         isset($GLOBALS['admin_menu_has_entries'][$action])
1283         ) && (
1284         $GLOBALS['admin_menu_has_entries'][$action] === true
1285         )) || (
1286         $action == "login"
1287         )
1288         );
1289 }
1290
1291 // Setter for 'admin_menu_has_entries'
1292 function setAdminMenuHasEntries ($action, $hasEntries) {
1293         $GLOBALS['admin_menu_has_entries'][$action] = (bool) $hasEntries;
1294 }
1295
1296 // Creates a link to the user's admin-profile
1297 function ADMIN_CREATE_USERID_LINK ($uid) {
1298         // Is the userid set correctly?
1299         if ($uid > 0) {
1300                 // Create a link to that profile
1301                 return "{!URL!}/modules.php?module=admin&amp;what=list_user&amp;uid=".bigintval($uid);
1302         } // END - if
1303
1304         // Return a link to the user list
1305         return "{!URL!}/modules.php?module=admin&amp;what=list_user";
1306 }
1307
1308 //
1309 ?>