314642ed0c89fecd759ec12e6abcc445160892c1
[mailer.git] / inc / mysql-manager.php
1 <?php
2 /************************************************************************
3  * Mailer v0.2.1-FINAL                                Start: 08/26/2003 *
4  * ===================                          Last change: 11/29/2004 *
5  *                                                                      *
6  * -------------------------------------------------------------------- *
7  * File              : mysql-manager.php                                *
8  * -------------------------------------------------------------------- *
9  * Short description : All database-related functions                   *
10  * -------------------------------------------------------------------- *
11  * Kurzbeschreibung  : Alle datenbank-relevanten Funktionen             *
12  * -------------------------------------------------------------------- *
13  * Copyright (c) 2003 - 2009 by Roland Haeder                           *
14  * Copyright (c) 2009 - 2015 by Mailer Developer Team                   *
15  * For more information visit: http://mxchange.org                      *
16  *                                                                      *
17  * This program is free software; you can redistribute it and/or modify *
18  * it under the terms of the GNU General Public License as published by *
19  * the Free Software Foundation; either version 2 of the License, or    *
20  * (at your option) any later version.                                  *
21  *                                                                      *
22  * This program is distributed in the hope that it will be useful,      *
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
25  * GNU General Public License for more details.                         *
26  *                                                                      *
27  * You should have received a copy of the GNU General Public License    *
28  * along with this program; if not, write to the Free Software          *
29  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,               *
30  * MA  02110-1301  USA                                                  *
31  ************************************************************************/
32
33 // Some security stuff...
34 if (!defined('__SECURITY')) {
35         die();
36 } // END - if
37
38 // "Getter" for module description
39 // @TODO Can we cache this?
40 function getTitleFromMenu ($mode, $what, $column = 'what', $ADD = '') {
41         // Debug message
42         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'mode=' . $mode . ',what=' . $what . ',column=' . $column . ',add=' . $ADD);
43
44         // Fix empty 'what'
45         if (empty($what)) {
46                 $what = getIndexHome();
47         } elseif ((isGetRequestElementSet('action')) && ($column == 'what')) {
48                 // Get it from action
49                 return getTitleFromMenu($mode, getAction(), 'action', $ADD);
50         } elseif ($what == 'welcome') {
51                 // Overview page
52                 return '{--WHAT_IS_WELCOME--}';
53         }
54
55         // Default is not found
56         $data['title'] = '??? (' . $what . ')';
57
58         // Look for title
59         $result = sqlQueryEscaped("SELECT `title` FROM `{?_MYSQL_PREFIX?}_%s_menu` WHERE `%s`='%s'" . $ADD . " LIMIT 1",
60                 array(
61                         $mode,
62                         $column,
63                         $what
64                 ), __FUNCTION__, __LINE__);
65
66         // Is there an entry?
67         if (sqlNumRows($result) == 1) {
68                 // Fetch the title
69                 $data = sqlFetchArray($result);
70         } // END - if
71
72         // Free result
73         sqlFreeResult($result);
74
75         // Return it
76         return $data['title'];
77 }
78
79 // Add link into output stream (or return it) for 'You Are Here' navigation
80 function addYouAreHereLink ($accessLevel, $FQFN, $return = FALSE) {
81         // Use only filename of the FQFN...
82         $file = basename($FQFN);
83
84         // Init variables
85         $linkAdd = '';
86         $OUT = '';
87         $ADD = '';
88         $prefix = '';
89
90         // First we have to do some analysis...
91         if (substr($file, 0, 7) == 'action-') {
92                 // This is an action file!
93                 $type = 'action';
94                 $search = substr($file, 7);
95
96                 // Get access level from it
97                 $modCheck = getModuleFromFileName($file, $accessLevel);
98
99                 // Add what
100                 $ADD = " AND (`what`='' OR `what` IS NULL)";
101         } elseif (substr($file, 0, 5) == 'what-') {
102                 // This is a 'what file'!
103                 $type = 'what';
104                 $search = substr($file, 5);
105
106                 // Get access level from it
107                 $modCheck = getModuleFromFileName($file, $accessLevel);
108
109                 // Is there admin? Then display all
110                 $ADD = " AND `visible`='Y' AND `locked`='N'";
111                 if (isAdmin()) {
112                         // Display all!
113                         $ADD = '';
114                 } // END - if
115
116                 $dummy = substr($search, 0, -4);
117                 $ADD .= sprintf(" AND `action`='%s'", getActionFromModuleWhat($accessLevel, $dummy));
118         } elseif ($accessLevel == 'sponsor') {
119                 // Sponsor menu
120                 $type     = 'what';
121                 $search   = $file;
122                 $modCheck = getModule();
123         } else {
124                 // Other
125                 $type     = 'menu';
126                 $search   = $file;
127                 $modCheck = getModule();
128         }
129
130         // Begin the navigation line
131         if (!isset($GLOBALS['nav_depth'])) {
132                 // Init nav_depth
133                 $GLOBALS['nav_depth'] = '0';
134
135                 // Run the pre-filter chain
136                 $ret = runFilterChain('pre_youhere_line', array('access_level' => $accessLevel, 'type' => $type, 'search' => $search, 'prefix' => $prefix, 'link_add' => $linkAdd, 'content' => '', 'add' => $ADD));
137
138                 // Add pre-content
139                 $prefix = $ret['content'];
140
141                 // Add default content
142                 $prefix .= '<div class="you_are_here">{--YOU_ARE_HERE--}&nbsp;<strong><a class="you_are_here" href="{%url=modules.php?module=' . getModule() . $linkAdd . '%}">Home</a></strong>';
143         } elseif ($return === FALSE) {
144                 // Count depth
145                 $GLOBALS['nav_depth']++;
146         }
147
148         // Add arrow
149         $prefix .= '&nbsp;-&gt;&nbsp;';
150
151         // We need to remove .php and the end
152         if (substr($search, -4, 4) == '.php') {
153                 // Remove the .php
154                 $search = substr($search, 0, -4);
155         } // END - if
156
157         // Is ext-sql_patches installed?
158         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'isExtensionInstalledAndNewer()=' . intval(isExtensionInstalledAndNewer('sql_patches', '0.2.3')) . ',youre_here=' . getYoureHere() . ',isAdmin()=' . intval(isAdmin()) . ',modCheck=' . $modCheck);
159         if (((isExtensionInstalledAndNewer('sql_patches', '0.2.3')) && (isYoureHereEnabled())) || ((isAdmin()) && ($modCheck == 'admin'))) {
160                 // Output HTML code
161                 $OUT = $prefix . '<strong><a class="you_are_here" href="{%url=modules.php?module=' . $modCheck . '&amp;' . $type . '=' . $search . $linkAdd . '%}">' . getTitleFromMenu($accessLevel, $search, $type, $ADD) . '</a></strong>';
162
163                 // Can we close the you-are-here navigation?
164                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'type=' . $type . ',getWhat()=' . getWhat() . ',accessLevel=' . $accessLevel . ',isWhatSet()=' . intval(isWhatSet()));
165                 if (($type == 'what') || (($type == 'action') && ((!isWhatSet()) || (($accessLevel == 'admin') && (getWhat() == 'welcome'))))) {
166                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'type=' . $type);
167                         // Add closing div and br-tag
168                         $GLOBALS['nav_depth'] = '0';
169
170                         // Run the post-filter chain
171                         $ret = runFilterChain('post_youhere_line', array('access_level' => $accessLevel, 'type' => $type, 'search' => $search, 'prefix' => $prefix, 'link_add' => $linkAdd, 'content' => $OUT, 'add' => $ADD));
172
173                         // Get content from filter back
174                         $OUT = $ret['content'];
175
176                         // Close div-tag, so not the filters have to do it
177                         $OUT .= '</div>';
178                 } // END - if
179         } // END - if
180
181         // Return or output HTML code?
182         if ($return === TRUE) {
183                 // Return HTML code
184                 return $OUT;
185         } else {
186                 // Output HTML code here
187                 outputHtml($OUT);
188         }
189 }
190
191 // Adds a menu (mode = guest/member/admin/sponsor) to output
192 function addMenu ($mode, $action, $what) {
193         // Init some variables
194         $main_cnt = '0';
195
196         // is the menu action valid?
197         if (!isMenuActionValid($mode, $action, $what, TRUE)) {
198                 return getCode('MENU_NOT_VALID');
199         } // END - if
200
201         // Non-admin shall not see all menus
202         $ADD = " AND `visible`='Y' AND `locked`='N'";
203         if (isAdmin()) {
204                 // Is admin, so make all visible
205                 $ADD = '';
206         } // END - if
207
208         // Load SQL data and add the menu to the output stream...
209         $result_main = sqlQueryEscaped("SELECT
210         `title`,
211         `what`,
212         `action`,
213         `visible`,
214         `locked`
215 FROM
216         `{?_MYSQL_PREFIX?}_%s_menu`
217 WHERE
218         (`what`='' OR `what` IS NULL)
219         ".$ADD."
220 ORDER BY
221         `sort` ASC",
222                 array($mode), __FUNCTION__, __LINE__);
223
224         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'main_cnt=' . $main_cnt . ',getWhat()=' . getWhat());
225         if (!ifSqlHasZeroNums($result_main)) {
226                 // There are menus available, so we simply display them... :)
227                 $GLOBALS['rows'] = '';
228                 while ($content = sqlFetchArray($result_main)) {
229                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'main_cnt=' . $main_cnt . ',action=' . $content['action'] . ',getWhat()=' . getWhat());
230                         // Disable the block-mode
231                         enableBlockMode(FALSE);
232
233                         // Load menu header template
234                         $GLOBALS['rows'] .= loadTemplate($mode . '_menu_title', TRUE, $content);
235
236                         // Sub menu
237                         $result_sub = sqlQueryEscaped("SELECT
238         `title` AS `sub_title`,
239         `what` AS `sub_what`,
240         `visible` AS `sub_visible`,
241         `locked` AS `sub_locked`
242 FROM
243         `{?_MYSQL_PREFIX?}_%s_menu`
244 WHERE
245         `action`='%s' AND
246         `what` != '' AND
247         `what` IS NOT NULL
248         " . $ADD . "
249 ORDER BY
250         `sort` ASC",
251                                 array(
252                                         $mode,
253                                         $content['action']
254                                 ), __FUNCTION__, __LINE__);
255
256                         // Are there some entries?
257                         if (!ifSqlHasZeroNums($result_sub)) {
258                                 // Init counter
259                                 $count = '0';
260
261                                 // Load all sub menus
262                                 while ($content2 = sqlFetchArray($result_sub)) {
263                                         // Merge both arrays in one
264                                         $content = merge_array($content, $content2);
265
266                                         // Init content
267                                         $OUT = '';
268
269                                         // Full file name for checking menu
270                                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'sub_what=' . $content['sub_what']);
271                                         $inc = sprintf('inc/modules/%s/what-%s.php', $mode, $content['sub_what']);
272                                         if (isIncludeReadable($inc)) {
273                                                 // Mark currently selected menu - open
274                                                 if ((!empty($what)) && (($what == $content['sub_what']))) {
275                                                         $OUT = '<strong>';
276                                                 } // END - if
277
278                                                 // Is ext-sql_patches up-to-date, and display_home_in_index is Y?
279                                                 if ((getModule() == 'index') && (isExtensionInstalledAndNewer('sql_patches', '0.8.3')) && (isDisplayHomeInIndexEnabled()) && ($content['sub_what'] == getIndexHome())) {
280                                                         // Use index.php as link
281                                                         $OUT .= '<a name="menu" class="menu_blur" href="{%url=index.php%}" target="_self">';
282                                                 } else {
283                                                         // Regular navigation link
284                                                         $OUT .= '<a name="menu" class="menu_blur" href="{%url=modules.php?module=' . getModule() . '&amp;what=' . $content['sub_what'] . '%}" target="_self">';
285                                                 }
286                                         } else {
287                                                 // Not found - open
288                                                 $OUT .= '<span class="bad" style="cursor:help" title="{%message,ADMIN_MENU_WHAT_404_TITLE=' . $content['sub_what'] . '%}">';
289                                         }
290
291                                         // Menu title
292                                         $OUT .= '{?menu_blur_spacer?}' . $content['sub_title'];
293
294                                         if (isIncludeReadable($inc)) {
295                                                 $OUT .= '</a>';
296
297                                                 // Mark currently selected menu - close
298                                                 if ((!empty($what)) && (($what == $content['sub_what']))) {
299                                                         $OUT .= '</strong>';
300                                                 } // END - if
301                                         } else {
302                                                 // Not found - close
303                                                 $OUT .= '</span>';
304                                         }
305
306                                         // Cunt it up
307                                         $count++;
308
309                                         // Rewrite array
310                                         $content = array(
311                                                 'menu'    => $OUT,
312                                                 'what'    => $content['sub_what'],
313                                                 'visible' => $content['sub_visible'],
314                                                 'locked'  => $content['locked'],
315                                         );
316
317                                         // Add regular menu row or bottom row?
318                                         if ($count < sqlNumRows($result_sub)) {
319                                                 $GLOBALS['rows'] .= loadTemplate($mode . '_menu_row', TRUE, $content);
320                                         } else {
321                                                 $GLOBALS['rows'] .= loadTemplate($mode . '_menu_bottom', TRUE, $content);
322                                         }
323                                 } // END - while
324                         } else {
325                                 // This is a menu block... ;-)
326                                 enableBlockMode();
327
328                                 // Load menu block
329                                 $INC = sprintf('inc/modules/%s/action-%s.php', $mode, $content['action']);
330                                 if (isFileReadable($INC)) {
331                                         // Load include file
332                                         if ((!isExtensionActive($content['action'])) || ($content['action'] == 'online')) $GLOBALS['rows'] .= loadTemplate('menu_what_begin', TRUE, $mode);
333                                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'main_cnt=' . $main_cnt . ',action=' . $content['action'] . ',getWhat()=' . getWhat());
334                                         loadInclude($INC);
335                                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'main_cnt=' . $main_cnt . ',action=' . $content['action'] . ',getWhat()=' . getWhat());
336                                         if ((!isExtensionActive($content['action'])) || ($content['action'] == 'online')) $GLOBALS['rows'] .= loadTemplate('menu_what_end', TRUE, $mode);
337                                 }
338                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'main_cnt=' . $main_cnt . ',action=' . $content['action'] . ',getWhat()=' . getWhat());
339                         }
340
341                         // Free result
342                         sqlFreeResult($result_sub);
343
344                         // Count one up
345                         $main_cnt++;
346
347                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'main_cnt=' . $main_cnt . ',getWhat()=' . getWhat());
348                         if (sqlNumRows($result_main) > $main_cnt) {
349                                 // Add separator
350                                 $GLOBALS['rows'] .= loadTemplate('menu_separator', TRUE, $mode);
351
352                                 // Prepare filter data array
353                                 $filterData = array(
354                                         'output'    => '',
355                                         'exclusive' => FALSE,
356                                         'action'    => $action,
357                                         'mode'      => $mode,
358                                 );
359
360                                 // Run filter chain
361                                 $filterData = runFilterChain($mode . '_menu_advert', $filterData);
362
363                                 // Add content output
364                                 $GLOBALS['rows'] .= $filterData['output'];
365                         } // END - if
366                 } // END - while
367
368                 // Free memory
369                 sqlFreeResult($result_main);
370
371                 // Prepare filter data array
372                 $filterData = array(
373                         'output'    => '',
374                         'exclusive' => FALSE,
375                         'action'    => $action,
376                         'mode'      => $mode,
377                 );
378
379                 // Run filter chain
380                 $filterData = runFilterChain($mode . '_menu_advert_end', $filterData);
381
382                 // Add content output
383                 $GLOBALS['rows'] .= $filterData['output'];
384
385                 // Prepare data
386                 $content = array(
387                         'rows'      => $GLOBALS['rows'],
388                         'menu_mode' => $mode
389                 );
390
391                 // Load main template
392                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'main_cnt=' . $main_cnt . ',getWhat()=' . getWhat());
393                 loadTemplate('menu_table', FALSE, $content);
394         } // END - if
395 }
396
397 // Checks whether the current user is a member
398 function isMember () {
399         // By default no member
400         $ret = FALSE;
401
402         // Fix missing 'last_online' array, damn stupid code :(((
403         // @TODO Try to rewrite this to one or more functions
404         if ((!isset($GLOBALS['last_online'])) || (!is_array($GLOBALS['last_online']))) {
405                 $GLOBALS['last_online'] = array();
406         } // END - if
407
408         // Is the cache entry there?
409         if (isset($GLOBALS[__FUNCTION__])) {
410                 // Then return it
411                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'CACHED! (' . intval($GLOBALS[__FUNCTION__]) . ')');
412                 return $GLOBALS[__FUNCTION__];
413         } elseif ((!isSessionVariableSet('userid')) || (!isSessionVariableSet('u_hash'))) {
414                 // Destroy any existing user session data
415                 destroyMemberSession();
416                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'No member set in cookie/session.');
417
418                 // Abort further processing
419                 return FALSE;
420         }
421
422         // Get userid secured from session
423         setMemberId(getSession('userid'));
424
425         // ... and set it as currently handled user id
426         setCurrentUserId(getMemberId());
427
428         // Init user data array
429         initUserData();
430
431         // Fix "deleted" cookies
432         fixDeletedCookies(array('userid', 'u_hash'));
433
434         // Are cookies set and can the member data be loaded?
435         if ((isMemberIdSet()) && (isSessionVariableSet('u_hash')) && (fetchUserData(getMemberId()) === TRUE)) {
436                 // Validate password by created the difference of it and the secret key
437                 $valPass = encodeHashForCookie(getUserData('password'));
438
439                 // So did we now have valid data and an unlocked user?
440                 if ((getUserData('status') == 'CONFIRMED') && ($valPass == getSession('u_hash'))) {
441                         // Transfer last module and online time
442                         $GLOBALS['last_online']['module'] = getUserData(getUserLastWhatName());
443                         $GLOBALS['last_online']['online'] = getUserData('last_online');
444
445                         // Account is confirmed and all cookie data is valid so he is definely logged in! :-)
446                         $ret = TRUE;
447                 } // END - if
448         } // END - if
449
450         // Is $ret still false?
451         if ($ret === FALSE) {
452                 // Yes, so destroy the session
453                 destroyMemberSession();
454         } // END - if
455
456         // Cache status
457         $GLOBALS[__FUNCTION__] = $ret;
458
459         // Return status
460         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'ret=' . intval($ret));
461         return $ret;
462 }
463
464 // Fetch user data for given user id
465 function fetchUserData ($value, $column = 'userid') {
466         // Extension ext-user must be there at any case
467         if (!isExtensionActive('user')) {
468                 // Absent ext-user is really not good
469                 return FALSE;
470         } elseif (is_null($value)) {
471                 // This shall never happen, so please report it
472                 reportBug(__FUNCTION__, __LINE__, 'value=NULL,column=' . $column . ' - value can never be NULL');
473         }
474
475         // If we should look for userid secure&set it here
476         if (substr($column, -2, 2) == 'id') {
477                 // Secure userid
478                 $value = bigintval($value);
479
480                 // Don't look for invalid userids...
481                 if (!isValidId($value)) {
482                         // Invalid, so abort here
483                         reportBug(__FUNCTION__, __LINE__, 'User id ' . $value . ' is invalid.');
484                 } // END - if
485
486                 // Unset cached values if found and different
487                 if ((isCurrentUserIdSet()) && (getCurrentUserId() != $value)) {
488                         // Unset it
489                         unsetCurrentUserId();
490                 } elseif (isValidUserData()) {
491                         // Use cache, so it is fine
492                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $value . ' is valid, using cache #1');
493                         return TRUE;
494                 } // END - if
495         } elseif (isValidUserData()) {
496                 // Using cache is fine
497                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $value . ' is valid, using cache #2');
498                 return TRUE;
499         }
500
501         // By default none was found
502         $found = FALSE;
503
504         // Extra SQL statements
505         $ADD = runFilterChain('convert_user_data_columns', ' ');
506
507         // Query for the user
508         $result = sqlQueryEscaped("SELECT *" . $ADD . " FROM `{?_MYSQL_PREFIX?}_user_data` WHERE `%s`='%s' LIMIT 1",
509                 array(
510                         $column,
511                         $value
512                 ), __FUNCTION__, __LINE__);
513
514         // Is there a record?
515         if (sqlNumRows($result) == 1) {
516                 // Load data from cookies
517                 $data = sqlFetchArray($result);
518
519                 // Set the userid for later use
520                 setCurrentUserId($data['userid']);
521
522                 // And cache the data for this userid
523                 $GLOBALS['user_data'][getCurrentUserId()] = $data;
524
525                 // Rewrite 'last_failure' if found and ext-user has version >= 0.3.7
526                 if ((isExtensionInstalledAndNewer('user', '0.3.7')) && (isset($GLOBALS['user_data'][getCurrentUserId()]['last_failure']))) {
527                         // Backup the raw one and zero it
528                         $GLOBALS['user_data'][getCurrentUserId()]['last_failure_raw'] = $GLOBALS['user_data'][getCurrentUserId()]['last_failure'];
529                         $GLOBALS['user_data'][getCurrentUserId()]['last_failure'] = NULL;
530
531                         // Is it not zero?
532                         if (!is_null($GLOBALS['user_data'][getCurrentUserId()]['last_failure_raw'])) {
533                                 // Seperate data/time
534                                 $array = explode(' ', $GLOBALS['user_data'][getCurrentUserId()]['last_failure_raw']);
535
536                                 // Seperate data and time again
537                                 $array['date'] = explode('-', $array[0]);
538                                 $array['time'] = explode(':', $array[1]);
539
540                                 // Now pass it to mktime()
541                                 $GLOBALS['user_data'][getCurrentUserId()]['last_failure'] = mktime(
542                                         $array['time'][0],
543                                         $array['time'][1],
544                                         $array['time'][2],
545                                         $array['date'][1],
546                                         $array['date'][2],
547                                         $array['date'][0]
548                                 );
549                         } // END - if
550                 } // END - if
551
552                 // Found, but valid?
553                 $found = isValidUserData();
554         } // END - if
555
556         // Free memory
557         sqlFreeResult($result);
558
559         // Return result
560         return $found;
561 }
562
563 /*
564  * Checks whether the current session bears a valid admin id and password hash.
565  *
566  * This patched function will reduce many SELECT queries for the current admin
567  * login.
568  */
569 function isAdmin () {
570         //* DIE: */ reportBug(__FUNCTION__, __LINE__, 'CALLED!');
571         //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'CALLED!');
572
573         // Is there cache?
574         if (isset($GLOBALS[__FUNCTION__])) {
575                 // Return it
576                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'isAdmin()=' . intval($GLOBALS[__FUNCTION__]) . ' - CACHED!');
577                 return $GLOBALS[__FUNCTION__];
578         } // END - if
579
580         if ((isInstaller()) || (!isAdminRegistered())) {
581                 // No admin in installation phase!
582                 $GLOBALS[__FUNCTION__] = FALSE;
583                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'isAdmin()=' . intval($GLOBALS[__FUNCTION__]) . ' - INSTALLER!');
584                 return FALSE;
585         } // END - if
586
587         // Init variables
588         $ret = FALSE;
589         $adminId = '0';
590         $passwordFromCookie = '';
591
592         // If admin login is not given take current from cookies...
593         //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'isSessionVariableSet(admin_id)=' . intval(isSessionVariableSet('admin_id')) . ',isSessionVariableSet(admin_md5)=' . intval(isSessionVariableSet('admin_md5')));
594         if ((isSessionVariableSet('admin_id')) && (isSessionVariableSet('admin_md5'))) {
595                 // Debug message
596                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Getting admin data from session ...');
597
598                 // Get admin login and password from session/cookies
599                 $adminId            = getCurrentAdminId();
600                 $passwordFromCookie = getAdminMd5();
601         } // END - if
602         //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'adminId=' . $adminId . ',passwordFromCookie=' . $passwordFromCookie);
603
604         // Abort if admin id is zero
605         if (($adminId == '0') || (empty($passwordFromCookie))) {
606                 // A very noisy debug message ...
607                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Current adminId is zero. isSessionVariableSet(admin_id)=' . intval(isSessionVariableSet('admin_id')) . ',isSessionVariableSet(admin_md5)=' . intval(isSessionVariableSet('admin_md5')));
608
609                 // Abort here now
610                 $GLOBALS[__FUNCTION__] = FALSE;
611                 return FALSE;
612         } // END - if
613
614         // Init it with failed
615         $GLOBALS[__FUNCTION__] = FALSE;
616
617         // Search in array for entry
618         if (isset($GLOBALS['admin_hash'])) {
619                 // Use cached string
620                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'Using admin_hash=' . $GLOBALS['admin_hash'] . ' from cache');
621         } elseif ((!empty($adminId)) && (!empty($passwordFromCookie)) && (isAdminHashSet($adminId) === TRUE)) {
622                 // Get admin hash and hash it
623                 $GLOBALS['admin_hash'] = encodeHashForCookie(getAdminHash($adminId));
624                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'valPass=' . $GLOBALS['admin_hash']);
625
626                 // Count cache hits
627                 incrementStatsEntry('cache_hits');
628         } elseif ((!empty($adminId)) && ((!isExtensionActive('cache')) || (isAdminHashSet($adminId) === FALSE))) {
629                 // Get admin hash and hash it
630                 $GLOBALS['admin_hash'] = encodeHashForCookie(getAdminHash($adminId));
631                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'valPass=' . $GLOBALS['admin_hash']);
632         }
633
634         // Check if password is valid
635         //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, '(' . $GLOBALS['admin_hash'] . '==' . $passwordFromCookie . ')='.intval($GLOBALS['admin_hash'] == $passwordFromCookie));
636         $GLOBALS[__FUNCTION__] = ((!empty($GLOBALS['admin_hash'])) && ($GLOBALS['admin_hash'] == $passwordFromCookie));
637
638         // Return result of comparision
639         //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'isAdmin()=' . intval($GLOBALS[__FUNCTION__]));
640         return $GLOBALS[__FUNCTION__];
641 }
642
643 // Generates a list of "max receiveable emails per day"
644 function addMaxReceiveList ($mode, $default = '') {
645         $OUT = '';
646         $result = FALSE;
647
648         switch ($mode) {
649                 case 'guest':
650                         // Guests (in the registration form) are not allowed to select 0 mails per day.
651                         $result = sqlQuery('SELECT `value`, `comment` FROM `{?_MYSQL_PREFIX?}_max_receive` WHERE `value` > 0 ORDER BY `value` ASC',
652                         __FUNCTION__, __LINE__);
653                         break;
654
655                 case 'admin':
656                 case 'member':
657                         // Members are allowed to set to zero mails per day (we will change this soon!)
658                         $result = sqlQuery('SELECT `value`, `comment` FROM `{?_MYSQL_PREFIX?}_max_receive` ORDER BY `value` ASC',
659                         __FUNCTION__, __LINE__);
660                         break;
661
662                 default: // Invalid!
663                         logDebugMessage(__FUNCTION__, __LINE__, sprintf('Invalid mode %s detected.', $mode));
664                         break;
665         }
666
667         // Some entries are found?
668         if (!ifSqlHasZeroNums($result)) {
669                 $OUT = '';
670                 while ($content = sqlFetchArray($result)) {
671                         $OUT .= '      <option value="' . $content['value'] . '"';
672
673                         if (postRequestElement('max_mails') == $content['value']) {
674                                 $OUT .= ' selected="selected"';
675                         } // END - if
676
677                         $OUT .= '>' . $content['value'] . ' {--PER_DAY--}';
678                         if (!empty($content['comment'])) $OUT .= '(' . $content['comment'] . ')';
679                         $OUT .= '</option>';
680                 }
681
682                 // Load template
683                 $OUT = loadTemplate(($mode . '_receive_table'), TRUE, $OUT);
684         } else {
685                 // Maybe the admin has to setup some maximum values?
686                 reportBug(__FUNCTION__, __LINE__, 'Nothing is being done here?');
687         }
688
689         // Free result
690         sqlFreeResult($result);
691
692         // Return generated HTML code
693         return $OUT;
694 }
695
696 // Checks whether the given email address is used.
697 function isEmailTaken ($email) {
698         // Default is no userid
699         $useridSql = ' IS NOT NULL';
700
701         // Is a member logged in?
702         if (isMember()) {
703                 // Get userid
704                 $useridSql = '!= ' . bigintval(getMemberId());
705         } // END - if
706
707         // Replace dot with {DOT}
708         $email = str_replace('.', '{DOT}', $email);
709
710         // Query the database
711         $result = sqlQueryEscaped("SELECT
712         COUNT(`userid`) AS `cnt`
713 FROM
714         `{?_MYSQL_PREFIX?}_user_data`
715 WHERE
716         '%s' REGEXP `email` AND
717         `userid` %s
718 LIMIT 1",
719                 array(
720                         $email,
721                         $useridSql
722                 ), __FUNCTION__, __LINE__);
723
724         // Is the email there?
725         list($count) = sqlFetchRow($result);
726
727         // Free the result
728         sqlFreeResult($result);
729
730         // Return result
731         return ($count == 1);
732 }
733
734 // Validate the given menu action
735 function isMenuActionValid ($mode, $action, $what, $updateEntry = FALSE) {
736         // Is the cache entry there and we shall not update?
737         if ((isset($GLOBALS['action_valid'][$mode][$action][$what])) && ($updateEntry === FALSE)) {
738                 // Count cache hit
739                 incrementStatsEntry('cache_hits');
740
741                 // Then use this cache
742                 return $GLOBALS['action_valid'][$mode][$action][$what];
743         } // END - if
744
745         // By default nothing is valid
746         $ret = FALSE;
747
748         // Look in all menus or only unlocked
749         $add = '';
750         if ((!isAdmin()) && ($mode != 'admin')) $add = " AND `locked`='N'";
751
752         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'mode=' . $mode . ',action=' . $action . ',what=' . $what);
753         if (($mode != 'admin') && ($updateEntry === TRUE)) {
754                 // Update guest or member menu
755                 $sql = sqlQueryEscaped("UPDATE `{?_MYSQL_PREFIX?}_%s_menu` SET `counter`=`counter`+1 WHERE `action`='%s' AND `what`='%s'".$add." LIMIT 1",
756                         array(
757                                 $mode,
758                                 $action,
759                                 $what
760                         ), __FUNCTION__, __LINE__, FALSE);
761         } elseif (($what != 'welcome') && (!empty($what))) {
762                 // Other actions
763                 $sql = sqlQueryEscaped("SELECT `id`, `what` FROM `{?_MYSQL_PREFIX?}_%s_menu` WHERE `action`='%s' AND `what`='%s'".$add." ORDER BY `action` DESC LIMIT 1",
764                         array(
765                                 $mode,
766                                 $action,
767                                 $what
768                         ), __FUNCTION__, __LINE__, FALSE);
769         } else {
770                 // Admin login overview
771                 $sql = sqlQueryEscaped("SELECT `id`, `what` FROM `{?_MYSQL_PREFIX?}_%s_menu` WHERE `action`='%s' AND (`what`='' OR `what` IS NULL)".$add." ORDER BY `action` DESC LIMIT 1",
772                         array(
773                                 $mode,
774                                 $action
775                         ), __FUNCTION__, __LINE__, FALSE);
776         }
777
778         // Run SQL command
779         $result = sqlQuery($sql, __FUNCTION__, __LINE__);
780
781         // Should we look for affected rows (only update) or found rows?
782         if ($updateEntry === TRUE) {
783                 // Check updated/affected rows
784                 $ret = (!ifSqlHasZeroAffectedRows());
785         } else {
786                 // Check found rows
787                 $ret = (!ifSqlHasZeroNums($result));
788         }
789
790         // Free memory
791         sqlFreeResult($result);
792
793         // Set cache entry
794         $GLOBALS['action_valid'][$mode][$action][$what] = $ret;
795
796         // Return result
797         return $ret;
798 }
799
800 // Get action value from mode (admin/guest/member) and what-value
801 function getActionFromModuleWhat ($module, $what) {
802         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'module=' . $module . ',what=' . $what);
803         // Init status
804         $data['action'] = '';
805
806         if (!isExtensionInstalledAndNewer('sql_patches', '0.0.5')) {
807                 // ext-sql_patches is missing so choose depending on mode
808                 $what = determineWhat($module);
809         } elseif ((empty($what)) && ($module != 'admin')) {
810                 // Use configured 'home'
811                 $what = getIndexHome();
812         } // END - if
813
814         if ($module == 'admin') {
815                 // Action value for admin area
816                 if (isGetRequestElementSet('action')) {
817                         // Use from request!
818                         return getRequestElement('action');
819                 } elseif (isActionSet()) {
820                         // Get it directly from URL
821                         return getAction();
822                 } elseif (($what == 'welcome') || (!isWhatSet())) {
823                         // Default value for admin area
824                         $data['action'] = 'login';
825                 }
826         } elseif (isActionSet()) {
827                 // Get it directly from URL
828                 return getAction();
829         }
830         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, ' ret=' . $data['action']);
831
832         // Does the module have a menu?
833         if (ifModuleHasMenu($module)) {
834                 // Rewriting modules to menu
835                 $module = mapModuleToTable($module);
836
837                 // Guest and member menu is 'main' as the default
838                 if (empty($data['action'])) {
839                         $data['action'] = 'main';
840                 } // END - if
841
842                 // Load from database
843                 $result = sqlQueryEscaped("SELECT `action` FROM `{?_MYSQL_PREFIX?}_%s_menu` WHERE `what`='%s' LIMIT 1",
844                         array(
845                                 $module,
846                                 $what
847                         ), __FUNCTION__, __LINE__);
848
849                 // Entry found?
850                 if (sqlNumRows($result) == 1) {
851                         // Load action value and pray that this one is the right you want... ;-)
852                         $data = sqlFetchArray($result);
853                 } // END - if
854
855                 // Free memory
856                 sqlFreeResult($result);
857         } elseif ((!isExtensionInstalled('sql_patches')) && ($module != 'admin') && ($module != 'unknown')) {
858                 // No ext-sql_patches installed, but maybe we need to register an admin?
859                 if (isAdminRegistered()) {
860                         // Redirect to admin area
861                         redirectToUrl('admin.php');
862                 } // END - if
863         }
864
865         // Return action value
866         return $data['action'];
867 }
868
869 // Get category name back
870 function getCategory ($cid) {
871         // Default is not found
872         $data['cat'] = '{--_CATEGORY_404--}';
873
874         // Is the category id set?
875         if (!isValidId($cid)) {
876                 // No category
877                 $data['cat'] = '{--_CATEGORY_NONE--}';
878         } elseif (isValidId($cid)) {
879                 // Lookup the category in database
880                 $result = sqlQueryEscaped('SELECT `cat` FROM `{?_MYSQL_PREFIX?}_cats` WHERE `id`=%s LIMIT 1',
881                         array(bigintval($cid)), __FUNCTION__, __LINE__);
882                 if (sqlNumRows($result) == 1) {
883                         // Category found... :-)
884                         $data = sqlFetchArray($result);
885                 } // END - if
886
887                 // Free result
888                 sqlFreeResult($result);
889         } // END - if
890
891         // Return result
892         return $data['cat'];
893 }
894
895 // Get a string of "mail title" and price back
896 function getPaymentTitlePrice ($paymentsId, $full = FALSE) {
897         // Only title or also including price?
898         if ($full === FALSE) {
899                 $ret = getPaymentData($paymentsId, 'main_title');
900         } else {
901                 $ret = getPaymentData($paymentsId, 'main_title') . ' / {%pipe,getPaymentData,translateComma=' . $paymentsId . '%} {?POINTS?}';
902         }
903
904         // Return result
905         return $ret;
906 }
907
908 // Get payment price
909 function getPaymentPrice ($paymentsId) {
910         // Return result
911         return getPaymentData($paymentsId, 'price');
912 }
913
914 // Get payment time
915 function getPaymentTime ($paymentsId) {
916         // Return result
917         return getPaymentData($paymentsId, 'time');
918 }
919
920 // Get payment 'payment'
921 function getPaymentPayment ($paymentsId) {
922         // Return result
923         return getPaymentData($paymentsId, 'payment');
924 }
925
926 // "Getter" for payment data (cached)
927 function getPaymentData ($paymentsId, $lookFor) {
928         // Default value...
929         $data[$lookFor] = NULL;
930
931         // Is there cache?
932         if (isset($GLOBALS['cache_array']['payments'][$lookFor][$paymentsId])) {
933                 // Use it if found to save SQL queries
934                 $data[$lookFor] = $GLOBALS['cache_array']['payments'][$lookFor][$paymentsId];
935
936                 // Update cache hits
937                 incrementStatsEntry('cache_hits');
938         } elseif (!isExtensionActive('cache')) {
939                 // Search for it in database
940                 $result = sqlQueryEscaped('SELECT `%s` FROM `{?_MYSQL_PREFIX?}_payments` WHERE `id`=%s LIMIT 1',
941                         array(
942                                 $lookFor,
943                                 bigintval($paymentsId)
944                         ), __FUNCTION__, __LINE__);
945
946                 // Is the entry there?
947                 if (sqlNumRows($result) == 1) {
948                         // Payment type found... :-)
949                         $data = sqlFetchArray($result);
950                 } // END - if
951
952                 // Free result
953                 sqlFreeResult($result);
954         }
955
956         // Return value
957         return $data[$lookFor];
958 }
959
960 // Remove a receiver's id from $receivers and add a link for him to confirm
961 function removeReceiver (&$receivers, $key, $userid, $poolId, $statsId = 0, $isBonusMail = FALSE) {
962         // Default is not removed
963         $ret = 'failed';
964
965         // Is the userid valid?
966         if (isValidId($userid)) {
967                 // Remove entry from array
968                 unset($receivers[$key]);
969
970                 // Is there already a line for this user available?
971                 if (isValidId($statsId)) {
972                         // Default is 'normal' mail
973                         $type = 'NORMAL';
974                         $rowName = 'stats_id';
975
976                         // Only when we got a real stats id continue searching for the entry
977                         if ($isBonusMail === TRUE) {
978                                 $type = 'BONUS';
979                                 $rowName = 'bonus_id';
980                         } // END - if
981
982                         // Try to look the entry up
983                         $result = sqlQueryEscaped("SELECT `id` FROM `{?_MYSQL_PREFIX?}_user_links` WHERE `%s`=%s AND `userid`=%s AND `link_type`='%s' LIMIT 1",
984                                 array(
985                                         $rowName,
986                                         bigintval($statsId),
987                                         bigintval($userid),
988                                         $type
989                                 ), __FUNCTION__, __LINE__);
990
991                         // Was it *not* found?
992                         if (ifSqlHasZeroNums($result)) {
993                                 // So we add one!
994                                 sqlQueryEscaped("INSERT INTO `{?_MYSQL_PREFIX?}_user_links` (`%s`, `userid`, `link_type`) VALUES (%s,%s,'%s')",
995                                         array(
996                                                 $rowName,
997                                                 bigintval($statsId),
998                                                 bigintval($userid),
999                                                 $type
1000                                         ), __FUNCTION__, __LINE__);
1001
1002                                 // Update 'mails_sent' if ext-sql_patches is updated
1003                                 if (isExtensionInstalledAndNewer('sql_patches', '0.7.4')) {
1004                                         // Update the pool
1005                                         updatePoolDataById($poolId, 'mails_sent', 1, '+');
1006                                 } // END - if
1007                                 $ret = 'done';
1008                         } else {
1009                                 // Already found
1010                                 $ret = 'already';
1011                         }
1012
1013                         // Free memory
1014                         sqlFreeResult($result);
1015                 } // END - if
1016         } // END - if
1017
1018         // Return status for sending routine
1019         return $ret;
1020 }
1021
1022 // Calculate sum (default) or count records of given criteria
1023 function countSumTotalData ($search, $tableName, $lookFor = 'id', $whereStatement = 'userid', $countRows = FALSE, $add = '', $mode = '=') {
1024         // Debug message
1025         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'search=' . $search . ',tableName=' . $tableName . ',lookFor=' . $lookFor . ',whereStatement=' . $whereStatement . ',add=' . $add);
1026         if ((empty($search)) && (!is_null($search))) {
1027                 // Count or sum whole table?
1028                 if ($countRows === TRUE) {
1029                         // Count whole table
1030                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'COUNT!');
1031                         $result = sqlQueryEscaped('SELECT COUNT(`%s`) AS `res` FROM `{?_MYSQL_PREFIX?}_%s`' . $add . ' LIMIT 1',
1032                                 array(
1033                                         $lookFor,
1034                                         $tableName
1035                                 ), __FUNCTION__, __LINE__);
1036                 } else {
1037                         // Sum whole table
1038                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'SUM!');
1039                         $result = sqlQueryEscaped('SELECT SUM(`%s`) AS `res` FROM `{?_MYSQL_PREFIX?}_%s`' . $add . ' LIMIT 1',
1040                                 array(
1041                                         $lookFor,
1042                                         $tableName
1043                                 ), __FUNCTION__, __LINE__);
1044                 }
1045         } elseif (($countRows === TRUE) || ($lookFor == 'userid')) {
1046                 // Count rows
1047                 if (is_null($search)) {
1048                         // Fix mode
1049                         if ($mode == '=') {
1050                                 $mode = 'IS';
1051                         } elseif ($mode == '!=') {
1052                                 $mode = 'IS NOT';
1053                         }
1054
1055                         // Look for NULL/0
1056                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'COUNT-NULL!');
1057                         $result = sqlQueryEscaped("SELECT COUNT(`%s`) AS `res` FROM `{?_MYSQL_PREFIX?}_%s` WHERE (`%s` %s NULL OR `%s`=0)" . $add . ' LIMIT 1',
1058                                 array(
1059                                         $lookFor,
1060                                         $tableName,
1061                                         $whereStatement,
1062                                         $mode,
1063                                         $whereStatement
1064                                 ), __FUNCTION__, __LINE__);
1065                 } else {
1066                         // Regular entry
1067                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'COUNT!');
1068                         $result = sqlQueryEscaped("SELECT COUNT(`%s`) AS `res` FROM `{?_MYSQL_PREFIX?}_%s` WHERE `%s`%s'%s'" . $add . ' LIMIT 1',
1069                                 array(
1070                                         $lookFor,
1071                                         $tableName,
1072                                         $whereStatement,
1073                                         $mode,
1074                                         $search
1075                                 ), __FUNCTION__, __LINE__);
1076                 }
1077         } else {
1078                 // Sum all rows
1079                 if (is_null($search)) {
1080                         // Fix mode
1081                         if ($mode == '=') {
1082                                 $mode = 'IS';
1083                         } elseif ($mode == '!=') {
1084                                 $mode = 'IS NOT';
1085                         }
1086
1087                         // Look for NULL/0
1088                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'SUM-NULL!');
1089                         $result = sqlQueryEscaped("SELECT SUM(`%s`) AS `res` FROM `{?_MYSQL_PREFIX?}_%s` WHERE (`%s` %s NULL OR `%s`=0)" . $add . ' LIMIT 1',
1090                                 array(
1091                                         $lookFor,
1092                                         $tableName,
1093                                         $whereStatement,
1094                                         $mode,
1095                                         $whereStatement
1096                                 ), __FUNCTION__, __LINE__);
1097                 } else {
1098                         // Regular entry
1099                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'SUM!');
1100                         $result = sqlQueryEscaped("SELECT SUM(`%s`) AS `res` FROM `{?_MYSQL_PREFIX?}_%s` WHERE `%s`%s'%s'" . $add . ' LIMIT 1',
1101                                 array(
1102                                         $lookFor,
1103                                         $tableName,
1104                                         $whereStatement,
1105                                         $mode,
1106                                         $search
1107                                 ), __FUNCTION__, __LINE__);
1108                 }
1109         }
1110
1111         // Load row
1112         $data = sqlFetchArray($result);
1113
1114         // Free result
1115         sqlFreeResult($result);
1116
1117         // Fix empty values
1118         if ((empty($data['res'])) && ($lookFor != 'counter') && ($lookFor != 'id') && ($lookFor != 'userid') && ($lookFor != 'rallye_id')) {
1119                 // Float number
1120                 $data['res'] = '0.00000';
1121         } elseif ('' . $data['res'] . '' == '') {
1122                 // Fix empty result
1123                 $data['res'] = '0';
1124         }
1125
1126         // Return value
1127         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'res=' . $data['res']);
1128         return $data['res'];
1129 }
1130
1131 /**
1132  * Sends out mail to all administrators. This function is no longer obsolete
1133  * because we need it when there is no ext-admins installed
1134  */
1135 function sendAdminEmails ($subject, $message, $isBugReport = FALSE) {
1136         // Default is no special header
1137         $mailHeader = '';
1138
1139         // Is it a bug report?
1140         if ($isBugReport === TRUE) {
1141                 // Then add a reply-to line back to the author (me)
1142                 $mailHeader = 'Reply-To: webmaster@mxchange.org' . PHP_EOL;
1143         } // END - if
1144
1145         // Load all admin email addresses
1146         $result = sqlQuery('SELECT `email` FROM `{?_MYSQL_PREFIX?}_admins` ORDER BY `id` ASC', __FUNCTION__, __LINE__);
1147
1148         // And send the notification to all of them
1149         while ($content = sqlFetchArray($result)) {
1150                 // Send the email out
1151                 sendEmail($content['email'], $subject, $message, 'N', $mailHeader);
1152         } // END - if
1153
1154         // Free result
1155         sqlFreeResult($result);
1156
1157         // Really simple... ;-)
1158 }
1159
1160 // Get id number from administrator's login name
1161 function getAdminId ($adminLogin) {
1162         // By default no admin is found
1163         $data['id'] = -1;
1164
1165         // Check cache
1166         if (isset($GLOBALS['cache_array']['admin']['admin_id'][$adminLogin])) {
1167                 // Use it if found to save SQL queries
1168                 $data['id'] = $GLOBALS['cache_array']['admin']['admin_id'][$adminLogin];
1169
1170                 // Update cache hits
1171                 incrementStatsEntry('cache_hits');
1172         } elseif (!isExtensionActive('cache')) {
1173                 // Load from database
1174                 $result = sqlQueryEscaped("SELECT `id` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `login`='%s' LIMIT 1",
1175                         array($adminLogin), __FUNCTION__, __LINE__);
1176
1177                 // Is there an entry?
1178                 if (sqlNumRows($result) == 1) {
1179                         // Get it
1180                         $data = sqlFetchArray($result);
1181                 } // END - if
1182
1183                 // Free result
1184                 sqlFreeResult($result);
1185         }
1186
1187         // Return the id
1188         return $data['id'];
1189 }
1190
1191 // "Getter" for current admin id
1192 function getCurrentAdminId () {
1193         // Log debug message
1194         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'called!');
1195
1196         // Is there cache?
1197         if (!isset($GLOBALS['current_admin_id'])) {
1198                 // Get the admin login from session
1199                 $adminId = getSession('admin_id');
1200
1201                 // Remember in cache securely
1202                 setCurrentAdminId(bigintval($adminId));
1203         } // END - if
1204
1205         // Return it
1206         return $GLOBALS['current_admin_id'];
1207 }
1208
1209 // Setter for current admin id
1210 function setCurrentAdminId ($currentAdminId) {
1211         // Set it secured
1212         $GLOBALS['current_admin_id'] = bigintval($currentAdminId);
1213 }
1214
1215 // Get password hash from administrator's login name
1216 function getAdminHash ($adminId) {
1217         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'adminId=' . $adminId . ' - ENTERED!');
1218         // By default an invalid hash is returned
1219         $data['password'] = -1;
1220
1221         // Is admin hash set?
1222         if (isAdminHashSet($adminId)) {
1223                 // Check cache
1224                 $data['password'] = $GLOBALS['cache_array']['admin']['password'][$adminId];
1225
1226                 // Update cache hits
1227                 incrementStatsEntry('cache_hits');
1228         } elseif (!isExtensionActive('cache')) {
1229                 // Load from database
1230                 $result = sqlQueryEscaped("SELECT `password` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
1231                         array(bigintval($adminId)), __FUNCTION__, __LINE__);
1232
1233                 // Is there an entry?
1234                 if (sqlNumRows($result) == 1) {
1235                         // Fetch data
1236                         $data = sqlFetchArray($result);
1237
1238                         // Set cache
1239                         setAdminHash($adminId, $data['password']);
1240                 } // END - if
1241
1242                 // Free result
1243                 sqlFreeResult($result);
1244         }
1245
1246         // Return password hash
1247         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'adminId=' . $adminId . ',data[password]=' . $data['password'] . ' - EXIT!');
1248         return $data['password'];
1249 }
1250
1251 // "Getter" for admin login
1252 function getAdminLogin ($adminId) {
1253         // By default a non-existent login is returned (other functions react on this!)
1254         $data['login'] = '***';
1255
1256         if (isset($GLOBALS['cache_array']['admin']['login'][$adminId])) {
1257                 // Get cache
1258                 $data['login'] = $GLOBALS['cache_array']['admin']['login'][$adminId];
1259
1260                 // Update cache hits
1261                 incrementStatsEntry('cache_hits');
1262         } elseif (!isExtensionActive('cache')) {
1263                 // Load from database
1264                 $result = sqlQueryEscaped("SELECT `login` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
1265                         array(bigintval($adminId)), __FUNCTION__, __LINE__);
1266
1267                 // Entry found?
1268                 if (sqlNumRows($result) == 1) {
1269                         // Fetch data
1270                         $data = sqlFetchArray($result);
1271
1272                         // Set cache
1273                         $GLOBALS['cache_array']['admin']['login'][$adminId] = $data['login'];
1274                 } // END - if
1275
1276                 // Free memory
1277                 sqlFreeResult($result);
1278         }
1279
1280         // Return the result
1281         return $data['login'];
1282 }
1283
1284 // Get email address of admin id
1285 function getAdminEmail ($adminId) {
1286         // By default an invalid emails is returned
1287         $data['email'] = '***';
1288
1289         if (isset($GLOBALS['cache_array']['admin']['email'][$adminId])) {
1290                 // Get cache
1291                 $data['email'] = $GLOBALS['cache_array']['admin']['email'][$adminId];
1292
1293                 // Update cache hits
1294                 incrementStatsEntry('cache_hits');
1295         } elseif (!isExtensionActive('cache')) {
1296                 // Load from database
1297                 $result_admin_id = sqlQueryEscaped("SELECT `email` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
1298                         array(bigintval($adminId)), __FUNCTION__, __LINE__);
1299
1300                 // Entry found?
1301                 if (sqlNumRows($result_admin_id) == 1) {
1302                         // Get data
1303                         $data = sqlFetchArray($result_admin_id);
1304
1305                         // Set cache
1306                         $GLOBALS['cache_array']['admin']['email'][$adminId] = $data['email'];
1307                 } // END - if
1308
1309                 // Free result
1310                 sqlFreeResult($result_admin_id);
1311         }
1312
1313         // Return email
1314         return $data['email'];
1315 }
1316
1317 // Get default ACL of admin id
1318 function getAdminDefaultAcl ($adminId) {
1319         // By default an invalid ACL value is returned
1320         $data['default_acl'] = 'NO-ACL';
1321
1322         // Is ext-sql_patches there and was it found in cache?
1323         if (!isExtensionActive('sql_patches')) {
1324                 // Not found, which is bad, so we need to allow all
1325                 $data['default_acl'] = 'allow';
1326         } elseif (isset($GLOBALS['cache_array']['admin']['default_acl'][$adminId])) {
1327                 // Use cache
1328                 $data['default_acl'] = $GLOBALS['cache_array']['admin']['default_acl'][$adminId];
1329
1330                 // Update cache hits
1331                 incrementStatsEntry('cache_hits');
1332         } elseif (!isExtensionActive('cache')) {
1333                 // Load from database
1334                 $result_admin_id = sqlQueryEscaped("SELECT `default_acl` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
1335                         array(bigintval($adminId)), __FUNCTION__, __LINE__);
1336
1337                 // Is there an entry?
1338                 if (sqlNumRows($result_admin_id) == 1) {
1339                         // Fetch data
1340                         $data = sqlFetchArray($result_admin_id);
1341
1342                         // Set cache
1343                         $GLOBALS['cache_array']['admin']['default_acl'][$adminId] = $data['default_acl'];
1344                 }
1345
1346                 // Free result
1347                 sqlFreeResult($result_admin_id);
1348         }
1349
1350         // Return default ACL
1351         return $data['default_acl'];
1352 }
1353
1354 // Get menu mode (la_mode) of admin id
1355 function getAdminMenuMode ($adminId) {
1356         // By default an invalid mode
1357         $data['la_mode'] = 'INVALID';
1358
1359         // Is ext-sql_patches there and was it found in cache?
1360         if (!isExtensionActive('sql_patches')) {
1361                 // Not found, which is bad, so we need to allow all
1362                 $data['la_mode'] = 'global';
1363         } elseif (isset($GLOBALS['cache_array']['admin']['la_mode'][$adminId])) {
1364                 // Use cache
1365                 $data['la_mode'] = $GLOBALS['cache_array']['admin']['la_mode'][$adminId];
1366
1367                 // Update cache hits
1368                 incrementStatsEntry('cache_hits');
1369         } elseif (!isExtensionActive('cache')) {
1370                 // Load from database
1371                 $result_admin_id = sqlQueryEscaped("SELECT `la_mode` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
1372                         array(bigintval($adminId)), __FUNCTION__, __LINE__);
1373
1374                 // Is there an entry?
1375                 if (sqlNumRows($result_admin_id) == 1) {
1376                         // Fetch data
1377                         $data = sqlFetchArray($result_admin_id);
1378
1379                         // Set cache
1380                         $GLOBALS['cache_array']['admin']['la_mode'][$adminId] = $data['la_mode'];
1381                 }
1382
1383                 // Free result
1384                 sqlFreeResult($result_admin_id);
1385         }
1386
1387         // Return default ACL
1388         return $data['la_mode'];
1389 }
1390
1391 // Generates an option list from various parameters
1392 function generateOptions ($table, $key, $value, $default = '', $extra = '', $whereStatement = '', $disabled = array(), $callback = '', $allowNone = FALSE) {
1393         $ret = '';
1394
1395         // Allow none?
1396         if ($allowNone === TRUE) {
1397                 // Add option for none
1398                 $ret .= '<option value="0">{--SELECT_NONE--}</option>';
1399         } // END - if
1400
1401         if ($table == '/ARRAY/') {
1402                 // Selection from array
1403                 if ((is_array($key)) && (is_array($value)) && ((count($key)) == (count($value)) || (!empty($callback)))) {
1404                         // Both are arrays
1405                         foreach ($key as $idx => $optionValue) {
1406                                 $ret .= '<option value="' . $optionValue . '"';
1407                                 if ($default == $optionValue) {
1408                                         // Selected by default
1409                                         $ret .= ' selected="selected"';
1410                                 } elseif (isset($disabled[$optionValue])) {
1411                                         // Disabled!
1412                                         $ret .= ' disabled="disabled"';
1413                                 }
1414
1415                                 // Is the call-back function set?
1416                                 if (!empty($callback)) {
1417                                         // Call it
1418                                         $value[$idx] = call_user_func_array($callback, array($key[$idx]));
1419                                 } // END - if
1420
1421                                 // Finish option tag
1422                                 $ret .= '>' . $value[$idx] . '</option>';
1423                         } // END - foreach
1424                 } else {
1425                         // Problem in request
1426                         reportBug(__FUNCTION__, __LINE__, 'Not all are arrays: key[' . count($key) . ']=' . gettype($key) . ',value[' . count($value) . ']=' . gettype($value) . ',callback=' . $callback);
1427                 }
1428         } else {
1429             ///////////////////////
1430                 // Data from database /
1431                 ///////////////////////
1432
1433                 // Init extra column (if requested)
1434                 $extraColumn = '';
1435                 if (!empty($extra)) {
1436                         $extraColumn = ',`' . $extra . '` AS `extra`';
1437                 } // END - if
1438
1439                 // Run SQL query
1440                 $result = sqlQueryEscaped("SELECT `%s` AS `key`, `%s` AS `value`" . $extraColumn . " FROM `{?_MYSQL_PREFIX?}_%s` " . $whereStatement . " ORDER BY `%s` ASC",
1441                         array(
1442                                 $key,
1443                                 $value,
1444                                 $table,
1445                                 $value
1446                         ), __FUNCTION__, __LINE__);
1447
1448                 // Is there rows?
1449                 if (!ifSqlHasZeroNums($result)) {
1450                         // Found data so add them as OPTION lines
1451                         while ($content = sqlFetchArray($result)) {
1452                                 // Is extra set?
1453                                 if (!isset($content['extra'])) {
1454                                         // Set it to empty
1455                                         $content['extra'] = '';
1456                                 } // END - if
1457
1458                                 $ret .= '<option value="' . $content['key'] . '"';
1459
1460                                 if ($default == $content['key']) {
1461                                         // Selected by default
1462                                         $ret .= ' selected="selected"';
1463                                 } elseif (isset($disabled[$content['key']])) {
1464                                         // Disabled!
1465                                         $ret .= ' disabled="disabled"';
1466                                 }
1467
1468                                 // Add it, if set
1469                                 if (!empty($content['extra'])) {
1470                                         $content['extra'] = ' (' . $content['extra'] . ')';
1471                                 } // END - if
1472
1473                                 // Is the call-back function set?
1474                                 if (!empty($callback)) {
1475                                         // Call it
1476                                         $content['value'] = call_user_func_array($callback, array($content['value']));
1477                                 } // END - if
1478
1479                                 // Finish option list
1480                                 $ret .= '>' . $content['value'] . $content['extra'] . '</option>';
1481                         } // END - while
1482                 } else {
1483                         // No data found
1484                         $ret = '<option value="x">{--SELECT_NONE--}</option>';
1485                 }
1486
1487                 // Free memory
1488                 sqlFreeResult($result);
1489         }
1490
1491         // Return - hopefully - the requested data
1492         return $ret;
1493 }
1494
1495 // Deletes a user account with given reason
1496 function deleteUserAccount ($userid, $reason) {
1497         // Init points
1498         $data['points'] = '0';
1499
1500         // Search for the points and user data
1501         $result = sqlQueryEscaped("SELECT
1502         (SUM(`p`.`points`) - `d`.`used_points`) AS `points`
1503 FROM
1504         `{?_MYSQL_PREFIX?}_user_points` AS `p`
1505 LEFT JOIN
1506         `{?_MYSQL_PREFIX?}_user_data` AS `d`
1507 ON
1508         `p`.`userid`=`d`.`userid`
1509 WHERE
1510         `p`.`userid`=%s
1511 LIMIT 1",
1512                 array(bigintval($userid)), __FUNCTION__, __LINE__);
1513
1514         // Is there an entry?
1515         if (sqlNumRows($result) == 1) {
1516                 // Save his points to add them to the jackpot
1517                 $data = sqlFetchArray($result);
1518
1519                 // Delete points entries as well
1520                 // @TODO Rewrite these lines to a filter
1521                 sqlQueryEscaped("DELETE LOW_PRIORITY FROM `{?_MYSQL_PREFIX?}_user_points` WHERE `userid`=%s",
1522                         array(bigintval($userid)), __FUNCTION__, __LINE__);
1523
1524                 // Update mediadata as well
1525                 if (isExtensionInstalledAndNewer('mediadata', '0.0.4')) {
1526                         // Update database
1527                         updateMediadataEntry(array('total_points'), 'sub', $data['points']);
1528                 } // END - if
1529
1530                 // Now, when we have all his points adds them do the jackpot!
1531                 if (isExtensionActive('jackpot')) {
1532                         addPointsToJackpot($data['points']);
1533                 } // END - if
1534         } // END - if
1535
1536         // Free the result
1537         sqlFreeResult($result);
1538
1539         // Delete category selections as well...
1540         sqlQueryEscaped("DELETE LOW_PRIORITY FROM `{?_MYSQL_PREFIX?}_user_cats` WHERE `userid`=%s",
1541                 array(bigintval($userid)), __FUNCTION__, __LINE__);
1542
1543         // Remove from rallye if found
1544         // @TODO Rewrite this to a filter
1545         if (isExtensionActive('rallye')) {
1546                 sqlQueryEscaped("DELETE LOW_PRIORITY FROM `{?_MYSQL_PREFIX?}_rallye_users` WHERE `userid`=%s",
1547                         array(bigintval($userid)), __FUNCTION__, __LINE__);
1548         } // END - if
1549
1550         // Add reason and translate points
1551         $data['text'] = $reason;
1552
1553         // Now a mail to the user and that's all...
1554         $message = loadEmailTemplate('member_user_deleted', $data, $userid);
1555         sendEmail($userid, '{--ADMIN_DELETE_ACCOUNT--}', $message);
1556
1557         // Ok, delete the account!
1558         sqlQueryEscaped("DELETE LOW_PRIORITY FROM `{?_MYSQL_PREFIX?}_user_data` WHERE `userid`=%s LIMIT 1", array(bigintval($userid)), __FUNCTION__, __LINE__);
1559 }
1560
1561 // Gets the matching what name from module
1562 function getWhatFromModule ($modCheck) {
1563         // Is the request element set?
1564         if (isGetRequestElementSet('what')) {
1565                 // Then return this!
1566                 return getRequestElement('what');
1567         } // END - if
1568
1569         // Default is empty
1570         $what = '';
1571
1572         // Check on given module
1573         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'modCheck=' . $modCheck);
1574         switch ($modCheck) {
1575                 case 'index': // Guest area
1576                         // Is ext-sql_patches installed and newer than 0.0.5?
1577                         if (isExtensionInstalledAndNewer('sql_patches', '0.0.5')) {
1578                                 // Use it from config
1579                                 $what = getIndexHome();
1580                         } else {
1581                                 // Use default 'welcome'
1582                                 $what = 'welcome';
1583                         }
1584                         break;
1585
1586                 default: // Default for all other menus (getIndexHome() is for index module only)
1587                         $what = 'welcome';
1588                         break;
1589         } // END - switch
1590
1591         // Return what value
1592         return $what;
1593 }
1594
1595 // Returns HTML code with an option list of all categories
1596 function generateCategoryOptionsList ($mode, $userid = NULL) {
1597         // Prepare WHERE statement
1598         $whereStatement = " WHERE `visible`='Y'";
1599         if (isAdmin()) $whereStatement = '';
1600
1601         // Initialize array...
1602         $categories = array(
1603                 'id'      => array(),
1604                 'name'    => array(),
1605                 'userids' => array()
1606         );
1607
1608         // Get categories
1609         $result = sqlQuery('SELECT
1610         `id`,
1611         `cat`
1612 FROM
1613         `{?_MYSQL_PREFIX?}_cats`
1614 ' . $whereStatement . '
1615 ORDER BY
1616         `sort` ASC',
1617                 __FUNCTION__, __LINE__);
1618
1619         // Are there entries?
1620         if (!ifSqlHasZeroNums($result)) {
1621                 // ... and begin loading stuff
1622                 while ($content = sqlFetchArray($result)) {
1623                         // Transfer some data
1624                         $categories['id'][]   = $content['id'];
1625                         array_push($categories['name'], $content['cat']);
1626
1627                         // Check which users are in this category
1628                         $result_userids = sqlQueryEscaped("SELECT `userid` FROM `{?_MYSQL_PREFIX?}_user_cats` WHERE `cat_id`=%s AND `userid` != %s ORDER BY `userid` ASC",
1629                                 array(
1630                                         bigintval($content['id']),
1631                                         convertNullToZero($userid)
1632                                 ), __FUNCTION__, __LINE__);
1633
1634                         // Init count
1635                         $userid_cnt = '0';
1636
1637                         // Start adding all
1638                         while ($data = sqlFetchArray($result_userids)) {
1639                                 // Add user count
1640                                 $userid_cnt += countSumTotalData($data['userid'], 'user_data', 'userid', 'userid', TRUE, runFilterChain('user_exclusion_sql', " AND `status`='CONFIRMED' AND `receive_mails` > 0"));
1641                         } // END - while
1642
1643                         // Free memory
1644                         sqlFreeResult($result_userids);
1645
1646                         // Add counter
1647                         array_push($categories['userids'], $userid_cnt);
1648                 } // END - while
1649
1650                 // Free memory
1651                 sqlFreeResult($result);
1652
1653                 // Generate options
1654                 $OUT = '';
1655                 foreach ($categories['id'] as $key => $value) {
1656                         $OUT .= '      <option value="' . $value . '">' . $categories['name'][$key] . ' (' . $categories['userids'][$key] . ' {--USERS_IN_CATEGORY--})</option>';
1657                 } // END - foreach
1658         } else {
1659                 // No cateogries are defined yet
1660                 $OUT = '<option class="bad">{--MEMBER_NO_CATEGORIES--}</option>';
1661         }
1662
1663         // Return HTML code
1664         return $OUT;
1665 }
1666
1667 // Add bonus mail to queue
1668 function addBonusMailToQueue ($subject, $text, $receiverList, $points, $seconds, $url, $categoryId, $mode='normal', $receiver=0) {
1669         // Is admin or bonus extension there?
1670         if (!isAdmin()) {
1671                 // Abort here
1672                 return FALSE;
1673         } elseif (!isExtensionActive('bonus')) {
1674                 // Abort here
1675                 return FALSE;
1676         }
1677
1678         // Calculcate target sent
1679         $target = countSelection(explode(';', $receiverList));
1680
1681         // Receiver is zero?
1682         if ($receiver == '0') {
1683                 // Then auto-fix it
1684                 $receiver = $target;
1685         } // END - if
1686
1687         // HTML extension active?
1688         if (isExtensionActive('html_mail')) {
1689                 // Add HTML mail
1690                 sqlQueryEscaped("INSERT INTO `{?_MYSQL_PREFIX?}_bonus` (
1691         `subject`,
1692         `text`,
1693         `receivers`,
1694         `points`,
1695         `time`,
1696         `data_type`,
1697         `timestamp`,
1698         `url`,
1699         `cat_id`,
1700         `target_send`,
1701         `mails_sent`,
1702         `html_msg`
1703 ) VALUES (
1704         '%s',
1705         '%s',
1706         '%s',
1707         %s,
1708         %s,
1709         'NEW',
1710         UNIX_TIMESTAMP(),
1711         '%s',
1712         %s,
1713         %s,
1714         %s,
1715         '%s'
1716 )",
1717                 array(
1718                         $subject,
1719                         $text,
1720                         $receiverList,
1721                         $points,
1722                         bigintval($seconds),
1723                         $url,
1724                         bigintval($categoryId),
1725                         $target,
1726                         bigintval($receiver),
1727                         convertBooleanToYesNo($mode == 'html')
1728                 ), __FUNCTION__, __LINE__);
1729         } else {
1730                 // Add regular mail
1731                 sqlQueryEscaped("INSERT INTO `{?_MYSQL_PREFIX?}_bonus` (
1732         `subject`,
1733         `text`,
1734         `receivers`,
1735         `points`,
1736         `time`,
1737         `data_type`,
1738         `timestamp`,
1739         `url`,
1740         `cat_id`,
1741         `target_send`,
1742         `mails_sent`
1743 ) VALUES (
1744         '%s',
1745         '%s',
1746         '%s',
1747         %s,
1748         %s,
1749         'NEW',
1750         UNIX_TIMESTAMP(),
1751         '%s',
1752         %s,
1753         %s,
1754         %s
1755 )",
1756                 array(
1757                         $subject,
1758                         $text,
1759                         $receiverList,
1760                         $points,
1761                         bigintval($seconds),
1762                         $url,
1763                         bigintval($categoryId),
1764                         $target,
1765                         bigintval($receiver),
1766                 ), __FUNCTION__, __LINE__);
1767         }
1768 }
1769
1770 // Generate a receiver list for given category and maximum receivers
1771 function generateReceiverList ($categoryId, $receiver, $mode = '') {
1772         // Init variables
1773         $extraColumns = '';
1774         $receiverList = '';
1775         $result       = FALSE;
1776
1777         // Secure data
1778         $categoryId = bigintval($categoryId);
1779         $receiver   = bigintval($receiver);
1780
1781         // Is the receiver zero and mode set?
1782         if (($receiver == '0') && (!empty($mode))) {
1783                 // Auto-fix receiver maximum
1784                 $receiver = getTotalReceivers($mode);
1785         } // END - if
1786
1787         // Exclude (maybe exclude) testers
1788         $addWhere = runFilterChain('user_exclusion_sql', ' ');
1789
1790         // Category given?
1791         if (isValidId($categoryId)) {
1792                 // Select category
1793                 $extraColumns  = "LEFT JOIN `{?_MYSQL_PREFIX?}_user_cats` AS `c` ON `d`.`userid`=`c`.`userid`";
1794                 $addWhere = sprintf(' AND `c`.`cat_id`=%s', $categoryId);
1795         } // END - if
1796
1797         // Exclude users in holiday?
1798         if (isExtensionInstalledAndNewer('holiday', '0.1.3')) {
1799                 // Add something for the holiday extension
1800                 $addWhere .= " AND `d`.`holiday_active`='N'";
1801         } // END - if
1802
1803         // Run query
1804         $result = sqlQueryEscaped("SELECT
1805         `d`.`userid`
1806 FROM
1807         `{?_MYSQL_PREFIX?}_user_data` AS `d`
1808         " . $extraColumns . "
1809 WHERE
1810         `d`.`status`='CONFIRMED'
1811         " . $addWhere . "
1812 ORDER BY
1813         `d`.`{?order_select?}` {?order_mode?}
1814 LIMIT %s",
1815                 array(
1816                         $receiver
1817                 ), __FUNCTION__, __LINE__);
1818
1819         // Entries found?
1820         if ((sqlNumRows($result) >= $receiver) && ($receiver > 0)) {
1821                 // Load all entries
1822                 while ($content = sqlFetchArray($result)) {
1823                         // Add receiver when not empty
1824                         if (!empty($content['userid'])) {
1825                                 $receiverList .= $content['userid'] . ';';
1826                         } // END - if
1827                 } // END - while
1828
1829                 // Free memory
1830                 sqlFreeResult($result);
1831
1832                 // Remove trailing semicolon
1833                 $receiverList = substr($receiverList, 0, -1);
1834         } // END - if
1835
1836         // Return list
1837         return $receiverList;
1838 }
1839
1840 // Recuce the amount of received emails for the receipients for given email
1841 function reduceRecipientReceivedMails ($column, $id, $count) {
1842         // Search for mail in database
1843         $result = sqlQueryEscaped("SELECT * FROM `{?_MYSQL_PREFIX?}_user_links` WHERE `%s`=%s ORDER BY `userid` ASC LIMIT %s",
1844                 array(
1845                         $column,
1846                         bigintval($id),
1847                         $count
1848                 ), __FUNCTION__, __LINE__
1849         );
1850
1851         // Are there entries?
1852         if (!ifSqlHasZeroNums($result)) {
1853                 // Now load all userids for one big query!
1854                 $userids = array();
1855                 while ($data = sqlFetchArray($result)) {
1856                         // By default reduce and found no emails
1857                         $num = 0;
1858
1859                         // We must now look if he has already confirmed this mail, so might sound double, but it may resolve problems
1860                         // @TODO Rewrite this to a filter
1861                         if ((isset($data['stats_id'])) && (isValidId($data['stats_id']))) {
1862                                 // User email
1863                                 $num = countSumTotalData($data['userid'], 'user_stats_data', 'id', 'userid', TRUE, sprintf(" AND `stats_type`='mailid' AND `stats_data`=%s", bigintval($data['stats_id'])));
1864                         } elseif ((isset($data['bonus_id'])) && (isValidId($data['bonus_id']))) {
1865                                 // Bonus mail
1866                                 $num = countSumTotalData($data['userid'], 'user_stats_data', 'id', 'userid', TRUE, sprintf(" AND `stats_type`='bonusid' AND `stats_data`=%s", bigintval($data['bonus_id'])));
1867                         }
1868
1869                         // Reduce this users total received emails?
1870                         if ($num === 0) {
1871                                 $userids[$data['userid']] = $data['userid'];
1872                         } // END - if
1873                 } // END - while
1874
1875                 if (isFilledArray($userids)) {
1876                         // Now update all user accounts
1877                         sqlQueryEscaped("UPDATE `{?_MYSQL_PREFIX?}_user_data` SET `emails_received`=`emails_received`-1 WHERE `userid` IN (%s) LIMIT %s",
1878                                 array(
1879                                         implode(',', $userids),
1880                                         count($userids)
1881                                 ), __FUNCTION__, __LINE__);
1882                 } else {
1883                         // Nothing deleted
1884                         displayMessage('{%message,ADMIN_MAIL_NOTHING_DELETED=' . $id . '%}');
1885                 }
1886         } // END - if
1887
1888         // Free result
1889         sqlFreeResult($result);
1890 }
1891
1892 // Creates a new task
1893 function createNewTask ($subject, $notes, $taskType, $userid = NULL, $adminId = NULL, $strip = TRUE) {
1894         // Insert the task data into the database
1895         sqlQueryEscaped("INSERT INTO `{?_MYSQL_PREFIX?}_task_system` (`assigned_admin`, `userid`, `status`, `task_type`, `subject`, `text`, `task_created`) VALUES (%s, %s, 'NEW', '%s', '%s', '%s', UNIX_TIMESTAMP())",
1896                 array(
1897                         convertZeroToNull($adminId),
1898                         convertZeroToNull($userid),
1899                         $taskType,
1900                         $subject,
1901                         $notes
1902                 ), __FUNCTION__, __LINE__, TRUE, $strip);
1903
1904         // Return insert id which is the task id
1905         return getSqlInsertId();
1906 }
1907
1908 // Updates last module / online time
1909 function updateLastActivity ($userid) {
1910         // Is 'what' set?
1911         if (isWhatSet()) {
1912                 // Run the update query
1913                 sqlQueryEscaped("UPDATE
1914         `{?_MYSQL_PREFIX?}_user_data`
1915 SET
1916         `{%%pipe,getUserLastWhatName%%}`='{%%pipe,getWhat%%}',
1917         `last_online`=UNIX_TIMESTAMP(),
1918         `REMOTE_ADDR`='{%%pipe,detectRemoteAddr%%}'
1919 WHERE
1920         `userid`=%s
1921 LIMIT 1",
1922                 array(
1923                         bigintval($userid)
1924                 ), __FUNCTION__, __LINE__);
1925         } else {
1926                 // No what set, needs to be ignored (last_module is last_what)
1927                 sqlQueryEscaped("UPDATE
1928         `{?_MYSQL_PREFIX?}_user_data`
1929 SET
1930         `{%%pipe,getUserLastWhatName%%}`=NULL,
1931         `last_online`=UNIX_TIMESTAMP(),
1932         `REMOTE_ADDR`='{%%pipe,detectRemoteAddr%%}'
1933 WHERE
1934         `userid`=%s
1935 LIMIT 1",
1936                 array(
1937                         bigintval($userid)
1938                 ), __FUNCTION__, __LINE__);
1939         }
1940 }
1941
1942 // List all given joined rows (callback function from XML)
1943 function doGenericJoinedListEntries ($tableTemplate, $rowTemplate, $noEntryMessageId, $tableName, $tableJoinType, $tableJoinName, $joinOnLeftTable, $joinOnCondition, $joinOnRightTable, $columns, $whereColumns, $orderByColumns, $callbackColumns, $extraParameters = array(), $conditions = array(), $content = array()) {
1944         // Verify that tableName and columns are not empty
1945         if ((!is_array($tableName)) || (count($tableName) != 1)) {
1946                 // No tableName specified
1947                 reportBug(__FUNCTION__, __LINE__, 'tableName is not given. Please fix your XML,tableName[]=' . gettype($tableName) . '!=array,tableTemplate=' . $tableTemplate . ',rowTemplate=' . $rowTemplate);
1948         } elseif (!isFilledArray($columns)) {
1949                 // No columns specified
1950                 reportBug(__FUNCTION__, __LINE__, 'columns is not given. Please fix your XML,tableTemplate=' . $tableTemplate . ',rowTemplate=' . $rowTemplate . ',tableName[0]=' . $tableName[0]);
1951         }
1952
1953         // This is the minimum query, so at least columns and tableName must have entries
1954         $sql = 'SELECT ';
1955
1956         // Get the sql part back from given array
1957         $sql .= getSqlPartFromXmlArray($columns);
1958
1959         // Add "FROM"
1960         $sql .= getSqlXmlFromTable($tableName);
1961
1962         // Add "JOIN"
1963         $sql .= getSqlXmlJoinedTable($tableJoinType, $tableJoinName, $joinOnLeftTable, $joinOnCondition, $joinOnRightTable);
1964
1965         // Add "WHERE"
1966         $sql .= getSqlXmlWhereConditions($whereColumns, $conditions);
1967
1968         // Add "ORDER BY"
1969         $sql .= getSqlXmlOrderBy($orderByColumns);
1970
1971         // Now handle all over to the inner function which will execute the listing
1972         doListEntries($sql, $tableTemplate, $noEntryMessageId, $rowTemplate, $callbackColumns, $extraParameters, $content);
1973 }
1974
1975 // List all given rows (callback function from XML)
1976 function doGenericListEntries ($tableTemplate, $rowTemplate, $noEntryMessageId, $tableName, $columns, $whereColumns, $orderByColumns, $callbackColumns, $extraParameters = array(), $conditions = array(), $content = array()) {
1977         // Verify that tableName and columns are not empty
1978         if ((!is_array($tableName)) || (count($tableName) != 1)) {
1979                 // No tableName specified
1980                 reportBug(__FUNCTION__, __LINE__, 'tableName is not given. Please fix your XML,tableName[]=' . gettype($tableName) . '!=array,tableTemplate=' . $tableTemplate . ',rowTemplate=' . $rowTemplate);
1981         } elseif (!isFilledArray($columns)) {
1982                 // No columns specified
1983                 reportBug(__FUNCTION__, __LINE__, 'columns is not given. Please fix your XML,tableTemplate=' . $tableTemplate . ',rowTemplate=' . $rowTemplate . ',tableName[0]=' . $tableName[0]);
1984         }
1985
1986         // This is the minimum query, so at least columns and tableName must have entries
1987         $sql = 'SELECT ';
1988
1989         // Get the sql part back from given array
1990         $sql .= getSqlPartFromXmlArray($columns);
1991
1992         // Add "FROM"
1993         $sql .= getSqlXmlFromTable($tableName);
1994
1995         // Add "WHERE"
1996         $sql .= getSqlXmlWhereConditions($whereColumns, $conditions);
1997
1998         // Add "ORDER BY"
1999         $sql .= getSqlXmlOrderBy($orderByColumns);
2000
2001         // Now handle all over to the inner function which will execute the listing
2002         doListEntries($sql, $tableTemplate, $noEntryMessageId, $rowTemplate, $callbackColumns, $extraParameters, $content);
2003 }
2004
2005 // Do the listing of entries
2006 function doListEntries ($sql, $tableTemplate, $noEntryMessageId, $rowTemplate, $callbackColumns, $extraParameters = array(), $content = array()) {
2007         // Run the SQL query
2008         $result = sqlQuery($sql, __FUNCTION__, __LINE__);
2009
2010         // Are there some URLs left?
2011         if (!ifSqlHasZeroNums($result)) {
2012                 // List all URLs
2013                 $OUT = '';
2014                 while ($row = sqlFetchArray($result)) {
2015                         // "Translate" content
2016                         foreach ($callbackColumns as $columnName => $callbackName) {
2017                                 // Fill the callback arguments
2018                                 $args = array($row[$columnName]);
2019
2020                                 // Is there more to add?
2021                                 if (isset($extraParameters[$columnName])) {
2022                                         // Add them as well
2023                                         $args = merge_array($args, $extraParameters[$columnName]);
2024                                 } // END - if
2025
2026                                 // Call the callback-function
2027                                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'callbackFunction=' . $callbackName . ',args=<pre>'.print_r($args, TRUE).'</pre>');
2028                                 // @TODO If the EL sub-system can support more than one parameter, this call_user_func_array() can be avoided
2029                                 $row[$columnName] = call_user_func_array($callbackName, $args);
2030                         } // END - foreach
2031
2032                         // Load row template
2033                         $OUT .= loadTemplate(trim($rowTemplate[0]), TRUE, $row);
2034                 } // END - while
2035
2036                 // Is at least one entry set in content?
2037                 if (isFilledArray($content)) {
2038                         // Then add generic 'rows' element
2039                         $content['rows'] = $OUT;
2040                 } else {
2041                         // Direct output is content
2042                         $content = $OUT;
2043                 }
2044
2045                 // Load main template
2046                 loadTemplate(trim($tableTemplate[0]), FALSE, $content);
2047         } else {
2048                 // No URLs in surfbar
2049                 displayMessage('{--' .$noEntryMessageId[0] . '--}');
2050         }
2051
2052         // Free result
2053         sqlFreeResult($result);
2054 }
2055
2056 // Adds a given entry to the database
2057 function doGenericAddEntries ($tableName, $columns = array(), $filterFunctions = array(), $extraValues = array(), $timeColumns = array(), $columnIndex = NULL) {
2058         //* DEBUG: */ die(__FUNCTION__.':columns=<pre>'.print_r($columns,TRUE).'</pre>,filterFunctions=<pre>'.print_r($filterFunctions,TRUE).'</pre>,extraValues=<pre>'.print_r($extraValues,TRUE).'</pre>,timeColumns=<pre>'.print_r($timeColumns,TRUE).'</pre>,columnIndex=<pre>'.print_r($columnIndex,TRUE).'</pre>,POST=<pre>'.print_r($_POST,TRUE).'</pre>');
2059         // Verify that tableName and columns are not empty
2060         if ((!is_array($tableName)) || (count($tableName) != 1)) {
2061                 // No tableName specified
2062                 reportBug(__FUNCTION__, __LINE__, 'tableName is not given. Please fix your XML,tableName[]=' . gettype($tableName) . '!=array: userIdColumn=' . $userIdColumn);
2063         } elseif (!isFilledArray($columns)) {
2064                 // No columns specified
2065                 reportBug(__FUNCTION__, __LINE__, 'columns is not given. Please fix your XML.');
2066         }
2067
2068         // Init columns and value elements
2069         $sqlColumns = array();
2070         $sqlValues  = array();
2071
2072         // Default is that all went fine
2073         $GLOBALS['__XML_PARSE_RESULT'] = TRUE;
2074
2075         // Is there "time columns"?
2076         if (isFilledArray($timeColumns)) {
2077                 // Then "walk" through all entries
2078                 foreach ($timeColumns as $column) {
2079                         // Convert all (possible) selections
2080                         convertSelectionsToEpocheTimeInPostData($column . '_ye');
2081                 } // END - foreach
2082         } // END - if
2083
2084         // Add columns and values
2085         foreach ($columns as $key => $columnName) {
2086                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',columnName=' . $columnName);
2087                 // Is columnIndex set?
2088                 if (!is_null($columnIndex)) {
2089                         // Check conditions
2090                         //* DEBUG: */ die('columnName=<pre>'.print_r($columnName,TRUE).'</pre>columnIndex=<pre>'.print_r($columnIndex,TRUE).'</pre>'.debug_get_printable_backtrace());
2091                         assert((is_array($columnName)) && (is_string($columnIndex)) && (isset($columnName[$columnIndex])));
2092
2093                         // Then use that index "blindly"
2094                         $columnName = $columnName[$columnIndex];
2095                 } // END - if
2096
2097                 // Debug message
2098                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',columnName[' . gettype($columnName) . ']=' . $columnName . ',filterFunctions=' . $filterFunctions[$key] . ',extraValues=' . intval(isset($extraValues[$key])) . ',extraValuesName=' . intval(isset($extraValues[$columnName . '_list'])));
2099
2100                 // Get value back (no array supported)
2101                 $value = postRequestElement($columnName);
2102
2103                 // Is this an array and element 0 is set?
2104                 if ((is_array($value)) && (isset($value[0]))) {
2105                         // Then only take this
2106                         $value = $value[0];
2107                 } // END - if
2108
2109                 // Copy entry securely to the final arrays
2110                 $sqlColumns[$key] = sqlEscapeString($columnName);
2111                 $sqlValues[$key]  = sqlEscapeString($value);
2112
2113                 // Search for it
2114                 $search = key(search_array($columns, 'column', $columnName));
2115
2116                 // Try to handle call-back functions and/or extra values on the list
2117                 //* DEBUG: */ outputHtml($key . '/' . $columnName . '=<pre>'.print_r($columns,true).'</pre>search_array()=<pre>'.print_r(search_array($columns, 'column', $columnName), TRUE).'</pre>');
2118                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'sqlValues[' . $key . '(' . gettype($key) . ')][' . gettype($sqlValues[$key]) . ']=' . $sqlValues[$key] . ' - BEFORE!');
2119                 if (is_string($key)) {
2120                         // Key is a string
2121                         $sqlValues[$key] = doHandleExtraValues($filterFunctions, $extraValues, $key . '_list', $sqlValues[$key], array(''), $search);
2122                 } else {
2123                         // Is a number
2124                         $sqlValues[$key] = doHandleExtraValues($filterFunctions, $extraValues, $key, $sqlValues[$key], array(''), $search);
2125                 }
2126
2127                 // Is the value not a number?
2128                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'sqlValues[' . $key . '(' . gettype($key) . ')][' . gettype($sqlValues[$key]) . ']=' . $sqlValues[$key] . ' - AFTER!');
2129                 if (($sqlValues[$key] != 'NULL') && (is_string($sqlValues[$key]))) {
2130                         // Add quotes around it
2131                         $sqlValues[$key] = chr(39) . $sqlValues[$key] . chr(39);
2132                 } // END - if
2133
2134                 // Is the value false?
2135                 if ($sqlValues[$key] === FALSE) {
2136                         // One "parser" didn't like it
2137                         $GLOBALS['__XML_PARSE_RESULT'] = FALSE;
2138                         break;
2139                 } // END - if
2140         } // END - foreach
2141
2142         // If all values are okay, continue
2143         if ($sqlValues[$key] !== FALSE) {
2144                 // Build the SQL query
2145                 $sql = 'INSERT INTO `{?_MYSQL_PREFIX?}_' . $tableName[0] . '` (`' . implode('`, `', $sqlColumns) . "`) VALUES (" . implode(',', $sqlValues) . ')';
2146
2147                 // Run the SQL query
2148                 sqlQuery($sql, __FUNCTION__, __LINE__);
2149
2150                 // Add id number
2151                 setPostRequestElement('id', getSqlInsertId());
2152
2153                 // Prepare filter data array
2154                 $filterData = array(
2155                         'mode'          => 'add',
2156                         'table_name'    => $tableName,
2157                         'content'       => postRequestArray(),
2158                         'id'            => getSqlInsertId(),
2159                         'subject'       => '',
2160                         // @TODO Used generic 'userid' here
2161                         'userid_column' => array('userid'),
2162                         'raw_userid'    => array('userid'),
2163                         'affected'      => sqlAffectedRows(),
2164                         'sql'           => $sql,
2165                 );
2166
2167                 // Send "build mail" out
2168                 runFilterChain('send_build_mail', $filterData);
2169         } // END - if
2170 }
2171
2172 // Edit rows by given id numbers
2173 function doGenericEditEntriesConfirm ($tableName, $columns = array(), $filterFunctions = array(), $extraValues = array(), $timeColumns = array(), $editNow = array(FALSE), $idColumn = array('id'), $userIdColumn = array('userid'), $rawUserId = array('userid'), $cacheFiles = array(), $subject = '') {
2174         // Is there "time columns"?
2175         if (isFilledArray($timeColumns)) {
2176                 // Then "walk" through all entries
2177                 foreach ($timeColumns as $column) {
2178                         // Convert all (possible) selections
2179                         convertSelectionsToEpocheTimeInPostData($column . '_ye');
2180                 } // END - foreach
2181         } // END - if
2182
2183         // Change them all
2184         $affected = '0';
2185         foreach (postRequestElement($idColumn[0]) as $id => $sel) {
2186                 // Secure id number
2187                 $id = bigintval($id);
2188
2189                 // Prepare content array (new values)
2190                 $content = array();
2191
2192                 // Prepare SQL for this row
2193                 $sql = sprintf('UPDATE `{?_MYSQL_PREFIX?}_%s` SET',
2194                         sqlEscapeString($tableName[0])
2195                 );
2196
2197                 // "Walk" through all entries
2198                 foreach (postRequestArray() as $key => $entries) {
2199                         // Skip raw userid which is always invalid
2200                         if (($key == $rawUserId[0]) || ($key == ($rawUserId[0] . '_raw')) || ($key == 'do_edit')) {
2201                                 // Continue with next field
2202                                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',idColumn[0]=' . $idColumn[0] . ',rawUserId=' . $rawUserId[0]);
2203                                 continue;
2204                         } // END - if
2205
2206                         // Debug message
2207                         //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',id=' . $id . ',idColumn[0]=' . $idColumn[0] . ',entries=<pre>'.print_r($entries,TRUE).'</pre>');
2208
2209                         // Is entries an array?
2210                         if (($key != $idColumn[0]) && (is_array($entries)) && (isset($entries[$id]))) {
2211                                 // Search for the right array index
2212                                 $search = key(search_array($columns, 'column', $key));
2213
2214                                 // Add this entry to content
2215                                 $content[$key] = $entries[$id];
2216
2217                                 // Debug message
2218                                 //* BUG: */ die($key.'/'.$id.'/'.$search.'=<pre>'.print_r($columns,TRUE).'</pre><pre>'.print_r($filterFunctions,TRUE).'</pre>');
2219
2220                                 // Handle possible call-back functions and/or extra values
2221                                 $entries[$id] = doHandleExtraValues($filterFunctions, $extraValues, $key, $entries[$id], $userIdColumn, $search);
2222
2223                                 // Add key/value pair to SQL string
2224                                 $sql .= addKeyValueSql($key, $entries[$id]);
2225                         } elseif (($key != $idColumn[0]) && (!is_array($entries))) {
2226                                 // Search for it
2227                                 $search = key(search_array($columns, 'column', $key));
2228                                 //* BUG: */ die($key.'/<pre>'.print_r($search, TRUE).'</pre>=<pre>'.print_r($columns, TRUE).'</pre>');
2229
2230                                 // Debug message
2231                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',entries[' . gettype($entries) . ']=' . $entries . ',search=' . $search . ' - BEFORE!');
2232
2233                                 // Add normal entries as well
2234                                 $content[$key] = $entries;
2235
2236                                 // Handle possible call-back functions and/or extra values
2237                                 $entries = doHandleExtraValues($filterFunctions, $extraValues, $key, $entries, $userIdColumn, $search);
2238
2239                                 // Debug message
2240                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',entries[' . gettype($entries) . ']=' . $entries . ',search=' . $search . ' - AFTER!');
2241
2242                                 // Add key/value pair to SQL string
2243                                 $sql .= addKeyValueSql($key, $entries);
2244                         }
2245                 } // END - foreach
2246
2247                 // Finish SQL command
2248                 $sql = substr($sql, 0, -1) . " WHERE `" . sqlEscapeString($idColumn[0]) . "`=" . $id;
2249                 if ((isset($rawUserId[0])) && (isset($userIdColumn[0])) && (isPostRequestElementSet($rawUserId[0])) && (!is_array(postRequestElement($rawUserId[0])))) {
2250                         // Add user id as well
2251                         $sql .= ' AND `' . $userIdColumn[0] . '`=' . bigintval(postRequestElement($rawUserId[0]));
2252                 } // END - if
2253                 $sql .= " LIMIT 1";
2254
2255                 // Run this query
2256                 //* BUG: */ die($sql.'<pre>'.print_r(postRequestArray(), TRUE).'</pre>');
2257                 sqlQuery($sql, __FUNCTION__, __LINE__);
2258
2259                 // Add affected rows
2260                 $edited = sqlAffectedRows();
2261                 $affected += $edited;
2262
2263                 // Load all data from that id
2264                 $result = sqlQueryEscaped("SELECT * FROM `{?_MYSQL_PREFIX?}_%s` WHERE `%s`=%s LIMIT 1",
2265                         array(
2266                                 $tableName[0],
2267                                 $idColumn[0],
2268                                 $id
2269                         ), __FUNCTION__, __LINE__);
2270
2271                 // Fetch the data and merge it into $content
2272                 $content = merge_array($content, sqlFetchArray($result));
2273
2274                 // Prepare filter data array
2275                 $filterData = array(
2276                         'mode'          => 'edit',
2277                         'table_name'    => $tableName,
2278                         'content'       => $content,
2279                         'id'            => $id,
2280                         'subject'       => $subject,
2281                         'userid_column' => $userIdColumn,
2282                         'raw_userid'    => $rawUserId,
2283                         'affected'      => $edited,
2284                         'sql'           => $sql,
2285                 );
2286
2287                 // Send "build mail" out
2288                 runFilterChain('send_build_mail', $filterData);
2289
2290                 // Free the result
2291                 sqlFreeResult($result);
2292         } // END - foreach
2293
2294         // Delete cache?
2295         if ((isFilledArray($cacheFiles)) && (!empty($cacheFiles[0]))) {
2296                 // Delete cache file(s)
2297                 foreach ($cacheFiles as $cache) {
2298                         // Skip any empty entries
2299                         if (empty($cache)) {
2300                                 // This may cause trouble in loadCacheFile()
2301                                 continue;
2302                         } // END - if
2303
2304                         // Use rebuildCache() to delete it
2305                         rebuildCache($cache);
2306                 } // END - foreach
2307         } // END - if
2308
2309         // Return affected rows
2310         return $affected;
2311 }
2312
2313 // Delete rows by given id numbers
2314 function doGenericDeleteEntriesConfirm ($tableName, $columns = array(), $filterFunctions = array(), $extraValues = array(), $deleteNow = array(FALSE), $idColumn = array('id'), $userIdColumn = array('userid'), $rawUserId = array('userid'), $cacheFiles = array()) {
2315         // The base SQL command:
2316         $sql = "DELETE LOW_PRIORITY FROM `{?_MYSQL_PREFIX?}_%s` WHERE `%s` IN (%s)";
2317
2318         // Is a user id provided?
2319         //* BUG: */ die('<pre>'.print_r($rawUserId,TRUE).'</pre><pre>'.print_r($userIdColumn,TRUE).'</pre>');
2320         if ((isset($rawUserId[0])) && (isset($userIdColumn[0])) && (isPostRequestElementSet($rawUserId[0])) && (!is_array(postRequestElement($rawUserId[0])))) {
2321                 // Add user id as well
2322                 $sql .= ' AND `' . $userIdColumn[0] . '`=' . bigintval(postRequestElement($rawUserId[0]));
2323         } // END - if
2324
2325         // $idColumn[0] in POST must be an array again
2326         if (!is_array(postRequestElement($idColumn[0]))) {
2327                 // This indicates that you have conflicting form field naming with XML names
2328                 reportBug(__FUNCTION__, __LINE__, 'You have a wrong form field element, idColumn[0]=' . $idColumn[0]);
2329         } // END - if
2330
2331         // Delete them all
2332         //* BUG: */ die($sql.'<pre>'.print_r($tableName,TRUE).'</pre><pre>'.print_r($columns,TRUE).'</pre><pre>'.print_r($filterFunctions,TRUE).'</pre><pre>'.print_r($extraValues,TRUE).'</pre><pre>'.print_r($deleteNow,TRUE).'</pre><pre>'.print_r($idColumn,TRUE).'</pre>');
2333         $idList = '';
2334         foreach (postRequestElement($idColumn[0]) as $id => $sel) {
2335                 // Is id zero?
2336                 if (!isValidId($id)) {
2337                         // Then skip this
2338                         continue;
2339                 } // END - if
2340
2341                 // Is there a userid?
2342                 if (isPostRequestElementSet($userIdColumn[0])) {
2343                         // Load all data from that id
2344                         $result = sqlQueryEscaped("SELECT * FROM `{?_MYSQL_PREFIX?}_%s` WHERE `%s`=%s LIMIT 1",
2345                                 array(
2346                                         $tableName[0],
2347                                         $idColumn[0],
2348                                         $id
2349                                 ), __FUNCTION__, __LINE__);
2350
2351                         // Fetch the data
2352                         $content = sqlFetchArray($result);
2353
2354                         // Free the result
2355                         sqlFreeResult($result);
2356
2357                         // Send "build mails" out
2358                         sendGenericBuildMails('delete', $tableName, $content, $id, '', $userIdColumn);
2359                 } // END - if
2360
2361                 // Add id number
2362                 $idList .= $id . ',';
2363         } // END - foreach
2364
2365         // Run the query
2366         sqlQueryEscaped($sql,
2367                 array(
2368                         $tableName[0],
2369                         $idColumn[0],
2370                         convertNullToZero(substr($idList, 0, -1))
2371                 ), __FUNCTION__, __LINE__);
2372
2373         // Return affected rows
2374         return sqlAffectedRows();
2375 }
2376
2377 // Build a special template list
2378 // @TODO cacheFiles is not yet supported
2379 function doGenericListBuilder ($prefix, $listType, $tableName, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn, $rawUserId = array('userid'), $content = array()) {
2380         // $tableName and $idColumn must bove be arrays!
2381         if ((!is_array($tableName)) || (count($tableName) != 1)) {
2382                 // $tableName is no array
2383                 reportBug(__FUNCTION__, __LINE__, 'tableName[]=' . gettype($tableName) . '!=array: userIdColumn=' . $userIdColumn);
2384         } elseif (!is_array($idColumn)) {
2385                 // $idColumn is no array
2386                 reportBug(__FUNCTION__, __LINE__, 'idColumn[]=' . gettype($idColumn) . '!=array: userIdColumn=' . $userIdColumn);
2387         } elseif ((!is_array($userIdColumn)) || (count($userIdColumn) != 1)) {
2388                 // $tableName is no array
2389                 reportBug(__FUNCTION__, __LINE__, 'userIdColumn[]=' . gettype($userIdColumn) . '!=array: userIdColumn=' . $userIdColumn);
2390         }
2391
2392         // Init row output
2393         $OUT = '';
2394
2395         // "Walk" through all entries
2396         //* DEBUG: */ reportBug(__FUNCTION__, __LINE__, 'listType=<pre>'.print_r($listType,TRUE).'</pre>,tableName<pre>'.print_r($tableName,TRUE).'</pre>,columns=<pre>'.print_r($columns,TRUE).'</pre>,filterFunctions=<pre>'.print_r($filterFunctions,TRUE).'</pre>,extraValues=<pre>'.print_r($extraValues,TRUE).'</pre>,idColumn=<pre>'.print_r($idColumn,TRUE).'</pre>,userIdColumn=<pre>'.print_r($userIdColumn,TRUE).'</pre>,rawUserId=<pre>'.print_r($rawUserId,TRUE).'</pre>');
2397         foreach (postRequestElement($idColumn[0]) as $id => $selected) {
2398                 // Secure id number
2399                 $id = bigintval($id);
2400
2401                 // Get result from a given column array and table name
2402                 $result = getSqlResultFromArray($tableName[0], $columns, $idColumn[0], $id, __FUNCTION__, __LINE__);
2403
2404                 // Is there one entry?
2405                 if (sqlNumRows($result) == 1) {
2406                         // Load all data
2407                         $row = sqlFetchArray($result);
2408
2409                         // Filter all data
2410                         foreach ($row as $key => $value) {
2411                                 // Search index
2412                                 $idx  = searchXmlArray($key, $columns, 'column');
2413
2414                                 // Default name is NULL
2415                                 $name = NULL;
2416
2417                                 // Is the name there?
2418                                 if (isset($columns[$idx]['name'])) {
2419                                         // Then use it
2420                                         $name = $columns[$idx]['name'];
2421                                 } // END - if
2422
2423                                 // Skip any missing entries
2424                                 if ($idx === FALSE) {
2425                                         // Skip this one
2426                                         //* DEBUG: */ reportBug(__FUNCTION__, __LINE__, 'key=' . $key . ' - SKIPPED!');
2427                                         continue;
2428                                 } // END - if
2429
2430                                 // Is there a userid?
2431                                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',userIdColumn=' . $userIdColumn[0]);
2432                                 if ($key == $userIdColumn[0]) {
2433                                         // Add it again as raw id
2434                                         //* DEBUG: */ reportBug(__FUNCTION__, __LINE__, 'key=' . $key . ',userIdColumn=' . $userIdColumn[0]);
2435                                         $row[$userIdColumn[0]] = convertZeroToNull($value);
2436                                         $row[$userIdColumn[0] . '_raw'] = $row[$userIdColumn[0]];
2437                                 } // END - if
2438
2439                                 // If the key matches the idColumn variable, we need to temporary remember it
2440                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',idColumn=' . $idColumn[0] . ',value=' . $value);
2441                                 if ($key == $idColumn[0]) {
2442                                         /*
2443                                          * Found, so remember it securely (to make sure only id
2444                                          * numbers can pass, don't use alpha-numerical values!)
2445                                          */
2446                                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $value . ' - set as ' . $prefix . '_list_builder_id_value!');
2447                                         $GLOBALS[$prefix . '_list_builder_id_value'] = bigintval($value);
2448                                 } // END - if
2449
2450                                 // Try to handle call-back functions and/or extra values
2451                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'idx=' . $idx . ',row[' . $key . ']=' . $row[$key]);
2452                                 //if ($key == 'forced_campaign_created') die($idx.'=<pre>'.print_r($columns,true).'</pre><pre>'.print_r($extraValues,true).'</pre>');
2453                                 $row[$key] = doHandleExtraValues($filterFunctions, $extraValues, $idx, $row[$key], $userIdColumn, ((!is_null($name)) ? $name : $key), $id);
2454                         } // END - foreach
2455
2456                         // Then list it
2457                         $OUT .= loadTemplate(sprintf('%s_%s_%s_row',
2458                                 $prefix,
2459                                 $listType,
2460                                 $tableName[0]
2461                                 ), TRUE, $row
2462                         );
2463                 } // END - if
2464
2465                 // Free the result
2466                 sqlFreeResult($result);
2467         } // END - foreach
2468
2469         // Is there an entry in $content?
2470         if (isFilledArray($content)) {
2471                 // Use generic 'rows'
2472                 $content['rows'] = $OUT;
2473         } else {
2474                 // Use direct output
2475                 $content = $OUT;
2476         }
2477
2478         // Load master template
2479         loadTemplate(
2480                 sprintf('%s_%s_%s',
2481                         $prefix,
2482                         $listType,
2483                         $tableName[0]
2484                 ), FALSE, $content
2485         );
2486 }
2487
2488 // Adds key/value pair to a working SQL string together
2489 function addKeyValueSql ($key, $value) {
2490         // Init SQL
2491         $sql = '';
2492
2493         // Is it NULL?
2494         if (($value == 'NULL') || (is_null($value))) {
2495                 // Add key with NULL
2496                 $sql .= sprintf(' `%s`=NULL,',
2497                         sqlEscapeString($key)
2498                 );
2499         } elseif ((is_double($value)) || (is_float($value)) || (is_int($value))) {
2500                 // Is a number, so addd it directly
2501                 $sql .= sprintf(' `%s`=%s,',
2502                         sqlEscapeString($key),
2503                         $value
2504                 );
2505         } else {
2506                 // Else add the value escape'd
2507                 $sql .= sprintf(" `%s`='%s',",
2508                         sqlEscapeString($key),
2509                         sqlEscapeString($value)
2510                 );
2511         }
2512
2513         // Return SQL string
2514         return $sql;
2515 }
2516
2517 // "Getter" for an array from given table and columns
2518 function getArrayFromTable ($tableName, $columns, $orderBy, $ordered = 'ASC', $whereSql = '') {
2519         // The table must exist
2520         assert(ifSqlTableExists($tableName));
2521
2522         // Search for it
2523         $result = sqlQueryEscaped('SELECT
2524         `' . implode('`, `', $columns) . '`
2525 FROM
2526         `{?_MYSQL_PREFIX?}_%s`
2527 ' . $whereSql . '
2528 ORDER BY
2529         `%s` %S',
2530                 array(
2531                         $tableName,
2532                         $orderBy,
2533                         $ordered
2534                 ), __FUNCTION__, __LINE__
2535         );
2536
2537         // Init array
2538         $rows = array();
2539
2540         // Are there entries?
2541         if (!ifSqlHasZeroNums($result)) {
2542                 // Load all entries
2543                 while ($row = sqlFetchArray($result)) {
2544                         array_push($rows, $row);
2545                 } // END - while
2546         } // END - if
2547
2548         // Free result
2549         sqlFreeResult($result);
2550
2551         // Return all found rows
2552         return $rows;
2553 }
2554
2555 // [EOF]
2556 ?>