More misc fixes and rewrites (sorry, lame description)
[mailer.git] / inc / extensions.php
1 <?php
2 /************************************************************************
3  * MXChange v0.2.1                                    Start: 03/25/2004 *
4  * ===============                              Last change: 09/29/2004 *
5  *                                                                      *
6  * -------------------------------------------------------------------- *
7  * File              : extensions.php                                   *
8  * -------------------------------------------------------------------- *
9  * Short description : Extension management                             *
10  * -------------------------------------------------------------------- *
11  * Kurzbeschreibung  : Erweiterungen-Management                         *
12  * -------------------------------------------------------------------- *
13  * $Revision::                                                        $ *
14  * $Date::                                                            $ *
15  * $Tag:: 0.2.1-FINAL                                                 $ *
16  * $Author::                                                          $ *
17  * Needs to be in all Files and every File needs "svn propset           *
18  * svn:keywords Date Revision" (autoprobset!) at least!!!!!!            *
19  * -------------------------------------------------------------------- *
20  * Copyright (c) 2003 - 2008 by Roland Haeder                           *
21  * For more information visit: http://www.mxchange.org                  *
22  *                                                                      *
23  * This program is free software; you can redistribute it and/or modify *
24  * it under the terms of the GNU General Public License as published by *
25  * the Free Software Foundation; either version 2 of the License, or    *
26  * (at your option) any later version.                                  *
27  *                                                                      *
28  * This program is distributed in the hope that it will be useful,      *
29  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
30  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
31  * GNU General Public License for more details.                         *
32  *                                                                      *
33  * You should have received a copy of the GNU General Public License    *
34  * along with this program; if not, write to the Free Software          *
35  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,               *
36  * MA  02110-1301  USA                                                  *
37  ************************************************************************/
38
39 // Some security stuff...
40 if (!defined('__SECURITY')) {
41         $INC = substr(dirname(__FILE__), 0, strpos(dirname(__FILE__), '/inc') + 4) . '/security.php';
42         require($INC);
43 }
44
45 // Load the extension and maybe found language and function files.
46 function LOAD_EXTENSION ($ext_name, $EXT_LOAD_MODE = '', $EXT_VER = '', $dry_run = false) {
47         // Set current extension name
48         EXT_SET_CURR_NAME($ext_name);
49
50         // Init array
51         INIT_INC_POOL();
52
53         // Init EXT_UPDATE_DEPENDS
54         EXT_INIT_UPDATE_DEPENDS();
55
56         // Init current extension name list
57         INIT_EXT_SQLS();
58
59         // Is the extension already loaded?
60         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "Loading extension {$ext_name}, mode={$EXT_LOAD_MODE}, ver={$EXT_VER}.");
61         if ((isset($GLOBALS['ext_loaded']['ext'][$ext_name])) && (empty($EXT_LOAD_MODE))) {
62                 // Debug message
63                 DEBUG_LOG(__FUNCTION__, __LINE__, sprintf("Extension %s already loaded.", $ext_name));
64
65                 // Abort here
66                 return false;
67         } // END - if
68
69         // Construct include filename and FQFN for extension file
70         $INC = sprintf("inc/extensions/ext-%s.php", $ext_name);
71         $FQFN = constant('PATH') . $INC;
72
73         // Is the extension file NOT there?
74         if (!isIncludeReadable($INC)) {
75                 // Debug message
76                 DEBUG_LOG(__FUNCTION__, __LINE__, sprintf("Extension %s not found or not readable.", $ext_name));
77
78                 // Abort here
79                 return false;
80         } // END - if
81
82         // Construct FQFN for language file
83         $langInclude = sprintf("inc/language/%s_%s.php", $ext_name, getLanguage());
84
85         // Is this include there?
86         if ((isFileReadable($langInclude)) && (!isset($GLOBALS['ext_loaded']['lang'][$ext_name]))) {
87                 // Then load it
88                 //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "--- Language loaded.");
89                 $GLOBALS['ext_loaded']['lang'][$ext_name] = true;
90                 loadIncludeOnce($langInclude);
91         } elseif ((isDebugModeEnabled()) && ($ext_name != 'sql_patches') && (substr($ext_name, 0, 10) != 'admintheme')) {
92                 // No language file is not so good...
93                 DEBUG_LOG(__FUNCTION__, __LINE__, sprintf("WARNING: Extension %s has no language file or we cannot read from it. lang=%s",
94                         $ext_name, getLanguage()
95                 ));
96         }
97
98         // Construct FQFN for functions file
99         $funcsInclude = sprintf("inc/libs/%s_functions.php", $ext_name);
100
101         // Is this include there?
102         if ((isFileReadable($funcsInclude)) && (!isset($GLOBALS['ext_loaded']['funcs'][$ext_name]))) {
103                 // Then load it
104                 //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "--- Functions loaded.");
105                 $GLOBALS['ext_loaded']['funcs'][$ext_name] = true;
106                 loadIncludeOnce($funcsInclude);
107         } elseif ((isDebugModeEnabled()) && ($ext_name != 'sql_patches') && (substr($ext_name, 0, 10) != 'admintheme')) {
108                 // No functions file is not so good...
109                 DEBUG_LOG(__FUNCTION__, __LINE__, sprintf("WARNING: Extension %s has no own functions file or we cannot read from it.",
110                         $ext_name
111                 ));
112         } // END - if
113
114         // Extensions are not deprecated by default
115         EXT_SET_DEPRECATED('N');
116
117         // Extensions are not always active by default
118         EXT_SET_ALWAYS_ACTIVE('N');
119
120         // Extension update notes
121         EXT_SET_UPDATE_NOTES('');
122
123         // Include the extension file
124         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "Extension loaded.");
125         require($FQFN);
126
127         // Is this extension deprecated?
128         if (EXT_GET_DEPRECATED() == 'Y') {
129                 // Deactivate the extension
130                 DEACTIVATE_EXTENSION($ext_name);
131
132                 // Abort here
133                 return false;
134         } // END - if
135
136         // Mark it as loaded in normal mode
137         if (empty($EXT_LOAD_MODE)) {
138                 // Mark it now...
139                 $GLOBALS['ext_loaded']['ext'][$ext_name] = true;
140         } // END - if
141
142         // All fine!
143         return true;
144 }
145
146 // Registeres an extension and possible update depencies
147 function REGISTER_EXTENSION ($ext_name, $task_id, $dry_run = false, $logout = true) {
148         // Set current extension name
149         EXT_SET_CURR_NAME($ext_name);
150
151         //* DEBUG: */ print __FUNCTION__."[".__LINE__."]:currName=".EXT_GET_CURR_NAME()." - ENTERED!<br />\n";
152         // This shall never do a non-admin user or if the extension is active (already installed)
153         if ((!IS_ADMIN()) || (EXT_IS_ACTIVE($ext_name))) {
154                 return false;
155         } // END - if
156
157         // When this extension is already in install/update phase, all is fine
158         if (EXT_IS_REGISTER_RUNNING($ext_name)) {
159                 // Then abort here which is fine
160                 //* DEBUG: */ print __FUNCTION__."[".__LINE__."]:currName=".EXT_GET_CURR_NAME()." - ALREADY!<br />\n";
161                 return true;
162         } // END - if
163
164         // This registration is running
165         EXT_ADD_RUNNING_REGISTRATION($ext_name);
166
167         // Init EXT_UPDATE_DEPENDS
168         EXT_INIT_UPDATE_DEPENDS();
169
170         // Is the task id zero? Then we need to auto-fix it here
171         if ($task_id == 0) {
172                 // Try to find the task
173                 $task_id = DETERMINE_EXTENSION_TASK_ID(EXT_GET_CURR_NAME());
174
175                 // Still zero and not in dry-run?
176                 if (($task_id == 0) && (!$dry_run)) {
177                         // Then request a bug report
178                         debug_report_bug(sprintf("%s: task_id is still zero after DETERMINE_EXTENSION_TASK_ID(%s)",
179                         __FUNCTION__,
180                         EXT_GET_CURR_NAME()
181                         ));
182                 } // END - if
183         } // END - if
184
185         // Init queries and notes
186         INIT_EXT_SQLS();
187         EXT_INIT_NOTES();
188
189         // Init variables
190         $ret = false;
191         $test = false;
192         INIT_INC_POOL();
193
194         // By default we have no failures
195         EXT_SET_REPORTS_FAILURE(false);
196
197         // Does this extension exists?
198         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "currName=".EXT_GET_CURR_NAME()."");
199         if (LOAD_EXTENSION(EXT_GET_CURR_NAME(), 'register', '', $dry_run)) {
200                 // Set current extension name again
201                 EXT_SET_CURR_NAME($ext_name);
202
203                 // And run possible updates
204                 //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "".EXT_GET_CURR_NAME());
205                 $history = EXT_GET_VER_HISTORY();
206                 foreach ($history as $ver) {
207                         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "ext_name=".EXT_GET_CURR_NAME().", ext_ver={$ver}");
208                         // Load extension in update mode
209                         LOAD_EXTENSION(EXT_GET_CURR_NAME(), 'update', $ver, $dry_run);
210
211                         // Add update notes to our output
212                         ADD_EXTENSION_NOTES($ver);
213                 } // END - foreach
214
215                 // Does this extension depends on an outstanding update of another update?
216                 for ($dmy = EXT_GET_UPDATE_ITERATOR(); EXT_GET_UPDATE_ITERATOR() < EXT_COUNT_UPDATE_DEPENDS();) {
217                         // Get next update
218                         $ext_update = EXT_GET_ITERATOR_UPDATE_DEPENDS();
219
220                         // Increment here to avoid endless loop
221                         EXT_INCREMENT_UPDATE_INTERATOR();
222
223                         // Check for required file
224                         if (LOAD_EXTENSION($ext_update, 'register', '', $dry_run)) {
225                                 // Set current extension name again
226                                 EXT_SET_CURR_NAME($ext_name);
227
228                                 // If versions mismatch update extension first
229                                 $ext_ver = GET_EXT_VERSION($ext_update);
230
231                                 // Extension version set? If empty the extension is not registered
232                                 if (empty($ext_ver)) {
233                                         // Extension not registered so far so first load task's ID...
234                                         $task = DETERMINE_EXTENSION_TASK_ID($ext_update);
235
236                                         // Entry found?
237                                         if ($task > 0) {
238                                                 // Try to register the extension
239                                                 //* DEBUG: */ print __FUNCTION__."[".__LINE__."]:currName=".EXT_GET_CURR_NAME().":ext_update=".$ext_update.",taskId=".$task."<br />\n";
240                                                 $test = REGISTER_EXTENSION($ext_update, $task, $dry_run, false);
241
242                                                 // Reset extension name
243                                                 EXT_SET_CURR_NAME($ext_name);
244                                                 //* DEBUG: */ print __FUNCTION__."[".__LINE__."]:currName=".EXT_GET_CURR_NAME().':'; var_dump($test);
245                                         } // END - if
246                                 } elseif ($ext_ver != EXT_GET_VERSION()) {
247                                         // Ok, update this extension now
248                                         EXTENSION_UPDATE($ext_update, $ext_ver, $dry_run);
249
250                                         // All okay!
251                                         $test = true;
252                                 } else {
253                                         // Nothing to register / update before...
254                                         $test = true;
255                                 }
256                         } else {
257                                 // Required file for update does not exists!
258                                 $test = true;
259                                 // But this is fine for the first time...
260                         }
261
262                         // Restore the current extension name
263                         EXT_SET_CURR_NAME($ext_name);
264                 } // END - for
265
266                 // Is there no update?
267                 if (EXT_COUNT_UPDATE_DEPENDS(EXT_GET_CURR_NAME()) == 0) {
268                         // Then test is passed!
269                         $test = true;
270                 } // END - if
271
272                 // Switch back to register mode
273                 $EXT_LOAD_MODE = 'register';
274
275                 // Remains true if extension registration reports no failures
276                 //* DEBUG: */ print __FUNCTION__."[".__LINE__."]:currName=".EXT_GET_CURR_NAME().':'; var_dump($test);
277                 $test = (($test === true) && (EXT_GET_REPORTS_FAILURE() === false));
278                 //* DEBUG: */ print __FUNCTION__."[".__LINE__."]:currName=".EXT_GET_CURR_NAME().':'; var_dump($test);
279
280                 // Does everthing before wents ok?
281                 if ($test === true) {
282                         // "Dry-run-mode" activated?
283                         if ((!$dry_run) && (!EXT_IS_ON_REMOVAL_LIST())) {
284                                 //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "ext_name=".EXT_GET_CURR_NAME());
285                                 // Init SQLs and transfer ext->generic
286                                 INIT_SQLS();
287                                 SET_SQLS(GET_EXT_SQLS());
288
289                                 // Run installation pre-installation filters
290                                 runFilterChain('pre_extension_installed', array('dry_run' => $dry_run));
291
292                                 // Register extension
293                                 //* DEBUG: */ print __FUNCTION__."[".__LINE__."]:insert=".EXT_GET_CURR_NAME().'/'.EXT_GET_VERSION()." - INSERT!<br />\n";
294                                 SQL_QUERY_ESC("INSERT INTO `{!_MYSQL_PREFIX!}_extensions` (ext_name, ext_active, ext_version) VALUES ('%s','%s','%s')",
295                                         array(EXT_GET_CURR_NAME(), EXT_GET_ALWAYS_ACTIVE(), EXT_GET_VERSION()), __FUNCTION__, __LINE__);
296
297                                 // Remove cache file(s) if extension is active
298                                 runFilterChain('post_extension_installed', array('ext_name' => EXT_GET_CURR_NAME(), 'task_id' => $task_id));
299
300                                 // Remove all SQL commands
301                                 UNSET_SQLS();
302
303                                 // In normal mode return a true on success
304                                 $ret = true;
305                         } elseif ($dry_run) {
306                                 // Init SQLs and transfer ext->generic
307                                 INIT_SQLS();
308                                 SET_SQLS(GET_EXT_SQLS());
309
310                                 // Rewrite SQL command to keep { and } inside for dry-run
311                                 foreach (GET_SQLS() as $key => $sql) {
312                                         $sql = str_replace('{', "&#123;", str_replace('}', "&#125;", $sql));
313                                         SET_SQL_KEY($key, $sql);
314                                 } // END - foreach
315
316                                 // In  "dry-run" mode return array with all SQL commands
317                                 $ret = GET_SQLS();
318
319                                 // Remove all SQL commands
320                                 UNSET_SQLS();
321                         } else {
322                                 // Extension has been removed for updates, so all is fine!
323                                 $ret = true;
324                         }
325                 } else {
326                         // No, an error occurs while registering extension :-(
327                         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "".EXT_GET_CURR_NAME());
328                         $ret = false;
329                 }
330         } elseif (($task_id > 0) && (EXT_GET_CURR_NAME() != '')) {
331                 //* DEBUG: */ print __FUNCTION__."[".__LINE__."]:currName=".EXT_GET_CURR_NAME()."<br />\n";
332                 // Remove task from system when id and extension's name is valid
333                 SQL_QUERY_ESC("DELETE LOW_PRIORITY FROM `{!_MYSQL_PREFIX!}_task_system` WHERE `id`=%s AND `status`='NEW' LIMIT 1",
334                         array(bigintval($task_id)), __FUNCTION__, __LINE__);
335         }
336
337         // Is this the sql_patches?
338         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, ':'.EXT_GET_CURR_NAME()."/{$EXT_LOAD_MODE}");
339         if ((EXT_GET_CURR_NAME() == 'sql_patches') && (($EXT_LOAD_MODE == 'register') || ($EXT_LOAD_MODE == 'remove')) && (!$dry_run) && ($test)) {
340                 //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, ": LOAD!");
341                 if ($logout === true) {
342                         // Then redirect to logout
343                         redirectToUrl('modules.php?module=admin&amp;logout=1&amp;' . $EXT_LOAD_MODE . '=sql_patches');
344                 } else {
345                         // Add temporary filter
346                         registerFilter('shutdown', 'REDIRECT_TO_LOGOUT_SQL_PATCHES', true, true);
347                         $GLOBALS['ext_load_mode'] = $EXT_LOAD_MODE;
348                 }
349         } // END - if
350
351         // Return status code
352         //* DEBUG: */ print __FUNCTION__."[".__LINE__."]:currName=".EXT_GET_CURR_NAME()." - LEFT!<br />\n";
353         //* DEBUG: */ var_dump($ret);
354         return $ret;
355 }
356
357 // Run SQL queries for given extension id
358 // @TODO Change from ext_id to ext_name (not just even the variable! ;-) )
359 function EXTENSION_RUN_SQLS ($ext_id, $load_mode) {
360         // This shall never do a non-admin user!
361         if (!IS_ADMIN()) return false;
362
363         // Get extension's name
364         $ext_name = GET_EXT_NAME($ext_id);
365
366         // If it is not set then maybe there is no extension for that ID number
367         if (empty($ext_name)) {
368                 // We should fix these all!
369                 debug_report_bug(__FUNCTION__ . ': ext_name is empty. ext_id=' . $ext_id);
370         } // END - if
371
372         // Set current SQL name
373         EXT_SET_CURR_NAME($ext_name);
374
375         // Init EXT_UPDATE_DEPENDS
376         EXT_INIT_UPDATE_DEPENDS();
377
378         // Init array
379         INIT_EXT_SQLS();
380
381         // By default no SQL has been executed
382         $sqlRan = false;
383
384         // Load extension in detected mode
385         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, ":ext_name[{$ext_id}]=".EXT_GET_CURR_NAME()."");
386         LOAD_EXTENSION(EXT_GET_CURR_NAME(), $load_mode, '', false);
387
388         // Init these SQLs
389         INIT_SQLS();
390         SET_SQLS(GET_EXT_SQLS());
391
392         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, ":SQLs::count=".COUNT_SQLS()."");
393         if ((IS_SQLS_VALID() && (COUNT_SQLS() > 0))) {
394                 // Run any filters depending on the action here
395                 runFilterChain('extension_' . $load_mode, $ext_name);
396
397                 // Run SQL commands...
398                 runFilterChain('run_sqls');
399
400                 // Removal mode?
401                 if ($load_mode == 'remove') {
402                         // Delete this extension (remember to remove it from your server *before* you click on welcome!
403                         SQL_QUERY_ESC("DELETE LOW_PRIORITY FROM `{!_MYSQL_PREFIX!}_extensions` WHERE `ext_name`='%s' LIMIT 1",
404                                 array(EXT_GET_CURR_NAME()), __FUNCTION__, __LINE__);
405                 } // END - if
406         } // END - if
407
408         // Remove cache file(s) if extension is active
409         if (((EXT_IS_ACTIVE('cache')) || (GET_EXT_VERSION('cache') != '')) && (((SQL_AFFECTEDROWS() == 1)) || ($sqlRan === true) || ($load_mode == 'activate') || ($load_mode == 'deactivate'))) {
410                 // Run filters
411                 runFilterChain('post_extension_run_sql', EXT_GET_CURR_NAME());
412         } // END - if
413
414         // Is this the sql_patches?
415         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, ": id=".$ext_id.",currName=".EXT_GET_CURR_NAME().",loadMode=".$load_mode);
416         if ((EXT_GET_CURR_NAME() == 'sql_patches') && (($load_mode == 'register') || ($load_mode == 'remove'))) {
417                 // Then redirect to logout
418                 //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, ": LOAD!");
419                 redirectToUrl('modules.php?module=admin&amp;logout=1&amp;' . $load_mode . '=sql_patches');
420         } // END - if
421 }
422
423 // Check if given extension is active
424 function EXT_IS_ACTIVE ($ext_name) {
425         // Extensions are all inactive during installation
426         if ((!isInstalled()) || (isInstalling()) || (empty($ext_name))) return false;
427
428         // Not active is the default
429         $active = 'N';
430
431         // Check cache
432         if (isset($GLOBALS['cache_array']['extensions']['ext_active'][$ext_name])) {
433                 // Load from cache
434                 //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "CACHE! ext_name={$ext_name}");
435                 $active = $GLOBALS['cache_array']['extensions']['ext_active'][$ext_name];
436
437                 // Count cache hits
438                 incrementConfigEntry('cache_hits');
439         } elseif (isset($GLOBALS['ext_loaded'][$ext_name])) {
440                 // @TODO Extension is loaded, what next?
441                 app_die(__FUNCTION__, __LINE__, "LOADED:$ext_name");
442         } elseif (($ext_name == 'cache') || (GET_EXT_VERSION('cache') == '')) {
443                 //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "DB! ext_name={$ext_name}");
444                 // Load from database
445                 $result = SQL_QUERY_ESC("SELECT `ext_active` FROM `{!_MYSQL_PREFIX!}_extensions` WHERE `ext_name`='%s' LIMIT 1",
446                         array($ext_name), __FUNCTION__, __LINE__);
447
448                 // Entry found?
449                 if (SQL_NUMROWS($result) == 1) {
450                         // Load entry
451                         list($active) = SQL_FETCHROW($result);
452                 } // END - if
453
454                 // Free result
455                 SQL_FREERESULT($result);
456
457                 // Write cache array
458                 //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "ext_name=".$ext_name."[DB]: {$active}");
459                 $GLOBALS['cache_array']['extensions']['ext_active'][$ext_name] = $active;
460         } else {
461                 // Extension not active!
462                 //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "ext_name=".$ext_name.": Not active!");
463                 $GLOBALS['cache_array']['extensions']['ext_active'][$ext_name] = 'N';
464         }
465
466         // Debug message
467         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "ext_name={$ext_name},active={$active}");
468
469         // Is this extension activated? (For admins we always have active extensions...)
470         return ($active == 'Y');
471 }
472 // Get version from extensions
473 function GET_EXT_VERSION ($ext_name) {
474         // By default no extension is found
475         $ext_ver = false;
476
477         // Empty extension name should be fixed!
478         if (empty($ext_name)) {
479                 // Please report this bug!
480                 debug_report_bug(__FUNCTION__ . ': ext_name is empty which is not allowed here.');
481         } // END - if
482
483         // Extensions are all inactive during installation
484         if ((!isInstalled()) || (isInstalling())) return "";
485         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, ": ext_name={$ext_name}");
486
487         // Is the cache written?
488         if (isset($GLOBALS['cache_array']['extensions']['ext_version'][$ext_name])) {
489                 // Load data from cache
490                 //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, ": CACHE!");
491                 $ext_ver = $GLOBALS['cache_array']['extensions']['ext_version'][$ext_name];
492
493                 // Count cache hits
494                 incrementConfigEntry('cache_hits');
495         } elseif (!isCacheInstanceValid()) {
496                 // Load from database
497                 $result = SQL_QUERY_ESC("SELECT `ext_version` FROM `{!_MYSQL_PREFIX!}_extensions` WHERE `ext_name`='%s' LIMIT 1",
498                         array($ext_name), __FUNCTION__, __LINE__);
499                 //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, ": DB - ".SQL_NUMROWS($result)."");
500
501                 // Is the extension there?
502                 if (SQL_NUMROWS($result) == 1) {
503                         // Load entry
504                         list($ext_ver) = SQL_FETCHROW($result);
505                 } elseif (isDebugModeEnabled()) {
506                         // Not found!
507                         DEBUG_LOG(__FUNCTION__, __LINE__, sprintf(": Cannot find extension %s in database!", $ext_name));
508                 }
509
510                 // Free result
511                 SQL_FREERESULT($result);
512
513                 // Set cache
514                 $GLOBALS['cache_array']['extensions']['ext_version'][$ext_name] = $ext_ver;
515         }
516
517         // Return result
518         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, ": ret={$ext_ver}");
519         return $ext_ver;
520 }
521
522 // Updates a given extension with current extension version to latest version
523 function EXTENSION_UPDATE ($ext_name, $ext_ver, $dry_run = false) {
524         // Only admins are allowed to update extensions
525         if ((!IS_ADMIN()) || (empty($ext_name))) return false;
526
527         // Set current SQL name
528         EXT_SET_CURR_NAME($ext_name);
529
530         // Init arrays
531         INIT_EXT_SQLS();
532         EXT_INIT_NOTES();
533         INIT_INC_POOL();
534
535         // Load extension in test mode
536         LOAD_EXTENSION($ext_name, 'test', $ext_ver, $dry_run);
537
538         // Save version history
539         $history = EXT_GET_VER_HISTORY();
540
541         // Remove old SQLs array to prevent possible bugs
542         INIT_EXT_SQLS();
543
544         // Check if version is updated
545         if (((EXT_GET_VERSION() != $ext_ver) || ($dry_run)) && (is_array($history))) {
546                 // Search for starting point
547                 $start = array_search($ext_ver, $history);
548
549                 // And load SQL queries in order of version history
550                 for ($idx = ($start + 1); $idx < count($history); $idx++) {
551                         // Set current extension name
552                         //* DEBUG: */ print __FUNCTION__.'['.__LINE__.':] ext_name='.$ext_name.'<br />';
553                         EXT_SET_CURR_NAME($ext_name);
554
555                         // Set extension version
556                         $GLOBALS['cache_array']['update_ver'][EXT_GET_CURR_NAME()] = $history[$idx];
557
558                         // Load again...
559                         LOAD_EXTENSION(EXT_GET_CURR_NAME(), 'update', $GLOBALS['cache_array']['update_ver'][EXT_GET_CURR_NAME()], $dry_run);
560
561                         // Get all depencies
562                         $depencies = EXT_GET_UPDATE_DEPENDS();
563
564                         // Nothing to apply?
565                         if (count($depencies) > 0) {
566                                 // Apply all extension depencies
567                                 foreach ($depencies as $ext_depend) {
568                                         // Set it as current
569                                         EXT_SET_CURR_NAME($ext_depend);
570
571                                         // Is the extension there?
572                                         if (GET_EXT_VERSION($ext_depend) != '') {
573                                                 // Update another extension first!
574                                                 $test = EXTENSION_UPDATE($ext_depend, GET_EXT_VERSION($ext_depend), $dry_run);
575                                         } else {
576                                                 // Register new extension
577                                                 $test = REGISTER_EXTENSION($ext_depend, 0, $dry_run, false);
578                                         }
579                                 } // END - foreach
580
581                                 // Set name back
582                                 EXT_SET_CURR_NAME($ext_name);
583                         } // END - if
584
585                         // Add notes
586                         ADD_EXTENSION_NOTES($GLOBALS['cache_array']['update_ver'][EXT_GET_CURR_NAME()]);
587                 } // END - for
588
589                 // In real-mode execute any existing includes
590                 if (!$dry_run) {
591                         $GLOBALS['cache_array']['inc_pool'][EXT_GET_CURR_NAME()] = GET_INC_POOL();
592                         runFilterChain('load_includes');
593                         SET_INC_POOL($GLOBALS['cache_array']['inc_pool'][EXT_GET_CURR_NAME()]);
594                         unset($GLOBALS['cache_array']['inc_pool'][EXT_GET_CURR_NAME()]);
595                 } // END - if
596
597                 // Init these SQLs
598                 INIT_SQLS();
599                 SET_SQLS(GET_EXT_SQLS());
600
601                 // Run SQLs
602                 runFilterChain('run_sqls', array('dry_run' => $dry_run));
603
604                 if (!$dry_run) {
605                         // Create task
606                         CREATE_EXTENSION_UPDATE_TASK(getCurrentAdminId(), EXT_GET_CURR_NAME(), $GLOBALS['cache_array']['update_ver'][EXT_GET_CURR_NAME()], SQL_ESCAPE(EXT_GET_NOTES(EXT_GET_NOTES())));
607
608                         // Update extension's version
609                         SQL_QUERY_ESC("UPDATE `{!_MYSQL_PREFIX!}_extensions` SET ext_version='%s' WHERE `ext_name`='%s' LIMIT 1",
610                         array($GLOBALS['cache_array']['update_ver'][EXT_GET_CURR_NAME()], EXT_GET_CURR_NAME()), __FUNCTION__, __LINE__);
611
612                         // Remove arrays
613                         UNSET_SQLS();
614                         unset($GLOBALS['cache_array']['update_ver'][EXT_GET_CURR_NAME()]);
615
616                         // Run filters on success extension update
617                         runFilterChain('extension_update', EXT_GET_CURR_NAME());
618                 } // END - if
619         } // END - if
620 }
621
622 // Output verbose SQL table for extension
623 function EXTENSION_VERBOSE_TABLE ($queries = array(), $title = '', $dashed = '', $switch = false, $width = '100%') {
624         // Empty title?
625         if (empty($title)) {
626                 // Then fix it to default
627                 $title = getMessage('ADMIN_SQLS_EXECUTED_ON_REMOVAL');
628         } // END - if
629
630         // Are there some queries in $queries?
631         if (count($queries) > 0) {
632                 // Then use them instead!
633                 SET_SQLS($queries);
634         } // END - if
635
636         // Init variables
637         $SW = 2; $i = 1;
638         $OUT = '';
639
640         // Do we have queries?
641         if ((IS_SQLS_VALID()) && (GET_EXT_VERSION('sql_patches') >= '0.0.7') && (getConfig('verbose_sql') == 'Y')) {
642                 foreach (GET_SQLS() as $idx => $sql) {
643                         // Trim out spaces
644                         $sql = trim($sql);
645
646                         // Output command if set
647                         if (!empty($sql)) {
648                                 // Prepare output for template
649                                 $content = array(
650                                         'sw'  => $SW,
651                                         'i'   => $i,
652                                         'sql' => $sql
653                                 );
654
655                                 // Load row template
656                                 $OUT .= LOAD_TEMPLATE("admin_ext_sql_row", true, $content);
657
658                                 // Switch color and count up
659                                 $SW = 3 - $SW;
660                                 $i++;
661                         } // END - if
662                 } // END - foreach
663
664                 // Prepare content for template
665                 $content = array(
666                         'width'  => $width,
667                         'dashed' => $dashed,
668                         'title'  => $title,
669                         'out'    => $OUT
670                 );
671
672                 // Load main template
673                 $OUT = LOAD_TEMPLATE("admin_ext_sql_table", true, $content);
674         } elseif ((GET_EXT_VERSION('sql_patches') >= '0.0.7') && (getConfig('verbose_sql') == 'Y')) {
675                 // No addional SQL commands to run
676                 $OUT = LOAD_TEMPLATE('admin_settings_saved', true, getMessage('ADMIN_NO_ADDITIONAL_SQLS'));
677         } // END - if
678
679         // Return output
680         return $OUT;
681 }
682
683 // Get extension name from id
684 function GET_EXT_NAME ($ext_id) {
685         // Init extension name
686         $ret = '';
687
688         // Is cache there?
689         if (isset($GLOBALS['cache_array']['extensions']['ext_name'][$ext_id])) {
690                 // Load from cache
691                 $ret = $GLOBALS['cache_array']['extensions']['ext_name'][$ext_id];
692
693                 // Count cache hits
694                 incrementConfigEntry('cache_hits');
695         } elseif (!EXT_IS_ACTIVE('cache')) {
696                 // Load from database
697                 $result = SQL_QUERY_ESC("SELECT ext_name FROM `{!_MYSQL_PREFIX!}_extensions` WHERE `id`=%s LIMIT 1",
698                         array(bigintval($ext_id)), __FUNCTION__, __LINE__);
699                 list($ret) = SQL_FETCHROW($result);
700                 SQL_FREERESULT($result);
701         }
702
703         // Return the extension name
704         return $ret;
705 }
706
707 // Get extension id from name
708 function GET_EXT_ID ($ext_name) {
709         // Init ID number
710         $ret = 0;
711         if (isset($GLOBALS['cache_array']['extensions']['ext_id'][$ext_name])) {
712                 // Load from cache
713                 $ret = $GLOBALS['cache_array']['extensions']['ext_id'][$ext_name];
714
715                 // Count cache hits
716                 incrementConfigEntry('cache_hits');
717         } elseif (!EXT_IS_ACTIVE('cache')) {
718                 // Load from database
719                 $result = SQL_QUERY_ESC("SELECT `id` FROM `{!_MYSQL_PREFIX!}_extensions` WHERE `ext_name`='%s' LIMIT 1",
720                         array($ext_name), __FUNCTION__, __LINE__);
721                 list($ret) = SQL_FETCHROW($result);
722                 SQL_FREERESULT($result);
723         }
724
725         // Return value
726         return $ret;
727 }
728
729 // Activate given extension
730 function ACTIVATE_EXTENSION ($ext_name) {
731         // Activate the extension
732         SQL_QUERY_ESC("UPDATE `{!_MYSQL_PREFIX!}_extensions` SET `ext_active`='Y' WHERE `ext_name`='%s' LIMIT 1",
733         array($ext_name), __FUNCTION__, __LINE__);
734
735         // Extension has been activated?
736         if (SQL_AFFECTEDROWS() == 1) {
737                 // Then run all queries
738                 EXTENSION_RUN_SQLS(GET_EXT_ID($ext_name), 'activate');
739         } // END - if
740 }
741
742 // Deactivate given extension
743 function DEACTIVATE_EXTENSION($ext_name) {
744         // Activate the extension
745         SQL_QUERY_ESC("UPDATE `{!_MYSQL_PREFIX!}_extensions` SET `ext_active`='N' WHERE `ext_name`='%s' LIMIT 1",
746         array($ext_name), __FUNCTION__, __LINE__);
747
748         // Extension has been activated?
749         if (SQL_AFFECTEDROWS() == 1) {
750                 // Then run all queries
751                 EXTENSION_RUN_SQLS(GET_EXT_ID($ext_name), 'deactivate');
752
753                 // Create new task
754                 CREATE_EXTENSION_DEACTIVATION_TASK($ext_name);
755
756                 // Notify the admin
757                 sendAdminNotification(
758                 getMessage('ADMIN_SUBJECT_EXTENSION_DEACTIVATED'),
759                         'admin_ext_deactivated',
760                 array('ext_name' => $ext_name)
761                 );
762         } // END - if
763 }
764
765 // Checks wether the extension is older than given
766 function EXT_VERSION_IS_OLDER ($ext_name, $ext_ver) {
767         // Get current extension version
768         $currVersion = GET_EXT_VERSION($ext_name);
769
770         // Remove all dots from both versions
771         $currVersion = str_replace('.', '', $currVersion);
772         $ext_ver = str_replace('.', '', $ext_ver);
773
774         // Now compare both and return the result
775         return ($currVersion < $ext_ver);
776 }
777
778 // Creates a new task for updated extension
779 function CREATE_EXTENSION_UPDATE_TASK ($admin_id, $ext_name, $ext_ver, $notes) {
780         // Create subject line
781         $subject = '[UPDATE-'.$ext_name.'-'.$ext_ver.':] {--ADMIN_UPDATE_EXT_SUBJ--}';
782
783         // Is the extension there?
784         if (GET_EXT_VERSION($ext_name) != '') {
785                 // Check if task is not there
786                 if (DETERMINE_TASK_ID_BY_SUBJECT($subject) == 0) {
787                         // Task not created so it's a brand-new extension which we need to register and create a task for!
788                         createNewTask($subject, $notes, 'EXTENSION_UPDATE', 0, $admin_id);
789                 } // END - if
790         } // END - if
791 }
792
793 // Creates a new task for newly installed extension
794 function CREATE_NEW_EXTENSION_TASK ($admin_id, $subject, $ext) {
795         // Not installed and do we have created a task for the admin?
796         if ((DETERMINE_TASK_ID_BY_SUBJECT($subject) == 0) && (GET_EXT_VERSION($ext) == '')) {
797                 // Set default message if ext-foo is missing
798                 $message = sprintf(getMessage('ADMIN_EXT_TEXT_FILE_MISSING'), $ext);
799
800                 // Template file
801                 $tpl = sprintf("%stemplates/%s/html/ext/ext_%s.tpl",
802                         constant('PATH'),
803                         getLanguage(),
804                         $ext
805                 );
806
807                 // Load text for task if found
808                 if (isFileReadable($tpl)) {
809                         // Load extension's own text template (HTML!)
810                         $message = LOAD_TEMPLATE('ext_' . $ext, true);
811                 } else {
812                         // Write this in debug.log as well
813                         DEBUG_LOG(__FUNCTION__, __LINE__, $message);
814                 }
815
816                 // Task not created so it's a brand-new extension which we need to register and create a task for!
817                 createNewTask($subject, $message, 'EXTENSION_UPDATE', 0, $admin_id, false);
818         } // END - if
819 }
820
821 // Creates a task for automatically deactivated (deprecated) extension
822 function CREATE_EXTENSION_DEACTIVATION_TASK ($ext) {
823         // Create subject line
824         $subject = sprintf("[%s:] %s", $ext, getMessage('TASK_SUBJ_EXTENSION_DEACTIVATED'));
825
826         // Not installed and do we have created a task for the admin?
827         if ((DETERMINE_TASK_ID_BY_SUBJECT($subject) == 0) && (GET_EXT_VERSION($ext) != '')) {
828                 // Task not created so add it
829                 createNewTask($subject, SQL_ESCAPE(LOAD_TEMPLATE('task_ext_deactivated', true, $ext)), 'EXTENSION_DEACTIVATION');
830         } // END - if
831 }
832
833 // Checks if the module has a menu
834 function MODULE_HAS_MENU ($mod, $forceDb = false) {
835         // All is false by default
836         $ret = false;
837
838         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "mod={$mod},cache=".GET_EXT_VERSION('cache'));
839         if (GET_EXT_VERSION('cache') >= '0.1.2') {
840                 // Cache version is okay, so let's check the cache!
841                 if (isset($GLOBALS['cache_array']['modules']['has_menu'][$mod])) {
842                         // Check module cache and count hit
843                         $ret = ($GLOBALS['cache_array']['modules']['has_menu'][$mod] == 'Y');
844                         incrementConfigEntry('cache_hits');
845                 } elseif (isset($GLOBALS['cache_array']['extensions']['ext_menu'][$mod])) {
846                         // Check cache and count hit
847                         $ret = ($GLOBALS['cache_array']['extensions']['ext_menu'][$mod] == 'Y');
848                         incrementConfigEntry('cache_hits');
849                 } elseif ((IS_ADMIN()) && ($mod == 'admin')) {
850                         // Admin module has always a menu!
851                         $ret = true;
852                 }
853         } elseif ((GET_EXT_VERSION('sql_patches') >= '0.3.6') && ((!EXT_IS_ACTIVE('cache')) || ($forceDb === true))) {
854                 // Check database for entry
855                 $result = SQL_QUERY_ESC("SELECT `has_menu` FROM `{!_MYSQL_PREFIX!}_mod_reg` WHERE `module`='%s' LIMIT 1",
856                         array($mod), __FUNCTION__, __LINE__);
857
858                 // Entry found?
859                 if (SQL_NUMROWS($result) == 1) {
860                         // Load "has_menu" column
861                         list($has_menu) = SQL_FETCHROW($result);
862
863                         // Fake cache... ;-)
864                         $GLOBALS['cache_array']['extensions']['ext_menu'][$mod] = $has_menu;
865
866                         // Does it have a menu?
867                         $ret = ($has_menu == 'Y');
868                 } // END  - if
869
870                 // Free memory
871                 SQL_FREERESULT($result);
872         } elseif (GET_EXT_VERSION('sql_patches') == '') {
873                 // No sql_patches installed, so maybe in admin area or no admin registered?
874                 $ret = (((IS_ADMIN()) || (!isAdminRegistered())) && ($mod == 'admin')); // Then there is a menu!
875         }
876
877         // Return status
878         //* DEBUG: */ print __FUNCTION__."[".__LINE__."]:currName=".EXT_GET_CURR_NAME().':'; var_dump($ret);
879         return $ret;
880 }
881
882 // Determines the task id for given extension
883 function DETERMINE_EXTENSION_TASK_ID ($ext_name) {
884         // Default is not found
885         $task_id = 0;
886
887         // Search for extension task's id
888         $result = SQL_QUERY_ESC("SELECT `id` FROM `{!_MYSQL_PREFIX!}_task_system` WHERE `task_type`='EXTENSION' AND `subject`='[%s:]' LIMIT 1",
889                 array($ext_name), __FUNCTION__, __LINE__);
890
891         // Entry found?
892         if (SQL_NUMROWS($result) == 1) {
893                 // Task found so load task's ID and register extension...
894                 list($task_id) = SQL_FETCHROW($result);
895         } // END - if
896
897         // Free result
898         SQL_FREERESULT($result);
899
900         // Return it
901         return $task_id;
902 }
903
904 // Determines the task id for given subject
905 function DETERMINE_TASK_ID_BY_SUBJECT ($subject) {
906         // Default is not found
907         $task_id = 0;
908
909         // Search for task id
910         $result = SQL_QUERY_ESC("SELECT `id` FROM `{!_MYSQL_PREFIX!}_task_system` WHERE `subject` LIKE '%s%%' LIMIT 1",
911                 array($subject), __FUNCTION__, __LINE__);
912
913         // Entry found?
914         if (SQL_NUMROWS($result) == 1) {
915                 // Task found so load task's ID and register extension...
916                 list($task_id) = SQL_FETCHROW($result);
917         } // END - if
918
919         // Free result
920         SQL_FREERESULT($result);
921
922         // Return it
923         return $task_id;
924 }
925
926 // Add updates notes for given version
927 function ADD_EXTENSION_NOTES ($ver) {
928         // Init notes/content
929         $out = ''; $content = array();
930
931         // Is do we have verbose output enabled?
932         if ((getConfig('verbose_sql') == 'Y') || (!EXT_IS_ACTIVE('sql_patches'))) {
933                 // Update notes found?
934                 if (EXT_GET_UPDATE_NOTES() != '') {
935                         // Update notes found
936                         $content = array(
937                                 'ver'   => $ver,
938                                 'notes' => EXT_GET_UPDATE_NOTES()
939                         );
940
941                         // Reset them
942                         EXT_SET_UPDATE_NOTES('');
943                 } elseif (($ver == '0.0') || ($ver == '0.0.0')) {
944                         // Initial release
945                         $content = array(
946                                 'ver'   => $ver,
947                                 'notes' => getMessage('INITIAL_RELEASE')
948                         );
949                 } else {
950                         // No update notes found!
951                         $content = array(
952                                 'ver'   => $ver,
953                                 'notes' => getMessage('NO_UPDATE_NOTES')
954                         );
955                 }
956
957                 // Load template
958                 $out = LOAD_TEMPLATE('admin_ext_notes', true, $content);
959         } // END - if
960
961         // Add the notes
962         EXT_APPEND_NOTES($out);
963 }
964
965 // Getter for CSS files array
966 function EXT_GET_CSS_FILES () {
967         // By default no additional CSS files are found
968         $cssFiles = array();
969
970         // Is the array there?
971         if (isset($GLOBALS['css_files'])) {
972                 // Then use it
973                 $cssFiles = $GLOBALS['css_files'];
974         } // END - if
975
976         // Return array
977         return $cssFiles;
978 }
979
980 // Init CSS files array
981 function EXT_INIT_CSS_FILES () {
982         // Simply init it
983         $GLOBALS['css_files'] = array();
984 }
985
986 // Add new entry
987 function EXT_ADD_CSS_FILE ($file) {
988         // Is the array there?
989         if (!isset($GLOBALS['css_files'])) {
990                 // Then auto-init them
991                 EXT_INIT_CSS_FILES();
992         } // END - if
993
994         // Add the entry
995         $GLOBALS['css_files'][] = $file;
996 }
997
998 // Setter for EXT_ALWAYS_ACTIVE flag
999 function EXT_SET_ALWAYS_ACTIVE ($active) {
1000         $GLOBALS['ext_always_active'][EXT_GET_CURR_NAME()] = (string) $active;
1001 }
1002
1003 // Getter for EXT_ALWAYS_ACTIVE flag
1004 function EXT_GET_ALWAYS_ACTIVE () {
1005         return $GLOBALS['ext_always_active'][EXT_GET_CURR_NAME()];
1006 }
1007
1008 // Setter for EXT_VERSION flag
1009 function EXT_SET_VERSION ($version) {
1010         $GLOBALS['ext_version'][EXT_GET_CURR_NAME()] = (string) $version;
1011 }
1012
1013 // Getter for EXT_VERSION flag
1014 function EXT_GET_VERSION () {
1015         return $GLOBALS['ext_version'][EXT_GET_CURR_NAME()];
1016 }
1017
1018 // Setter for EXT_DEPRECATED flag
1019 function EXT_SET_DEPRECATED ($deprecated) {
1020         $GLOBALS['ext_deprecated'][EXT_GET_CURR_NAME()] = (string) $deprecated;
1021 }
1022
1023 // Getter for EXT_DEPRECATED flag
1024 function EXT_GET_DEPRECATED () {
1025         return $GLOBALS['ext_deprecated'][EXT_GET_CURR_NAME()];
1026 }
1027
1028 // Setter for EXT_UPDATE_DEPENDS flag
1029 function EXT_ADD_UPDATE_DEPENDS ($updateDepends) {
1030         // Is the update depency empty? (NEED TO BE FIXED!)
1031         if (empty($updateDepends)) {
1032                 // Please report this bug!
1033                 debug_report_bug("updateDepends is left empty!");
1034         } // END - if
1035
1036         // Is it not yet added?
1037         if (!in_array($updateDepends, $GLOBALS['ext_running_updates'])) {
1038                 //* DEBUG */ DEBUG_LOG(__FUNCTION__, __LINE__, "currName=".EXT_GET_CURR_NAME().'/'.$updateDepends);
1039                 // Add it to the list of extension update depencies map
1040                 $GLOBALS['ext_update_depends'][EXT_GET_CURR_NAME()][] = (string) $updateDepends;
1041
1042                 // Remember it in the list of running updates
1043                 $GLOBALS['ext_running_updates'][] = $updateDepends;
1044         } // END - if
1045 }
1046
1047 // Checks wether the given extension registration is in progress
1048 function EXT_IS_REGISTER_RUNNING ($ext_name) {
1049         return ((isset($GLOBALS['ext_register_running'])) && (in_array($ext_name, $GLOBALS['ext_register_running'])));
1050 }
1051
1052 // Init EXT_UPDATE_DEPENDS flag
1053 function EXT_INIT_UPDATE_DEPENDS () {
1054         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "currName=".EXT_GET_CURR_NAME());
1055
1056         // Init update depency map automatically if not found
1057         if (!EXT_IS_UPDATE_DEPENDS_INIT()) {
1058                 //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "currName=".EXT_GET_CURR_NAME()." - INIT!");
1059                 $GLOBALS['ext_update_depends'][EXT_GET_CURR_NAME()] = array();
1060         } // END - if
1061
1062         // Init running updates array
1063         EXT_INIT_RUNNING_UPDATES();
1064 }
1065
1066 // Adds an extension as "registration in progress"
1067 function EXT_ADD_RUNNING_REGISTRATION ($ext_name) {
1068         // Is it running?
1069         if (!EXT_IS_REGISTER_RUNNING($ext_name)) {
1070                 // Then add it!
1071                 $GLOBALS['ext_register_running'][] = $ext_name;
1072         } // END - if
1073 }
1074
1075 // Checks wether EXT_UPDATE_DEPENDS is initialized
1076 function EXT_IS_UPDATE_DEPENDS_INIT () {
1077         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "currName=".EXT_GET_CURR_NAME());
1078         return (isset($GLOBALS['ext_update_depends'][EXT_GET_CURR_NAME()]));
1079 }
1080
1081 // Initializes the list of running updates
1082 function EXT_INIT_RUNNING_UPDATES () {
1083         // Auto-init ext_running_updates
1084         if (!isset($GLOBALS['ext_running_updates'])) {
1085                 $GLOBALS['ext_running_updates'] = array();
1086                 $GLOBALS['ext_register_running'] = array();
1087         } // END - if
1088 }
1089
1090 // Getter for EXT_UPDATE_DEPENDS flag
1091 function EXT_GET_UPDATE_DEPENDS () {
1092         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "currName=".EXT_GET_CURR_NAME());
1093         return $GLOBALS['ext_update_depends'][EXT_GET_CURR_NAME()];
1094 }
1095
1096 // Getter for next iterator depency
1097 function EXT_GET_ITERATOR_UPDATE_DEPENDS () {
1098         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "currName=".EXT_GET_CURR_NAME());
1099         return ($GLOBALS['ext_update_depends'][EXT_GET_CURR_NAME()][EXT_GET_UPDATE_ITERATOR()]);
1100 }
1101
1102 // Counter for extension update depencies
1103 function EXT_COUNT_UPDATE_DEPENDS () {
1104         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "currName=".EXT_GET_CURR_NAME());
1105         return count($GLOBALS['ext_update_depends'][EXT_GET_CURR_NAME()]);
1106 }
1107
1108 // Removes given extension from update denpency list
1109 function EXT_REMOVE_UPDATE_DEPENDS ($ext_name) {
1110         // Look it up
1111         $key = array_search($ext_name, EXT_GET_UPDATE_DEPENDS());
1112
1113         // Is it valid?
1114         if ($key !== false) {
1115                 // Then remove it
1116                 unset($GLOBALS['ext_update_depends'][EXT_GET_CURR_NAME()][$key]);
1117
1118                 // And sort the array
1119                 ksort($GLOBALS['ext_update_depends'][EXT_GET_CURR_NAME()]);
1120         } // END - if
1121 }
1122
1123 // Init iterator for update depencies
1124 function EXT_INIT_UPDATE_ITERATOR () {
1125         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "currName=".EXT_GET_CURR_NAME());
1126         $GLOBALS['ext_depend_iterator'][EXT_GET_CURR_NAME()] = 0;
1127 }
1128
1129 // Getter for depency iterator
1130 function EXT_GET_UPDATE_ITERATOR () {
1131         // Auto-init iterator
1132         if (!isset($GLOBALS['ext_depend_iterator'][EXT_GET_CURR_NAME()])) EXT_INIT_UPDATE_ITERATOR();
1133
1134         // Return it
1135         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "currName=".EXT_GET_CURR_NAME().'/'.$GLOBALS['ext_depend_iterator'][EXT_GET_CURR_NAME()]);
1136         return $GLOBALS['ext_depend_iterator'][EXT_GET_CURR_NAME()];
1137 }
1138
1139 // Increments the update iterator
1140 function EXT_INCREMENT_UPDATE_INTERATOR () {
1141         //* DEBUG: */ DEBUG_LOG(__FUNCTION__, __LINE__, "currName=".EXT_GET_CURR_NAME());
1142         $GLOBALS['ext_depend_iterator'][EXT_GET_CURR_NAME()]++;
1143 }
1144
1145 // Setter for EXT_REPORTS_FAILURE flag
1146 function EXT_SET_REPORTS_FAILURE ($reportsFailure) {
1147         $GLOBALS['ext_reports_failure'] = (bool) $reportsFailure;
1148 }
1149
1150 // Getter for EXT_REPORTS_FAILURE flag
1151 function EXT_GET_REPORTS_FAILURE () {
1152         return $GLOBALS['ext_reports_failure'];
1153 }
1154
1155 // Setter for EXT_VER_HISTORY flag
1156 function EXT_SET_VER_HISTORY ($verHistory) {
1157         $GLOBALS['ext_ver_history'] = (array) $verHistory;
1158 }
1159
1160 // Getter for EXT_VER_HISTORY array
1161 function EXT_GET_VER_HISTORY () {
1162         return $GLOBALS['ext_ver_history'];
1163 }
1164
1165 // Setter for EXT_UPDATE_NOTES flag
1166 function EXT_SET_UPDATE_NOTES ($updateNotes) {
1167         $GLOBALS['ext_update_notes'] = (string) $updateNotes;
1168 }
1169
1170 // Getter for EXT_UPDATE_NOTES flag
1171 function EXT_GET_UPDATE_NOTES () {
1172         return $GLOBALS['ext_update_notes'];
1173 }
1174
1175 // Init extension notice
1176 function EXT_INIT_NOTES () {
1177         $GLOBALS['ext_notes'] = '';
1178 }
1179
1180 // Append extension notice
1181 function EXT_APPEND_NOTES ($notes) {
1182         $GLOBALS['ext_notes'] .= (string) $notes;
1183 }
1184
1185 // Getter for extension notes
1186 function EXT_GET_NOTES () {
1187         return $GLOBALS['ext_notes'];
1188 }
1189
1190 // Setter for current extension name
1191 function EXT_SET_CURR_NAME ($ext_name) {
1192         $GLOBALS['curr_ext_name'] = (string) $ext_name;
1193 }
1194
1195 // Getter for current extension name
1196 function EXT_GET_CURR_NAME () {
1197         if (isset($GLOBALS['curr_ext_name'])) {
1198                 return $GLOBALS['curr_ext_name'];
1199         } // END - if
1200
1201         // Not set!
1202         debug_report_bug(__FUNCTION__.": curr_ext_name not initialized. Please execute INIT_EXT_SQLS() before calling this function.");
1203 }
1204
1205 // Init SQLs array for current extension
1206 function INIT_EXT_SQLS () {
1207         // Auto-init the array now...
1208         if (!isset($GLOBALS['ext_sqls'][EXT_GET_CURR_NAME()])) {
1209                 $GLOBALS['ext_sqls'][EXT_GET_CURR_NAME()] = array();
1210         } // END - if
1211 }
1212
1213 // Adds SQLs to the SQLs array but "assigns" it with current extension name
1214 function ADD_EXT_SQL ($sql) {
1215         $GLOBALS['ext_sqls'][EXT_GET_CURR_NAME()][] = $sql;
1216 }
1217
1218 // Getter for SQLs array for current extension
1219 function GET_EXT_SQLS () {
1220         // Output debug backtrace if not found (SHOULD NOT HAPPEN!)
1221         if (!isset($GLOBALS['ext_sqls'][EXT_GET_CURR_NAME()])) {
1222                 // Not found, should not happen
1223                 debug_report_bug(sprintf("ext_sqls is empty, current extension: %s",
1224                 EXT_GET_CURR_NAME()
1225                 ));
1226         } // END - if
1227
1228         // Return the array
1229         return $GLOBALS['ext_sqls'][EXT_GET_CURR_NAME()];
1230 }
1231
1232 // Removes SQLs for current extension
1233 function UNSET_EXT_SQLS () {
1234         unset($GLOBALS['ext_sqls'][EXT_GET_CURR_NAME()]);
1235 }
1236
1237 // Auto-initializes the removal list
1238 function EXT_INIT_REMOVAL_LIST () {
1239         // Is the remove list there?
1240         if (!isset($GLOBALS['ext_update_remove'])) {
1241                 // Then create it
1242                 $GLOBALS['ext_update_remove'] = array();
1243         } // END - if
1244 }
1245
1246 // Checks wether the current extension is on the removal list
1247 function EXT_IS_ON_REMOVAL_LIST () {
1248         // Init removal list
1249         EXT_INIT_REMOVAL_LIST();
1250
1251         // Is it there?
1252         return (in_array(EXT_GET_CURR_NAME(), $GLOBALS['ext_update_remove']));
1253 }
1254
1255 // Adds the current extension to the removal list
1256 function EXT_ADD_CURRENT_TO_REMOVAL_LIST () {
1257         // Simply add it
1258         $GLOBALS['ext_update_remove'][] = EXT_GET_CURR_NAME();
1259 }
1260
1261 // Getter for removal list
1262 function EXT_GET_REMOVAL_LIST () {
1263         // Return the removal list
1264         return $GLOBALS['ext_update_remove'];
1265 }
1266
1267 // Redirects if the provided extension is not installed
1268 function redirectOnUninstalledExtension ($ext_name) {
1269         // So is the extension there?
1270         if ((!isExtensionInstalled($ext_name)) || (!EXT_IS_ACTIVE($ext_name))) {
1271                 // Redirect to index
1272                 redirectToUrl('modules.php?module=index&amp;msg=' . getCode('EXTENSION_PROBLEM') . '&amp;ext=' . $ext_name);
1273         } // END - if
1274 }
1275
1276 // Determines wether the given extension is installed
1277 function isExtensionInstalled ($ext_name) {
1278         // Default is not installed
1279         $isInstalled = false;
1280
1281         // Check cache ext_version
1282         $isInstalled = isset($GLOBALS['cache_array']['extensions']['ext_version'][$ext_name]);
1283
1284         // Return status
1285         return $isInstalled;
1286 }
1287
1288 //
1289 ?>