Updated copyright year.
[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 - 2016 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 (!ifSqlHasZeroNumRows($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 (!ifSqlHasZeroNumRows($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 (!ifSqlHasZeroNumRows($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 = (!ifSqlHasZeroNumRows($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                 return '{--_CATEGORY_NONE--}';
878         } // END - if
879
880         // Lookup the category in database
881         $result = sqlQueryEscaped('SELECT `cat` FROM `{?_MYSQL_PREFIX?}_cats` WHERE `id`=%s LIMIT 1',
882                 array(bigintval($cid)), __FUNCTION__, __LINE__);
883
884         if (sqlNumRows($result) == 1) {
885                 // Category found... :-)
886                 $data = sqlFetchArray($result);
887         } // END - if
888
889         // Free result
890         sqlFreeResult($result);
891
892         // Return result
893         return $data['cat'];
894 }
895
896 // Get a string of "mail title" and price back
897 function getPaymentTitlePrice ($paymentsId, $full = FALSE) {
898         // Only title or also including price?
899         if ($full === FALSE) {
900                 $ret = getPaymentData($paymentsId, 'main_title');
901         } else {
902                 $ret = getPaymentData($paymentsId, 'main_title') . ' / {%pipe,getPaymentData,translateComma=' . $paymentsId . '%} {?POINTS?}';
903         }
904
905         // Return result
906         return $ret;
907 }
908
909 // Get payment price
910 function getPaymentPrice ($paymentsId) {
911         // Return result
912         return getPaymentData($paymentsId, 'price');
913 }
914
915 // Get payment time
916 function getPaymentTime ($paymentsId) {
917         // Return result
918         return getPaymentData($paymentsId, 'time');
919 }
920
921 // Get payment 'payment'
922 function getPaymentPayment ($paymentsId) {
923         // Return result
924         return getPaymentData($paymentsId, 'payment');
925 }
926
927 // "Getter" for payment data (cached)
928 function getPaymentData ($paymentsId, $lookFor) {
929         // Default value...
930         $data[$lookFor] = NULL;
931
932         // Is there cache?
933         if (isset($GLOBALS['cache_array']['payments'][$lookFor][$paymentsId])) {
934                 // Use it if found to save SQL queries
935                 $data[$lookFor] = $GLOBALS['cache_array']['payments'][$lookFor][$paymentsId];
936
937                 // Update cache hits
938                 incrementStatsEntry('cache_hits');
939         } elseif (!isExtensionActive('cache')) {
940                 // Search for it in database
941                 $result = sqlQueryEscaped('SELECT `%s` FROM `{?_MYSQL_PREFIX?}_payments` WHERE `id`=%s LIMIT 1',
942                         array(
943                                 $lookFor,
944                                 bigintval($paymentsId)
945                         ), __FUNCTION__, __LINE__);
946
947                 // Is the entry there?
948                 if (sqlNumRows($result) == 1) {
949                         // Payment type found... :-)
950                         $data = sqlFetchArray($result);
951                 } // END - if
952
953                 // Free result
954                 sqlFreeResult($result);
955         }
956
957         // Return value
958         return $data[$lookFor];
959 }
960
961 // Remove a receiver's id from $receivers and add a link for him to confirm
962 function removeReceiver (&$receivers, $key, $userid, $poolId, $statsId = 0, $isBonusMail = FALSE) {
963         // Default is not removed
964         $ret = 'failed';
965
966         // Is the userid valid?
967         if (isValidId($userid)) {
968                 // Remove entry from array
969                 unset($receivers[$key]);
970
971                 // Is there already a line for this user available?
972                 if (isValidId($statsId)) {
973                         // Default is 'normal' mail
974                         $type = 'NORMAL';
975                         $rowName = 'stats_id';
976
977                         // Only when we got a real stats id continue searching for the entry
978                         if ($isBonusMail === TRUE) {
979                                 $type = 'BONUS';
980                                 $rowName = 'bonus_id';
981                         } // END - if
982
983                         // Try to look the entry up
984                         $result = sqlQueryEscaped("SELECT `id` FROM `{?_MYSQL_PREFIX?}_user_links` WHERE `%s`=%s AND `userid`=%s AND `link_type`='%s' LIMIT 1",
985                                 array(
986                                         $rowName,
987                                         bigintval($statsId),
988                                         bigintval($userid),
989                                         $type
990                                 ), __FUNCTION__, __LINE__);
991
992                         // Was it *not* found?
993                         if (ifSqlHasZeroNumRows($result)) {
994                                 // So we add one!
995                                 sqlQueryEscaped("INSERT INTO `{?_MYSQL_PREFIX?}_user_links` (`%s`, `userid`, `link_type`) VALUES (%s,%s,'%s')",
996                                         array(
997                                                 $rowName,
998                                                 bigintval($statsId),
999                                                 bigintval($userid),
1000                                                 $type
1001                                         ), __FUNCTION__, __LINE__);
1002
1003                                 // Update 'mails_sent' if ext-sql_patches is updated
1004                                 if (isExtensionInstalledAndNewer('sql_patches', '0.7.4')) {
1005                                         // Update the pool
1006                                         updatePoolDataById($poolId, 'mails_sent', 1, '+');
1007                                 } // END - if
1008                                 $ret = 'done';
1009                         } else {
1010                                 // Already found
1011                                 $ret = 'already';
1012                         }
1013
1014                         // Free memory
1015                         sqlFreeResult($result);
1016                 } // END - if
1017         } // END - if
1018
1019         // Return status for sending routine
1020         return $ret;
1021 }
1022
1023 // Calculate sum (default) or count records of given criteria
1024 function countSumTotalData ($search, $tableName, $lookFor = 'id', $whereStatement = 'userid', $countRows = FALSE, $add = '', $mode = '=') {
1025         // Debug message
1026         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'search=' . $search . ',tableName=' . $tableName . ',lookFor=' . $lookFor . ',whereStatement=' . $whereStatement . ',add=' . $add);
1027         if ((empty($search)) && (!is_null($search))) {
1028                 // Count or sum whole table?
1029                 if ($countRows === TRUE) {
1030                         // Count whole table
1031                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'COUNT!');
1032                         $result = sqlQueryEscaped('SELECT COUNT(`%s`) AS `res` FROM `{?_MYSQL_PREFIX?}_%s`' . $add . ' LIMIT 1',
1033                                 array(
1034                                         $lookFor,
1035                                         $tableName
1036                                 ), __FUNCTION__, __LINE__);
1037                 } else {
1038                         // Sum whole table
1039                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'SUM!');
1040                         $result = sqlQueryEscaped('SELECT SUM(`%s`) AS `res` FROM `{?_MYSQL_PREFIX?}_%s`' . $add . ' LIMIT 1',
1041                                 array(
1042                                         $lookFor,
1043                                         $tableName
1044                                 ), __FUNCTION__, __LINE__);
1045                 }
1046         } elseif (($countRows === TRUE) || ($lookFor == 'userid')) {
1047                 // Count rows
1048                 if (is_null($search)) {
1049                         // Fix mode
1050                         if ($mode == '=') {
1051                                 $mode = 'IS';
1052                         } elseif ($mode == '!=') {
1053                                 $mode = 'IS NOT';
1054                         }
1055
1056                         // Look for NULL/0
1057                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'COUNT-NULL!');
1058                         $result = sqlQueryEscaped("SELECT COUNT(`%s`) AS `res` FROM `{?_MYSQL_PREFIX?}_%s` WHERE (`%s` %s NULL OR `%s`=0)" . $add . ' LIMIT 1',
1059                                 array(
1060                                         $lookFor,
1061                                         $tableName,
1062                                         $whereStatement,
1063                                         $mode,
1064                                         $whereStatement
1065                                 ), __FUNCTION__, __LINE__);
1066                 } else {
1067                         // Regular entry
1068                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'COUNT!');
1069                         $result = sqlQueryEscaped("SELECT COUNT(`%s`) AS `res` FROM `{?_MYSQL_PREFIX?}_%s` WHERE `%s`%s'%s'" . $add . ' LIMIT 1',
1070                                 array(
1071                                         $lookFor,
1072                                         $tableName,
1073                                         $whereStatement,
1074                                         $mode,
1075                                         $search
1076                                 ), __FUNCTION__, __LINE__);
1077                 }
1078         } else {
1079                 // Sum all rows
1080                 if (is_null($search)) {
1081                         // Fix mode
1082                         if ($mode == '=') {
1083                                 $mode = 'IS';
1084                         } elseif ($mode == '!=') {
1085                                 $mode = 'IS NOT';
1086                         }
1087
1088                         // Look for NULL/0
1089                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'SUM-NULL!');
1090                         $result = sqlQueryEscaped("SELECT SUM(`%s`) AS `res` FROM `{?_MYSQL_PREFIX?}_%s` WHERE (`%s` %s NULL OR `%s`=0)" . $add . ' LIMIT 1',
1091                                 array(
1092                                         $lookFor,
1093                                         $tableName,
1094                                         $whereStatement,
1095                                         $mode,
1096                                         $whereStatement
1097                                 ), __FUNCTION__, __LINE__);
1098                 } else {
1099                         // Regular entry
1100                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'SUM!');
1101                         $result = sqlQueryEscaped("SELECT SUM(`%s`) AS `res` FROM `{?_MYSQL_PREFIX?}_%s` WHERE `%s`%s'%s'" . $add . ' LIMIT 1',
1102                                 array(
1103                                         $lookFor,
1104                                         $tableName,
1105                                         $whereStatement,
1106                                         $mode,
1107                                         $search
1108                                 ), __FUNCTION__, __LINE__);
1109                 }
1110         }
1111
1112         // Load row
1113         $data = sqlFetchArray($result);
1114
1115         // Free result
1116         sqlFreeResult($result);
1117
1118         // Fix empty values
1119         if ((empty($data['res'])) && ($lookFor != 'counter') && ($lookFor != 'id') && ($lookFor != 'userid') && ($lookFor != 'rallye_id')) {
1120                 // Float number
1121                 $data['res'] = '0.00000';
1122         } elseif ('' . $data['res'] . '' == '') {
1123                 // Fix empty result
1124                 $data['res'] = '0';
1125         }
1126
1127         // Return value
1128         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'res=' . $data['res']);
1129         return $data['res'];
1130 }
1131
1132 /**
1133  * Sends out mail to all administrators. This function is no longer obsolete
1134  * because we need it when there is no ext-admins installed
1135  */
1136 function sendAdminEmails ($subject, $message, $isBugReport = FALSE) {
1137         // Default is no special header
1138         $mailHeader = '';
1139
1140         // Is it a bug report?
1141         if ($isBugReport === TRUE) {
1142                 // Then add a reply-to line back to the author (me)
1143                 $mailHeader = 'Reply-To: webmaster@mxchange.org' . PHP_EOL;
1144         } // END - if
1145
1146         // Load all admin email addresses
1147         $result = sqlQuery('SELECT `email` FROM `{?_MYSQL_PREFIX?}_admins` ORDER BY `id` ASC', __FUNCTION__, __LINE__);
1148
1149         // And send the notification to all of them
1150         while ($content = sqlFetchArray($result)) {
1151                 // Send the email out
1152                 sendEmail($content['email'], $subject, $message, 'N', $mailHeader);
1153         } // END - if
1154
1155         // Free result
1156         sqlFreeResult($result);
1157
1158         // Really simple... ;-)
1159 }
1160
1161 // Get id number from administrator's login name
1162 function getAdminId ($adminLogin) {
1163         // By default no admin is found
1164         $data['id'] = -1;
1165
1166         // Check cache
1167         if (isset($GLOBALS['cache_array']['admin']['admin_id'][$adminLogin])) {
1168                 // Use it if found to save SQL queries
1169                 $data['id'] = $GLOBALS['cache_array']['admin']['admin_id'][$adminLogin];
1170
1171                 // Update cache hits
1172                 incrementStatsEntry('cache_hits');
1173         } elseif (!isExtensionActive('cache')) {
1174                 // Load from database
1175                 $result = sqlQueryEscaped("SELECT `id` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `login`='%s' LIMIT 1",
1176                         array($adminLogin), __FUNCTION__, __LINE__);
1177
1178                 // Is there an entry?
1179                 if (sqlNumRows($result) == 1) {
1180                         // Get it
1181                         $data = sqlFetchArray($result);
1182                 } // END - if
1183
1184                 // Free result
1185                 sqlFreeResult($result);
1186         }
1187
1188         // Return the id
1189         return $data['id'];
1190 }
1191
1192 // "Getter" for current admin id
1193 function getCurrentAdminId () {
1194         // Log debug message
1195         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'called!');
1196
1197         // Is there cache?
1198         if (!isset($GLOBALS['current_admin_id'])) {
1199                 // Get the admin login from session
1200                 $adminId = getSession('admin_id');
1201
1202                 // Remember in cache securely
1203                 setCurrentAdminId(bigintval($adminId));
1204         } // END - if
1205
1206         // Return it
1207         return $GLOBALS['current_admin_id'];
1208 }
1209
1210 // Setter for current admin id
1211 function setCurrentAdminId ($currentAdminId) {
1212         // Set it secured
1213         $GLOBALS['current_admin_id'] = bigintval($currentAdminId);
1214 }
1215
1216 // Get password hash from administrator's login name
1217 function getAdminHash ($adminId) {
1218         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'adminId=' . $adminId . ' - ENTERED!');
1219         // By default an invalid hash is returned
1220         $data['password'] = -1;
1221
1222         // Is admin hash set?
1223         if (isAdminHashSet($adminId)) {
1224                 // Check cache
1225                 $data['password'] = $GLOBALS['cache_array']['admin']['password'][$adminId];
1226
1227                 // Update cache hits
1228                 incrementStatsEntry('cache_hits');
1229         } elseif (!isExtensionActive('cache')) {
1230                 // Load from database
1231                 $result = sqlQueryEscaped("SELECT `password` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
1232                         array(bigintval($adminId)), __FUNCTION__, __LINE__);
1233
1234                 // Is there an entry?
1235                 if (sqlNumRows($result) == 1) {
1236                         // Fetch data
1237                         $data = sqlFetchArray($result);
1238
1239                         // Set cache
1240                         setAdminHash($adminId, $data['password']);
1241                 } // END - if
1242
1243                 // Free result
1244                 sqlFreeResult($result);
1245         }
1246
1247         // Return password hash
1248         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'adminId=' . $adminId . ',data[password]=' . $data['password'] . ' - EXIT!');
1249         return $data['password'];
1250 }
1251
1252 // "Getter" for admin login
1253 function getAdminLogin ($adminId) {
1254         // By default a non-existent login is returned (other functions react on this!)
1255         $data['login'] = '***';
1256
1257         if (isset($GLOBALS['cache_array']['admin']['login'][$adminId])) {
1258                 // Get cache
1259                 $data['login'] = $GLOBALS['cache_array']['admin']['login'][$adminId];
1260
1261                 // Update cache hits
1262                 incrementStatsEntry('cache_hits');
1263         } elseif (!isExtensionActive('cache')) {
1264                 // Load from database
1265                 $result = sqlQueryEscaped("SELECT `login` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
1266                         array(bigintval($adminId)), __FUNCTION__, __LINE__);
1267
1268                 // Entry found?
1269                 if (sqlNumRows($result) == 1) {
1270                         // Fetch data
1271                         $data = sqlFetchArray($result);
1272
1273                         // Set cache
1274                         $GLOBALS['cache_array']['admin']['login'][$adminId] = $data['login'];
1275                 } // END - if
1276
1277                 // Free memory
1278                 sqlFreeResult($result);
1279         }
1280
1281         // Return the result
1282         return $data['login'];
1283 }
1284
1285 // Get email address of admin id
1286 function getAdminEmail ($adminId) {
1287         // By default an invalid emails is returned
1288         $data['email'] = '***';
1289
1290         if (isset($GLOBALS['cache_array']['admin']['email'][$adminId])) {
1291                 // Get cache
1292                 $data['email'] = $GLOBALS['cache_array']['admin']['email'][$adminId];
1293
1294                 // Update cache hits
1295                 incrementStatsEntry('cache_hits');
1296         } elseif (!isExtensionActive('cache')) {
1297                 // Load from database
1298                 $result_admin_id = sqlQueryEscaped("SELECT `email` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
1299                         array(bigintval($adminId)), __FUNCTION__, __LINE__);
1300
1301                 // Entry found?
1302                 if (sqlNumRows($result_admin_id) == 1) {
1303                         // Get data
1304                         $data = sqlFetchArray($result_admin_id);
1305
1306                         // Set cache
1307                         $GLOBALS['cache_array']['admin']['email'][$adminId] = $data['email'];
1308                 } // END - if
1309
1310                 // Free result
1311                 sqlFreeResult($result_admin_id);
1312         }
1313
1314         // Return email
1315         return $data['email'];
1316 }
1317
1318 // Get default ACL of admin id
1319 function getAdminDefaultAcl ($adminId) {
1320         // By default an invalid ACL value is returned
1321         $data['default_acl'] = 'NO-ACL';
1322
1323         // Is ext-sql_patches there and was it found in cache?
1324         if (!isExtensionActive('sql_patches')) {
1325                 // Not found, which is bad, so we need to allow all
1326                 $data['default_acl'] = 'allow';
1327         } elseif (isset($GLOBALS['cache_array']['admin']['default_acl'][$adminId])) {
1328                 // Use cache
1329                 $data['default_acl'] = $GLOBALS['cache_array']['admin']['default_acl'][$adminId];
1330
1331                 // Update cache hits
1332                 incrementStatsEntry('cache_hits');
1333         } elseif (!isExtensionActive('cache')) {
1334                 // Load from database
1335                 $result_admin_id = sqlQueryEscaped("SELECT `default_acl` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
1336                         array(bigintval($adminId)), __FUNCTION__, __LINE__);
1337
1338                 // Is there an entry?
1339                 if (sqlNumRows($result_admin_id) == 1) {
1340                         // Fetch data
1341                         $data = sqlFetchArray($result_admin_id);
1342
1343                         // Set cache
1344                         $GLOBALS['cache_array']['admin']['default_acl'][$adminId] = $data['default_acl'];
1345                 }
1346
1347                 // Free result
1348                 sqlFreeResult($result_admin_id);
1349         }
1350
1351         // Return default ACL
1352         return $data['default_acl'];
1353 }
1354
1355 // Get menu mode (la_mode) of admin id
1356 function getAdminMenuMode ($adminId) {
1357         // By default an invalid mode
1358         $data['la_mode'] = 'INVALID';
1359
1360         // Is ext-sql_patches there and was it found in cache?
1361         if (!isExtensionActive('sql_patches')) {
1362                 // Not found, which is bad, so we need to allow all
1363                 $data['la_mode'] = 'global';
1364         } elseif (isset($GLOBALS['cache_array']['admin']['la_mode'][$adminId])) {
1365                 // Use cache
1366                 $data['la_mode'] = $GLOBALS['cache_array']['admin']['la_mode'][$adminId];
1367
1368                 // Update cache hits
1369                 incrementStatsEntry('cache_hits');
1370         } elseif (!isExtensionActive('cache')) {
1371                 // Load from database
1372                 $result_admin_id = sqlQueryEscaped("SELECT `la_mode` FROM `{?_MYSQL_PREFIX?}_admins` WHERE `id`=%s LIMIT 1",
1373                         array(bigintval($adminId)), __FUNCTION__, __LINE__);
1374
1375                 // Is there an entry?
1376                 if (sqlNumRows($result_admin_id) == 1) {
1377                         // Fetch data
1378                         $data = sqlFetchArray($result_admin_id);
1379
1380                         // Set cache
1381                         $GLOBALS['cache_array']['admin']['la_mode'][$adminId] = $data['la_mode'];
1382                 }
1383
1384                 // Free result
1385                 sqlFreeResult($result_admin_id);
1386         }
1387
1388         // Return default ACL
1389         return $data['la_mode'];
1390 }
1391
1392 // Generates an option list from various parameters
1393 function generateOptions ($table, $key, $value, $default = '', $extra = '', $whereStatement = '', $disabled = array(), $callback = '', $allowNone = FALSE) {
1394         $ret = '';
1395
1396         // Allow none?
1397         if ($allowNone === TRUE) {
1398                 // Add option for none
1399                 $ret .= '<option value="0">{--SELECT_NONE--}</option>';
1400         } // END - if
1401
1402         if ($table == '/ARRAY/') {
1403                 // Selection from array
1404                 if ((is_array($key)) && (is_array($value)) && ((count($key)) == (count($value)) || (!empty($callback)))) {
1405                         // Both are arrays
1406                         foreach ($key as $idx => $optionValue) {
1407                                 $ret .= '<option value="' . $optionValue . '"';
1408                                 if ($default == $optionValue) {
1409                                         // Selected by default
1410                                         $ret .= ' selected="selected"';
1411                                 } elseif (isset($disabled[$optionValue])) {
1412                                         // Disabled!
1413                                         $ret .= ' disabled="disabled"';
1414                                 }
1415
1416                                 // Is the call-back function set?
1417                                 if (!empty($callback)) {
1418                                         // Call it
1419                                         $value[$idx] = call_user_func_array($callback, array($key[$idx]));
1420                                 } // END - if
1421
1422                                 // Finish option tag
1423                                 $ret .= '>' . $value[$idx] . '</option>';
1424                         } // END - foreach
1425                 } else {
1426                         // Problem in request
1427                         reportBug(__FUNCTION__, __LINE__, 'Not all are arrays: key[' . count($key) . ']=' . gettype($key) . ',value[' . count($value) . ']=' . gettype($value) . ',callback=' . $callback);
1428                 }
1429         } else {
1430             ///////////////////////
1431                 // Data from database /
1432                 ///////////////////////
1433
1434                 // Init extra column (if requested)
1435                 $extraColumn = '';
1436                 if (!empty($extra)) {
1437                         $extraColumn = ',`' . $extra . '` AS `extra`';
1438                 } // END - if
1439
1440                 // Run SQL query
1441                 $result = sqlQueryEscaped("SELECT `%s` AS `key`, `%s` AS `value`" . $extraColumn . " FROM `{?_MYSQL_PREFIX?}_%s` " . $whereStatement . " ORDER BY `%s` ASC",
1442                         array(
1443                                 $key,
1444                                 $value,
1445                                 $table,
1446                                 $value
1447                         ), __FUNCTION__, __LINE__);
1448
1449                 // Is there rows?
1450                 if (!ifSqlHasZeroNumRows($result)) {
1451                         // Found data so add them as OPTION lines
1452                         while ($content = sqlFetchArray($result)) {
1453                                 // Is extra set?
1454                                 if (!isset($content['extra'])) {
1455                                         // Set it to empty
1456                                         $content['extra'] = '';
1457                                 } // END - if
1458
1459                                 $ret .= '<option value="' . $content['key'] . '"';
1460
1461                                 if ($default == $content['key']) {
1462                                         // Selected by default
1463                                         $ret .= ' selected="selected"';
1464                                 } elseif (isset($disabled[$content['key']])) {
1465                                         // Disabled!
1466                                         $ret .= ' disabled="disabled"';
1467                                 }
1468
1469                                 // Add it, if set
1470                                 if (!empty($content['extra'])) {
1471                                         $content['extra'] = ' (' . $content['extra'] . ')';
1472                                 } // END - if
1473
1474                                 // Is the call-back function set?
1475                                 if (!empty($callback)) {
1476                                         // Call it
1477                                         $content['value'] = call_user_func_array($callback, array($content['value']));
1478                                 } // END - if
1479
1480                                 // Finish option list
1481                                 $ret .= '>' . $content['value'] . $content['extra'] . '</option>';
1482                         } // END - while
1483                 } else {
1484                         // No data found
1485                         $ret = '<option value="x">{--SELECT_NONE--}</option>';
1486                 }
1487
1488                 // Free memory
1489                 sqlFreeResult($result);
1490         }
1491
1492         // Return - hopefully - the requested data
1493         return $ret;
1494 }
1495
1496 // Deletes a user account with given reason
1497 function deleteUserAccount ($userid, $reason) {
1498         // Init points
1499         $data['points'] = '0';
1500
1501         // Search for the points and user data
1502         $result = sqlQueryEscaped("SELECT
1503         (SUM(`p`.`points`) - `d`.`used_points`) AS `points`
1504 FROM
1505         `{?_MYSQL_PREFIX?}_user_points` AS `p`
1506 LEFT JOIN
1507         `{?_MYSQL_PREFIX?}_user_data` AS `d`
1508 ON
1509         `p`.`userid`=`d`.`userid`
1510 WHERE
1511         `p`.`userid`=%s
1512 LIMIT 1",
1513                 array(bigintval($userid)), __FUNCTION__, __LINE__);
1514
1515         // Is there an entry?
1516         if (sqlNumRows($result) == 1) {
1517                 // Save his points to add them to the jackpot
1518                 $data = sqlFetchArray($result);
1519
1520                 // Delete points entries as well
1521                 // @TODO Rewrite these lines to a filter
1522                 sqlQueryEscaped("DELETE LOW_PRIORITY FROM `{?_MYSQL_PREFIX?}_user_points` WHERE `userid`=%s",
1523                         array(bigintval($userid)), __FUNCTION__, __LINE__);
1524
1525                 // Update mediadata as well
1526                 if (isExtensionInstalledAndNewer('mediadata', '0.0.4')) {
1527                         // Update database
1528                         updateMediadataEntry(array('total_points'), 'sub', $data['points']);
1529                 } // END - if
1530
1531                 // Now, when we have all his points adds them do the jackpot!
1532                 if (isExtensionActive('jackpot')) {
1533                         addPointsToJackpot($data['points']);
1534                 } // END - if
1535         } // END - if
1536
1537         // Free the result
1538         sqlFreeResult($result);
1539
1540         // Delete category selections as well...
1541         sqlQueryEscaped("DELETE LOW_PRIORITY FROM `{?_MYSQL_PREFIX?}_user_cats` WHERE `userid`=%s",
1542                 array(bigintval($userid)), __FUNCTION__, __LINE__);
1543
1544         // Remove from rallye if found
1545         // @TODO Rewrite this to a filter
1546         if (isExtensionActive('rallye')) {
1547                 sqlQueryEscaped("DELETE LOW_PRIORITY FROM `{?_MYSQL_PREFIX?}_rallye_users` WHERE `userid`=%s",
1548                         array(bigintval($userid)), __FUNCTION__, __LINE__);
1549         } // END - if
1550
1551         // Add reason and translate points
1552         $data['text'] = $reason;
1553
1554         // Now a mail to the user and that's all...
1555         $message = loadEmailTemplate('member_user_deleted', $data, $userid);
1556         sendEmail($userid, '{--ADMIN_DELETE_ACCOUNT--}', $message);
1557
1558         // Ok, delete the account!
1559         sqlQueryEscaped("DELETE LOW_PRIORITY FROM `{?_MYSQL_PREFIX?}_user_data` WHERE `userid`=%s LIMIT 1", array(bigintval($userid)), __FUNCTION__, __LINE__);
1560 }
1561
1562 // Gets the matching what name from module
1563 function getWhatFromModule ($modCheck) {
1564         // Is the request element set?
1565         if (isGetRequestElementSet('what')) {
1566                 // Then return this!
1567                 return getRequestElement('what');
1568         } // END - if
1569
1570         // Default is empty
1571         $what = '';
1572
1573         // Check on given module
1574         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'modCheck=' . $modCheck);
1575         switch ($modCheck) {
1576                 case 'index': // Guest area
1577                         // Is ext-sql_patches installed and newer than 0.0.5?
1578                         if (isExtensionInstalledAndNewer('sql_patches', '0.0.5')) {
1579                                 // Use it from config
1580                                 $what = getIndexHome();
1581                         } else {
1582                                 // Use default 'welcome'
1583                                 $what = 'welcome';
1584                         }
1585                         break;
1586
1587                 default: // Default for all other menus (getIndexHome() is for index module only)
1588                         $what = 'welcome';
1589                         break;
1590         } // END - switch
1591
1592         // Return what value
1593         return $what;
1594 }
1595
1596 // Returns HTML code with an option list of all categories
1597 function generateCategoryOptionsList ($mode, $userid = NULL) {
1598         // Prepare WHERE statement
1599         $whereStatement = " WHERE `visible`='Y'";
1600         if (isAdmin()) $whereStatement = '';
1601
1602         // Initialize array...
1603         $categories = array(
1604                 'id'      => array(),
1605                 'name'    => array(),
1606                 'userids' => array()
1607         );
1608
1609         // Get categories
1610         $result = sqlQuery('SELECT
1611         `id`,
1612         `cat`
1613 FROM
1614         `{?_MYSQL_PREFIX?}_cats`
1615 ' . $whereStatement . '
1616 ORDER BY
1617         `sort` ASC',
1618                 __FUNCTION__, __LINE__);
1619
1620         // Are there entries?
1621         if (!ifSqlHasZeroNumRows($result)) {
1622                 // ... and begin loading stuff
1623                 while ($content = sqlFetchArray($result)) {
1624                         // Transfer some data
1625                         $categories['id'][]   = $content['id'];
1626                         array_push($categories['name'], $content['cat']);
1627
1628                         // Check which users are in this category
1629                         $result_userids = sqlQueryEscaped("SELECT `userid` FROM `{?_MYSQL_PREFIX?}_user_cats` WHERE `cat_id`=%s AND `userid` != %s ORDER BY `userid` ASC",
1630                                 array(
1631                                         bigintval($content['id']),
1632                                         convertNullToZero($userid)
1633                                 ), __FUNCTION__, __LINE__);
1634
1635                         // Init count
1636                         $userid_cnt = '0';
1637
1638                         // Start adding all
1639                         while ($data = sqlFetchArray($result_userids)) {
1640                                 // Add user count
1641                                 $userid_cnt += countSumTotalData($data['userid'], 'user_data', 'userid', 'userid', TRUE, runFilterChain('user_exclusion_sql', " AND `status`='CONFIRMED' AND `receive_mails` > 0"));
1642                         } // END - while
1643
1644                         // Free memory
1645                         sqlFreeResult($result_userids);
1646
1647                         // Add counter
1648                         array_push($categories['userids'], $userid_cnt);
1649                 } // END - while
1650
1651                 // Free memory
1652                 sqlFreeResult($result);
1653
1654                 // Generate options
1655                 $OUT = '';
1656                 foreach ($categories['id'] as $key => $value) {
1657                         $OUT .= '      <option value="' . $value . '">' . $categories['name'][$key] . ' (' . $categories['userids'][$key] . ' {--USERS_IN_CATEGORY--})</option>';
1658                 } // END - foreach
1659         } else {
1660                 // No cateogries are defined yet
1661                 $OUT = '<option class="bad">{--MEMBER_NO_CATEGORIES--}</option>';
1662         }
1663
1664         // Return HTML code
1665         return $OUT;
1666 }
1667
1668 // Add bonus mail to queue
1669 function addBonusMailToQueue ($subject, $text, $receiverList, $points, $seconds, $url, $categoryId, $mode='normal', $receiver=0) {
1670         // Is admin or bonus extension there?
1671         if (!isAdmin()) {
1672                 // Abort here
1673                 return FALSE;
1674         } elseif (!isExtensionActive('bonus')) {
1675                 // Abort here
1676                 return FALSE;
1677         }
1678
1679         // Calculcate target sent
1680         $target = countSelection(explode(';', $receiverList));
1681
1682         // Receiver is zero?
1683         if ($receiver == '0') {
1684                 // Then auto-fix it
1685                 $receiver = $target;
1686         } // END - if
1687
1688         // HTML extension active?
1689         if (isExtensionActive('html_mail')) {
1690                 // Add HTML mail
1691                 sqlQueryEscaped("INSERT INTO `{?_MYSQL_PREFIX?}_bonus` (
1692         `subject`,
1693         `text`,
1694         `receivers`,
1695         `points`,
1696         `time`,
1697         `data_type`,
1698         `timestamp`,
1699         `url`,
1700         `cat_id`,
1701         `target_send`,
1702         `mails_sent`,
1703         `html_msg`
1704 ) VALUES (
1705         '%s',
1706         '%s',
1707         '%s',
1708         %s,
1709         %s,
1710         'NEW',
1711         UNIX_TIMESTAMP(),
1712         '%s',
1713         %s,
1714         %s,
1715         %s,
1716         '%s'
1717 )",
1718                 array(
1719                         $subject,
1720                         $text,
1721                         $receiverList,
1722                         $points,
1723                         bigintval($seconds),
1724                         $url,
1725                         bigintval($categoryId),
1726                         $target,
1727                         bigintval($receiver),
1728                         convertBooleanToYesNo($mode == 'html')
1729                 ), __FUNCTION__, __LINE__);
1730         } else {
1731                 // Add regular mail
1732                 sqlQueryEscaped("INSERT INTO `{?_MYSQL_PREFIX?}_bonus` (
1733         `subject`,
1734         `text`,
1735         `receivers`,
1736         `points`,
1737         `time`,
1738         `data_type`,
1739         `timestamp`,
1740         `url`,
1741         `cat_id`,
1742         `target_send`,
1743         `mails_sent`
1744 ) VALUES (
1745         '%s',
1746         '%s',
1747         '%s',
1748         %s,
1749         %s,
1750         'NEW',
1751         UNIX_TIMESTAMP(),
1752         '%s',
1753         %s,
1754         %s,
1755         %s
1756 )",
1757                 array(
1758                         $subject,
1759                         $text,
1760                         $receiverList,
1761                         $points,
1762                         bigintval($seconds),
1763                         $url,
1764                         bigintval($categoryId),
1765                         $target,
1766                         bigintval($receiver),
1767                 ), __FUNCTION__, __LINE__);
1768         }
1769 }
1770
1771 // Generate a receiver list for given category and maximum receivers
1772 function generateReceiverList ($categoryId, $receiver, $mode = '') {
1773         // Init variables
1774         $extraColumns = '';
1775         $receiverList = '';
1776         $result       = FALSE;
1777
1778         // Secure data
1779         $categoryId = bigintval($categoryId);
1780         $receiver   = bigintval($receiver);
1781
1782         // Is the receiver zero and mode set?
1783         if (($receiver == '0') && (!empty($mode))) {
1784                 // Auto-fix receiver maximum
1785                 $receiver = getTotalReceivers($mode);
1786         } // END - if
1787
1788         // Exclude (maybe exclude) testers
1789         $addWhere = runFilterChain('user_exclusion_sql', ' ');
1790
1791         // Category given?
1792         if (isValidId($categoryId)) {
1793                 // Select category
1794                 $extraColumns  = "LEFT JOIN `{?_MYSQL_PREFIX?}_user_cats` AS `c` ON `d`.`userid`=`c`.`userid`";
1795                 $addWhere = sprintf(' AND `c`.`cat_id`=%s', $categoryId);
1796         } // END - if
1797
1798         // Exclude users in holiday?
1799         if (isExtensionInstalledAndNewer('holiday', '0.1.3')) {
1800                 // Add something for the holiday extension
1801                 $addWhere .= " AND `d`.`holiday_active`='N'";
1802         } // END - if
1803
1804         // Run query
1805         $result = sqlQueryEscaped("SELECT
1806         `d`.`userid`
1807 FROM
1808         `{?_MYSQL_PREFIX?}_user_data` AS `d`
1809         " . $extraColumns . "
1810 WHERE
1811         `d`.`status`='CONFIRMED'
1812         " . $addWhere . "
1813 ORDER BY
1814         `d`.`{?order_select?}` {?order_mode?}
1815 LIMIT %s",
1816                 array(
1817                         $receiver
1818                 ), __FUNCTION__, __LINE__);
1819
1820         // Entries found?
1821         if ((sqlNumRows($result) >= $receiver) && ($receiver > 0)) {
1822                 // Load all entries
1823                 while ($content = sqlFetchArray($result)) {
1824                         // Add receiver when not empty
1825                         if (!empty($content['userid'])) {
1826                                 $receiverList .= $content['userid'] . ';';
1827                         } // END - if
1828                 } // END - while
1829
1830                 // Free memory
1831                 sqlFreeResult($result);
1832
1833                 // Remove trailing semicolon
1834                 $receiverList = substr($receiverList, 0, -1);
1835         } // END - if
1836
1837         // Return list
1838         return $receiverList;
1839 }
1840
1841 // Recuce the amount of received emails for the receipients for given email
1842 function reduceRecipientReceivedMails ($column, $id, $count) {
1843         // Search for mail in database
1844         $result = sqlQueryEscaped("SELECT * FROM `{?_MYSQL_PREFIX?}_user_links` WHERE `%s`=%s ORDER BY `userid` ASC LIMIT %s",
1845                 array(
1846                         $column,
1847                         bigintval($id),
1848                         $count
1849                 ), __FUNCTION__, __LINE__
1850         );
1851
1852         // Are there entries?
1853         if (!ifSqlHasZeroNumRows($result)) {
1854                 // Now load all userids for one big query!
1855                 $userids = array();
1856                 while ($data = sqlFetchArray($result)) {
1857                         // By default reduce and found no emails
1858                         $num = 0;
1859
1860                         // We must now look if he has already confirmed this mail, so might sound double, but it may resolve problems
1861                         // @TODO Rewrite this to a filter
1862                         if ((isset($data['stats_id'])) && (isValidId($data['stats_id']))) {
1863                                 // User email
1864                                 $num = countSumTotalData($data['userid'], 'user_stats_data', 'id', 'userid', TRUE, sprintf(" AND `stats_type`='mailid' AND `stats_data`=%s", bigintval($data['stats_id'])));
1865                         } elseif ((isset($data['bonus_id'])) && (isValidId($data['bonus_id']))) {
1866                                 // Bonus mail
1867                                 $num = countSumTotalData($data['userid'], 'user_stats_data', 'id', 'userid', TRUE, sprintf(" AND `stats_type`='bonusid' AND `stats_data`=%s", bigintval($data['bonus_id'])));
1868                         }
1869
1870                         // Reduce this users total received emails?
1871                         if ($num === 0) {
1872                                 $userids[$data['userid']] = $data['userid'];
1873                         } // END - if
1874                 } // END - while
1875
1876                 if (isFilledArray($userids)) {
1877                         // Now update all user accounts
1878                         sqlQueryEscaped("UPDATE `{?_MYSQL_PREFIX?}_user_data` SET `emails_received`=`emails_received`-1 WHERE `userid` IN (%s) LIMIT %s",
1879                                 array(
1880                                         implode(',', $userids),
1881                                         count($userids)
1882                                 ), __FUNCTION__, __LINE__);
1883                 } else {
1884                         // Nothing deleted
1885                         displayMessage('{%message,ADMIN_MAIL_NOTHING_DELETED=' . $id . '%}');
1886                 }
1887         } // END - if
1888
1889         // Free result
1890         sqlFreeResult($result);
1891 }
1892
1893 // Creates a new task
1894 function createNewTask ($subject, $notes, $taskType, $userid = NULL, $adminId = NULL, $strip = TRUE) {
1895         // Insert the task data into the database
1896         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())",
1897                 array(
1898                         convertZeroToNull($adminId),
1899                         convertZeroToNull($userid),
1900                         $taskType,
1901                         $subject,
1902                         $notes
1903                 ), __FUNCTION__, __LINE__, TRUE, $strip);
1904
1905         // Return insert id which is the task id
1906         return getSqlInsertId();
1907 }
1908
1909 // Updates last module / online time
1910 function updateLastActivity ($userid) {
1911         // Is 'what' set?
1912         if (isWhatSet()) {
1913                 // Run the update query
1914                 sqlQueryEscaped("UPDATE
1915         `{?_MYSQL_PREFIX?}_user_data`
1916 SET
1917         `{%%pipe,getUserLastWhatName%%}`='{%%pipe,getWhat%%}',
1918         `last_online`=UNIX_TIMESTAMP(),
1919         `REMOTE_ADDR`='{%%pipe,detectRemoteAddr%%}'
1920 WHERE
1921         `userid`=%s
1922 LIMIT 1",
1923                 array(
1924                         bigintval($userid)
1925                 ), __FUNCTION__, __LINE__);
1926         } else {
1927                 // No what set, needs to be ignored (last_module is last_what)
1928                 sqlQueryEscaped("UPDATE
1929         `{?_MYSQL_PREFIX?}_user_data`
1930 SET
1931         `{%%pipe,getUserLastWhatName%%}`=NULL,
1932         `last_online`=UNIX_TIMESTAMP(),
1933         `REMOTE_ADDR`='{%%pipe,detectRemoteAddr%%}'
1934 WHERE
1935         `userid`=%s
1936 LIMIT 1",
1937                 array(
1938                         bigintval($userid)
1939                 ), __FUNCTION__, __LINE__);
1940         }
1941 }
1942
1943 // List all given joined rows (callback function from XML)
1944 function doGenericJoinedListEntries ($tableTemplate, $rowTemplate, $noEntryMessageId, $tableName, $tableJoinType, $tableJoinName, $joinOnLeftTable, $joinOnCondition, $joinOnRightTable, $columns, $whereColumns, $orderByColumns, $callbackColumns, $extraParameters = array(), $conditions = array(), $content = array()) {
1945         // Verify that tableName and columns are not empty
1946         if ((!is_array($tableName)) || (count($tableName) != 1)) {
1947                 // No tableName specified
1948                 reportBug(__FUNCTION__, __LINE__, 'tableName is not given. Please fix your XML,tableName[]=' . gettype($tableName) . '!=array,tableTemplate=' . $tableTemplate . ',rowTemplate=' . $rowTemplate);
1949         } elseif (!isFilledArray($columns)) {
1950                 // No columns specified
1951                 reportBug(__FUNCTION__, __LINE__, 'columns is not given. Please fix your XML,tableTemplate=' . $tableTemplate . ',rowTemplate=' . $rowTemplate . ',tableName[0]=' . $tableName[0]);
1952         }
1953
1954         // This is the minimum query, so at least columns and tableName must have entries
1955         $sql = 'SELECT ';
1956
1957         // Get the sql part back from given array
1958         $sql .= getSqlPartFromXmlArray($columns);
1959
1960         // Add "FROM"
1961         $sql .= getSqlXmlFromTable($tableName);
1962
1963         // Add "JOIN"
1964         $sql .= getSqlXmlJoinedTable($tableJoinType, $tableJoinName, $joinOnLeftTable, $joinOnCondition, $joinOnRightTable);
1965
1966         // Add "WHERE"
1967         $sql .= getSqlXmlWhereConditions($whereColumns, $conditions);
1968
1969         // Add "ORDER BY"
1970         $sql .= getSqlXmlOrderBy($orderByColumns);
1971
1972         // Now handle all over to the inner function which will execute the listing
1973         doListEntries($sql, $tableTemplate, $noEntryMessageId, $rowTemplate, $callbackColumns, $extraParameters, $content);
1974 }
1975
1976 // List all given rows (callback function from XML)
1977 function doGenericListEntries ($tableTemplate, $rowTemplate, $noEntryMessageId, $tableName, $columns, $whereColumns, $orderByColumns, $callbackColumns, $extraParameters = array(), $conditions = array(), $content = array()) {
1978         // Verify that tableName and columns are not empty
1979         if ((!is_array($tableName)) || (count($tableName) != 1)) {
1980                 // No tableName specified
1981                 reportBug(__FUNCTION__, __LINE__, 'tableName is not given. Please fix your XML,tableName[]=' . gettype($tableName) . '!=array,tableTemplate=' . $tableTemplate . ',rowTemplate=' . $rowTemplate);
1982         } elseif (!isFilledArray($columns)) {
1983                 // No columns specified
1984                 reportBug(__FUNCTION__, __LINE__, 'columns is not given. Please fix your XML,tableTemplate=' . $tableTemplate . ',rowTemplate=' . $rowTemplate . ',tableName[0]=' . $tableName[0]);
1985         }
1986
1987         // This is the minimum query, so at least columns and tableName must have entries
1988         $sql = 'SELECT ';
1989
1990         // Get the sql part back from given array
1991         $sql .= getSqlPartFromXmlArray($columns);
1992
1993         // Add "FROM"
1994         $sql .= getSqlXmlFromTable($tableName);
1995
1996         // Add "WHERE"
1997         $sql .= getSqlXmlWhereConditions($whereColumns, $conditions);
1998
1999         // Add "ORDER BY"
2000         $sql .= getSqlXmlOrderBy($orderByColumns);
2001
2002         // Now handle all over to the inner function which will execute the listing
2003         doListEntries($sql, $tableTemplate, $noEntryMessageId, $rowTemplate, $callbackColumns, $extraParameters, $content);
2004 }
2005
2006 // Do the listing of entries
2007 function doListEntries ($sql, $tableTemplate, $noEntryMessageId, $rowTemplate, $callbackColumns, $extraParameters = array(), $content = array()) {
2008         // Run the SQL query
2009         $result = sqlQuery($sql, __FUNCTION__, __LINE__);
2010
2011         // Are there some URLs left?
2012         if (!ifSqlHasZeroNumRows($result)) {
2013                 // List all URLs
2014                 $OUT = '';
2015                 while ($row = sqlFetchArray($result)) {
2016                         // "Translate" content
2017                         foreach ($callbackColumns as $columnName => $callbackName) {
2018                                 // Fill the callback arguments
2019                                 $args = array($row[$columnName]);
2020
2021                                 // Is there more to add?
2022                                 if (isset($extraParameters[$columnName])) {
2023                                         // Add them as well
2024                                         $args = merge_array($args, $extraParameters[$columnName]);
2025                                 } // END - if
2026
2027                                 // Call the callback-function
2028                                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'callbackFunction=' . $callbackName . ',args=<pre>'.print_r($args, TRUE).'</pre>');
2029                                 // @TODO If the EL sub-system can support more than one parameter, this call_user_func_array() can be avoided
2030                                 $row[$columnName] = call_user_func_array($callbackName, $args);
2031                         } // END - foreach
2032
2033                         // Load row template
2034                         $OUT .= loadTemplate(trim($rowTemplate[0]), TRUE, $row);
2035                 } // END - while
2036
2037                 // Is at least one entry set in content?
2038                 if (isFilledArray($content)) {
2039                         // Then add generic 'rows' element
2040                         $content['rows'] = $OUT;
2041                 } else {
2042                         // Direct output is content
2043                         $content = $OUT;
2044                 }
2045
2046                 // Load main template
2047                 loadTemplate(trim($tableTemplate[0]), FALSE, $content);
2048         } else {
2049                 // No URLs in surfbar
2050                 displayMessage('{--' .$noEntryMessageId[0] . '--}');
2051         }
2052
2053         // Free result
2054         sqlFreeResult($result);
2055 }
2056
2057 // Adds a given entry to the database
2058 function doGenericAddEntries ($tableName, $columns = array(), $filterFunctions = array(), $extraValues = array(), $timeColumns = array(), $columnIndex = NULL) {
2059         //* 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>');
2060         // Verify that tableName and columns are not empty
2061         if ((!is_array($tableName)) || (count($tableName) != 1)) {
2062                 // No tableName specified
2063                 reportBug(__FUNCTION__, __LINE__, 'tableName is not given. Please fix your XML,tableName[]=' . gettype($tableName) . '!=array: userIdColumn=' . $userIdColumn);
2064         } elseif (!isFilledArray($columns)) {
2065                 // No columns specified
2066                 reportBug(__FUNCTION__, __LINE__, 'columns is not given. Please fix your XML.');
2067         }
2068
2069         // Init columns and value elements
2070         $sqlColumns = array();
2071         $sqlValues  = array();
2072
2073         // Default is that all went fine
2074         $GLOBALS['__XML_PARSE_RESULT'] = TRUE;
2075
2076         // Is there "time columns"?
2077         if (isFilledArray($timeColumns)) {
2078                 // Then "walk" through all entries
2079                 foreach ($timeColumns as $column) {
2080                         // Convert all (possible) selections
2081                         convertSelectionsToEpocheTimeInPostData($column . '_ye');
2082                 } // END - foreach
2083         } // END - if
2084
2085         // Add columns and values
2086         foreach ($columns as $key => $columnName) {
2087                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',columnName=' . $columnName);
2088                 // Is columnIndex set?
2089                 if (!is_null($columnIndex)) {
2090                         // Check conditions
2091                         //* DEBUG: */ die('columnName=<pre>'.print_r($columnName,TRUE).'</pre>columnIndex=<pre>'.print_r($columnIndex,TRUE).'</pre>'.debug_get_printable_backtrace());
2092                         assert((is_array($columnName)) && (is_string($columnIndex)) && (isset($columnName[$columnIndex])));
2093
2094                         // Then use that index "blindly"
2095                         $columnName = $columnName[$columnIndex];
2096                 } // END - if
2097
2098                 // Debug message
2099                 //* 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'])));
2100
2101                 // Get value back (no array supported)
2102                 $value = postRequestElement($columnName);
2103
2104                 // Is this an array and element 0 is set?
2105                 if ((is_array($value)) && (isset($value[0]))) {
2106                         // Then only take this
2107                         $value = $value[0];
2108                 } // END - if
2109
2110                 // Copy entry securely to the final arrays
2111                 $sqlColumns[$key] = sqlEscapeString($columnName);
2112                 $sqlValues[$key]  = sqlEscapeString($value);
2113
2114                 // Search for it
2115                 $search = key(search_array($columns, 'column', $columnName));
2116
2117                 // Try to handle call-back functions and/or extra values on the list
2118                 //* DEBUG: */ outputHtml($key . '/' . $columnName . '=<pre>'.print_r($columns,true).'</pre>search_array()=<pre>'.print_r(search_array($columns, 'column', $columnName), TRUE).'</pre>');
2119                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'sqlValues[' . $key . '(' . gettype($key) . ')][' . gettype($sqlValues[$key]) . ']=' . $sqlValues[$key] . ' - BEFORE!');
2120                 if (is_string($key)) {
2121                         // Key is a string
2122                         $sqlValues[$key] = doHandleExtraValues($filterFunctions, $extraValues, $key . '_list', $sqlValues[$key], array(''), $search);
2123                 } else {
2124                         // Is a number
2125                         $sqlValues[$key] = doHandleExtraValues($filterFunctions, $extraValues, $key, $sqlValues[$key], array(''), $search);
2126                 }
2127
2128                 // Is the value not a number?
2129                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'sqlValues[' . $key . '(' . gettype($key) . ')][' . gettype($sqlValues[$key]) . ']=' . $sqlValues[$key] . ' - AFTER!');
2130                 if (($sqlValues[$key] != 'NULL') && (is_string($sqlValues[$key]))) {
2131                         // Add quotes around it
2132                         $sqlValues[$key] = chr(39) . $sqlValues[$key] . chr(39);
2133                 } // END - if
2134
2135                 // Is the value false?
2136                 if ($sqlValues[$key] === FALSE) {
2137                         // One "parser" didn't like it
2138                         $GLOBALS['__XML_PARSE_RESULT'] = FALSE;
2139                         break;
2140                 } // END - if
2141         } // END - foreach
2142
2143         // If all values are okay, continue
2144         if ($sqlValues[$key] !== FALSE) {
2145                 // Build the SQL query
2146                 $sql = 'INSERT INTO `{?_MYSQL_PREFIX?}_' . $tableName[0] . '` (`' . implode('`, `', $sqlColumns) . "`) VALUES (" . implode(',', $sqlValues) . ')';
2147
2148                 // Run the SQL query
2149                 sqlQuery($sql, __FUNCTION__, __LINE__);
2150
2151                 // Add id number
2152                 setPostRequestElement('id', getSqlInsertId());
2153
2154                 // Prepare filter data array
2155                 $filterData = array(
2156                         'mode'          => 'add',
2157                         'table_name'    => $tableName,
2158                         'content'       => postRequestArray(),
2159                         'id'            => getSqlInsertId(),
2160                         'subject'       => '',
2161                         // @TODO Used generic 'userid' here
2162                         'userid_column' => array('userid'),
2163                         'raw_userid'    => array('userid'),
2164                         'affected'      => sqlAffectedRows(),
2165                         'sql'           => $sql,
2166                 );
2167
2168                 // Send "build mail" out
2169                 runFilterChain('send_build_mail', $filterData);
2170         } // END - if
2171 }
2172
2173 // Edit rows by given id numbers
2174 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 = '') {
2175         // Is there "time columns"?
2176         if (isFilledArray($timeColumns)) {
2177                 // Then "walk" through all entries
2178                 foreach ($timeColumns as $column) {
2179                         // Convert all (possible) selections
2180                         convertSelectionsToEpocheTimeInPostData($column . '_ye');
2181                 } // END - foreach
2182         } // END - if
2183
2184         // Change them all
2185         $affected = '0';
2186         foreach (postRequestElement($idColumn[0]) as $id => $sel) {
2187                 // Secure id number
2188                 $id = bigintval($id);
2189
2190                 // Prepare content array (new values)
2191                 $content = array();
2192
2193                 // Prepare SQL for this row
2194                 $sql = sprintf('UPDATE `{?_MYSQL_PREFIX?}_%s` SET',
2195                         sqlEscapeString($tableName[0])
2196                 );
2197
2198                 // "Walk" through all entries
2199                 foreach (postRequestArray() as $key => $entries) {
2200                         // Skip raw userid which is always invalid
2201                         if (($key == $rawUserId[0]) || ($key == ($rawUserId[0] . '_raw')) || ($key == 'do_edit')) {
2202                                 // Continue with next field
2203                                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',idColumn[0]=' . $idColumn[0] . ',rawUserId=' . $rawUserId[0]);
2204                                 continue;
2205                         } // END - if
2206
2207                         // Debug message
2208                         //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',id=' . $id . ',idColumn[0]=' . $idColumn[0] . ',entries=<pre>'.print_r($entries,TRUE).'</pre>');
2209
2210                         // Is entries an array?
2211                         if (($key != $idColumn[0]) && (is_array($entries)) && (isset($entries[$id]))) {
2212                                 // Search for the right array index
2213                                 $search = key(search_array($columns, 'column', $key));
2214
2215                                 // Add this entry to content
2216                                 $content[$key] = $entries[$id];
2217
2218                                 // Debug message
2219                                 //* BUG: */ die($key.'/'.$id.'/'.$search.'=<pre>'.print_r($columns,TRUE).'</pre><pre>'.print_r($filterFunctions,TRUE).'</pre>');
2220
2221                                 // Handle possible call-back functions and/or extra values
2222                                 $entries[$id] = doHandleExtraValues($filterFunctions, $extraValues, $key, $entries[$id], $userIdColumn, $search);
2223
2224                                 // Add key/value pair to SQL string
2225                                 $sql .= addKeyValueSql($key, $entries[$id]);
2226                         } elseif (($key != $idColumn[0]) && (!is_array($entries))) {
2227                                 // Search for it
2228                                 $search = key(search_array($columns, 'column', $key));
2229                                 //* BUG: */ die($key.'/<pre>'.print_r($search, TRUE).'</pre>=<pre>'.print_r($columns, TRUE).'</pre>');
2230
2231                                 // Debug message
2232                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',entries[' . gettype($entries) . ']=' . $entries . ',search=' . $search . ' - BEFORE!');
2233
2234                                 // Add normal entries as well
2235                                 $content[$key] = $entries;
2236
2237                                 // Handle possible call-back functions and/or extra values
2238                                 $entries = doHandleExtraValues($filterFunctions, $extraValues, $key, $entries, $userIdColumn, $search);
2239
2240                                 // Debug message
2241                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',entries[' . gettype($entries) . ']=' . $entries . ',search=' . $search . ' - AFTER!');
2242
2243                                 // Add key/value pair to SQL string
2244                                 $sql .= addKeyValueSql($key, $entries);
2245                         }
2246                 } // END - foreach
2247
2248                 // Finish SQL command
2249                 $sql = substr($sql, 0, -1) . " WHERE `" . sqlEscapeString($idColumn[0]) . "`=" . $id;
2250                 if ((isset($rawUserId[0])) && (isset($userIdColumn[0])) && (isPostRequestElementSet($rawUserId[0])) && (!is_array(postRequestElement($rawUserId[0])))) {
2251                         // Add user id as well
2252                         $sql .= ' AND `' . $userIdColumn[0] . '`=' . bigintval(postRequestElement($rawUserId[0]));
2253                 } // END - if
2254                 $sql .= " LIMIT 1";
2255
2256                 // Run this query
2257                 //* BUG: */ die($sql.'<pre>'.print_r(postRequestArray(), TRUE).'</pre>');
2258                 sqlQuery($sql, __FUNCTION__, __LINE__);
2259
2260                 // Add affected rows
2261                 $edited = sqlAffectedRows();
2262                 $affected += $edited;
2263
2264                 // Load all data from that id
2265                 $result = sqlQueryEscaped("SELECT * FROM `{?_MYSQL_PREFIX?}_%s` WHERE `%s`=%s LIMIT 1",
2266                         array(
2267                                 $tableName[0],
2268                                 $idColumn[0],
2269                                 $id
2270                         ), __FUNCTION__, __LINE__);
2271
2272                 // Fetch the data and merge it into $content
2273                 $content = merge_array($content, sqlFetchArray($result));
2274
2275                 // Prepare filter data array
2276                 $filterData = array(
2277                         'mode'          => 'edit',
2278                         'table_name'    => $tableName,
2279                         'content'       => $content,
2280                         'id'            => $id,
2281                         'subject'       => $subject,
2282                         'userid_column' => $userIdColumn,
2283                         'raw_userid'    => $rawUserId,
2284                         'affected'      => $edited,
2285                         'sql'           => $sql,
2286                 );
2287
2288                 // Send "build mail" out
2289                 runFilterChain('send_build_mail', $filterData);
2290
2291                 // Free the result
2292                 sqlFreeResult($result);
2293         } // END - foreach
2294
2295         // Delete cache?
2296         if ((isFilledArray($cacheFiles)) && (!empty($cacheFiles[0]))) {
2297                 // Delete cache file(s)
2298                 foreach ($cacheFiles as $cache) {
2299                         // Skip any empty entries
2300                         if (empty($cache)) {
2301                                 // This may cause trouble in loadCacheFile()
2302                                 continue;
2303                         } // END - if
2304
2305                         // Use rebuildCache() to delete it
2306                         rebuildCache($cache);
2307                 } // END - foreach
2308         } // END - if
2309
2310         // Return affected rows
2311         return $affected;
2312 }
2313
2314 // Delete rows by given id numbers
2315 function doGenericDeleteEntriesConfirm ($tableName, $columns = array(), $filterFunctions = array(), $extraValues = array(), $deleteNow = array(FALSE), $idColumn = array('id'), $userIdColumn = array('userid'), $rawUserId = array('userid'), $cacheFiles = array()) {
2316         // The base SQL command:
2317         $sql = "DELETE LOW_PRIORITY FROM `{?_MYSQL_PREFIX?}_%s` WHERE `%s` IN (%s)";
2318
2319         // Is a user id provided?
2320         //* BUG: */ die('<pre>'.print_r($rawUserId,TRUE).'</pre><pre>'.print_r($userIdColumn,TRUE).'</pre>');
2321         if ((isset($rawUserId[0])) && (isset($userIdColumn[0])) && (isPostRequestElementSet($rawUserId[0])) && (!is_array(postRequestElement($rawUserId[0])))) {
2322                 // Add user id as well
2323                 $sql .= ' AND `' . $userIdColumn[0] . '`=' . bigintval(postRequestElement($rawUserId[0]));
2324         } // END - if
2325
2326         // $idColumn[0] in POST must be an array again
2327         if (!is_array(postRequestElement($idColumn[0]))) {
2328                 // This indicates that you have conflicting form field naming with XML names
2329                 reportBug(__FUNCTION__, __LINE__, 'You have a wrong form field element, idColumn[0]=' . $idColumn[0]);
2330         } // END - if
2331
2332         // Delete them all
2333         //* 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>');
2334         $idList = '';
2335         foreach (postRequestElement($idColumn[0]) as $id => $sel) {
2336                 // Is id zero?
2337                 if (!isValidId($id)) {
2338                         // Then skip this
2339                         continue;
2340                 } // END - if
2341
2342                 // Is there a userid?
2343                 if (isPostRequestElementSet($userIdColumn[0])) {
2344                         // Load all data from that id
2345                         $result = sqlQueryEscaped("SELECT * FROM `{?_MYSQL_PREFIX?}_%s` WHERE `%s`=%s LIMIT 1",
2346                                 array(
2347                                         $tableName[0],
2348                                         $idColumn[0],
2349                                         $id
2350                                 ), __FUNCTION__, __LINE__);
2351
2352                         // Fetch the data
2353                         $content = sqlFetchArray($result);
2354
2355                         // Free the result
2356                         sqlFreeResult($result);
2357
2358                         // Send "build mails" out
2359                         sendGenericBuildMails('delete', $tableName, $content, $id, '', $userIdColumn);
2360                 } // END - if
2361
2362                 // Add id number
2363                 $idList .= $id . ',';
2364         } // END - foreach
2365
2366         // Run the query
2367         sqlQueryEscaped($sql,
2368                 array(
2369                         $tableName[0],
2370                         $idColumn[0],
2371                         convertNullToZero(substr($idList, 0, -1))
2372                 ), __FUNCTION__, __LINE__);
2373
2374         // Return affected rows
2375         return sqlAffectedRows();
2376 }
2377
2378 // Build a special template list
2379 // @TODO cacheFiles is not yet supported
2380 function doGenericListBuilder ($prefix, $listType, $tableName, $columns, $filterFunctions, $extraValues, $idColumn, $userIdColumn, $rawUserId = array('userid'), $content = array()) {
2381         // $tableName and $idColumn must bove be arrays!
2382         if ((!is_array($tableName)) || (count($tableName) != 1)) {
2383                 // $tableName is no array
2384                 reportBug(__FUNCTION__, __LINE__, 'tableName[]=' . gettype($tableName) . '!=array: userIdColumn=' . $userIdColumn);
2385         } elseif (!is_array($idColumn)) {
2386                 // $idColumn is no array
2387                 reportBug(__FUNCTION__, __LINE__, 'idColumn[]=' . gettype($idColumn) . '!=array: userIdColumn=' . $userIdColumn);
2388         } elseif ((!is_array($userIdColumn)) || (count($userIdColumn) != 1)) {
2389                 // $tableName is no array
2390                 reportBug(__FUNCTION__, __LINE__, 'userIdColumn[]=' . gettype($userIdColumn) . '!=array: userIdColumn=' . $userIdColumn);
2391         }
2392
2393         // Init row output
2394         $OUT = '';
2395
2396         // "Walk" through all entries
2397         //* 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>');
2398         foreach (postRequestElement($idColumn[0]) as $id => $selected) {
2399                 // Secure id number
2400                 $id = bigintval($id);
2401
2402                 // Get result from a given column array and table name
2403                 $result = getSqlResultFromArray($tableName[0], $columns, $idColumn[0], $id, __FUNCTION__, __LINE__);
2404
2405                 // Is there one entry?
2406                 if (sqlNumRows($result) == 1) {
2407                         // Load all data
2408                         $row = sqlFetchArray($result);
2409
2410                         // Filter all data
2411                         foreach ($row as $key => $value) {
2412                                 // Search index
2413                                 $idx  = searchXmlArray($key, $columns, 'column');
2414
2415                                 // Default name is NULL
2416                                 $name = NULL;
2417
2418                                 // Is the name there?
2419                                 if (isset($columns[$idx]['name'])) {
2420                                         // Then use it
2421                                         $name = $columns[$idx]['name'];
2422                                 } // END - if
2423
2424                                 // Skip any missing entries
2425                                 if ($idx === FALSE) {
2426                                         // Skip this one
2427                                         //* DEBUG: */ reportBug(__FUNCTION__, __LINE__, 'key=' . $key . ' - SKIPPED!');
2428                                         continue;
2429                                 } // END - if
2430
2431                                 // Is there a userid?
2432                                 //* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',userIdColumn=' . $userIdColumn[0]);
2433                                 if ($key == $userIdColumn[0]) {
2434                                         // Add it again as raw id
2435                                         //* DEBUG: */ reportBug(__FUNCTION__, __LINE__, 'key=' . $key . ',userIdColumn=' . $userIdColumn[0]);
2436                                         $row[$userIdColumn[0]] = convertZeroToNull($value);
2437                                         $row[$userIdColumn[0] . '_raw'] = $row[$userIdColumn[0]];
2438                                 } // END - if
2439
2440                                 // If the key matches the idColumn variable, we need to temporary remember it
2441                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'key=' . $key . ',idColumn=' . $idColumn[0] . ',value=' . $value);
2442                                 if ($key == $idColumn[0]) {
2443                                         /*
2444                                          * Found, so remember it securely (to make sure only id
2445                                          * numbers can pass, don't use alpha-numerical values!)
2446                                          */
2447                                         //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'value=' . $value . ' - set as ' . $prefix . '_list_builder_id_value!');
2448                                         $GLOBALS[$prefix . '_list_builder_id_value'] = bigintval($value);
2449                                 } // END - if
2450
2451                                 // Try to handle call-back functions and/or extra values
2452                                 //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'idx=' . $idx . ',row[' . $key . ']=' . $row[$key]);
2453                                 //if ($key == 'forced_campaign_created') die($idx.'=<pre>'.print_r($columns,true).'</pre><pre>'.print_r($extraValues,true).'</pre>');
2454                                 $row[$key] = doHandleExtraValues($filterFunctions, $extraValues, $idx, $row[$key], $userIdColumn, ((!is_null($name)) ? $name : $key), $id);
2455                         } // END - foreach
2456
2457                         // Then list it
2458                         $OUT .= loadTemplate(sprintf('%s_%s_%s_row',
2459                                 $prefix,
2460                                 $listType,
2461                                 $tableName[0]
2462                                 ), TRUE, $row
2463                         );
2464                 } // END - if
2465
2466                 // Free the result
2467                 sqlFreeResult($result);
2468         } // END - foreach
2469
2470         // Is there an entry in $content?
2471         if (isFilledArray($content)) {
2472                 // Use generic 'rows'
2473                 $content['rows'] = $OUT;
2474         } else {
2475                 // Use direct output
2476                 $content = $OUT;
2477         }
2478
2479         // Load master template
2480         loadTemplate(
2481                 sprintf('%s_%s_%s',
2482                         $prefix,
2483                         $listType,
2484                         $tableName[0]
2485                 ), FALSE, $content
2486         );
2487 }
2488
2489 // Adds key/value pair to a working SQL string together
2490 function addKeyValueSql ($key, $value) {
2491         // Init SQL
2492         $sql = '';
2493
2494         // Is it NULL?
2495         if (($value == 'NULL') || (is_null($value))) {
2496                 // Add key with NULL
2497                 $sql .= sprintf(' `%s`=NULL,',
2498                         sqlEscapeString($key)
2499                 );
2500         } elseif ((is_double($value)) || (is_float($value)) || (is_int($value))) {
2501                 // Is a number, so addd it directly
2502                 $sql .= sprintf(' `%s`=%s,',
2503                         sqlEscapeString($key),
2504                         $value
2505                 );
2506         } else {
2507                 // Else add the value escape'd
2508                 $sql .= sprintf(" `%s`='%s',",
2509                         sqlEscapeString($key),
2510                         sqlEscapeString($value)
2511                 );
2512         }
2513
2514         // Return SQL string
2515         return $sql;
2516 }
2517
2518 // "Getter" for an array from given table and columns
2519 function getArrayFromTable ($tableName, $columns, $orderBy, $ordered = 'ASC', $whereSql = '') {
2520         // The table must exist
2521         assert(ifSqlTableExists($tableName));
2522
2523         // Search for it
2524         $result = sqlQueryEscaped('SELECT
2525         `' . implode('`, `', $columns) . '`
2526 FROM
2527         `{?_MYSQL_PREFIX?}_%s`
2528 ' . $whereSql . '
2529 ORDER BY
2530         `%s` %S',
2531                 array(
2532                         $tableName,
2533                         $orderBy,
2534                         $ordered
2535                 ), __FUNCTION__, __LINE__
2536         );
2537
2538         // Init array
2539         $rows = array();
2540
2541         // Are there entries?
2542         if (!ifSqlHasZeroNumRows($result)) {
2543                 // Load all entries
2544                 while ($row = sqlFetchArray($result)) {
2545                         array_push($rows, $row);
2546                 } // END - while
2547         } // END - if
2548
2549         // Free result
2550         sqlFreeResult($result);
2551
2552         // Return all found rows
2553         return $rows;
2554 }
2555
2556 // [EOF]
2557 ?>