OSDN Git Service

CHANGE:クエリ生成に使われているi18n::formatted_datetime()をDB::formatDateTime()に変更
[nucleus-jp/nucleus-next.git] / nucleus / libs / ADMIN.php
1 <?php
2 /*
3  * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
4  * Copyright (C) 2002-2009 The Nucleus Group
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  * (see nucleus/documentation/index.html#license for more info)
11  */
12 /**
13  * The code for the Nucleus admin area
14  *
15  * @license http://nucleuscms.org/license.txt GNU General Public License
16  * @copyright Copyright (C) 2002-2009 The Nucleus Group
17  * @version $Id: ADMIN.php 1661 2012-02-12 11:55:39Z sakamocchi $
18
19  */
20
21 if ( !function_exists('requestVar') ) exit;
22 require_once dirname(__FILE__) . '/showlist.php';
23
24 /**
25  * Builds the admin area and executes admin actions
26  */
27 class Admin
28 {
29         private $xml_version_info = '1.0';
30         private $formal_public_identifier = '-//W3C//DTD XHTML 1.0 Strict//EN';
31         private $system_identifier = 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd';
32         private $xhtml_namespace = 'http://www.w3.org/1999/xhtml';
33         
34     /**
35      * @var string $action action currently being executed ($action=xxxx -> action_xxxx method)
36      */
37     var $action;
38
39     /**
40      * Class constructor
41      */
42     function ADMIN() {
43
44     }
45
46     /**
47      * Executes an action
48      *
49      * @param string $action action to be performed
50      */
51     function action($action) {
52         global $CONF, $manager;
53
54         // list of action aliases
55         $alias = array(
56             'login' => 'overview',
57             '' => 'overview'
58         );
59
60         if (isset($alias[$action]))
61             $action = $alias[$action];
62
63         $methodName = 'action_' . $action;
64
65         $this->action = strtolower($action);
66
67         // check ticket. All actions need a ticket, unless they are considered to be safe (a safe action
68         // is an action that requires user interaction before something is actually done)
69         // all safe actions are in this array:
70         $aActionsNotToCheck = array(
71             'showlogin',
72             'login',
73             'overview',
74             'itemlist',
75             'blogcommentlist',
76             'bookmarklet',
77             'blogsettings',
78             'banlist',
79             'deleteblog',
80             'editmembersettings',
81             'browseownitems',
82             'browseowncomments',
83             'createitem',
84             'itemedit',
85             'itemmove',
86             'categoryedit',
87             'categorydelete',
88             'manage',
89             'actionlog',
90             'settingsedit',
91             'backupoverview',
92             'pluginlist',
93             'createnewlog',
94             'usermanagement',
95             'skinoverview',
96             'templateoverview',
97             'skinieoverview',
98             'itemcommentlist',
99             'commentedit',
100             'commentdelete',
101             'banlistnewfromitem',
102             'banlistdelete',
103             'itemdelete',
104             'manageteam',
105             'teamdelete',
106             'banlistnew',
107             'memberedit',
108             'memberdelete',
109             'pluginhelp',
110             'pluginoptions',
111             'plugindelete',
112             'skinedittype',
113             'skinremovetype',
114             'skindelete',
115             'skinedit',
116             'templateedit',
117             'templatedelete',
118             'activate',
119             'systemoverview'
120         );
121 /*
122         // the rest of the actions needs to be checked
123         $aActionsToCheck = array('additem', 'itemupdate', 'itemmoveto', 'categoryupdate', 'categorydeleteconfirm', 'itemdeleteconfirm', 'commentdeleteconfirm', 'teamdeleteconfirm', 'memberdeleteconfirm', 'templatedeleteconfirm', 'skindeleteconfirm', 'banlistdeleteconfirm', 'plugindeleteconfirm', 'batchitem', 'batchcomment', 'batchmember', 'batchcategory', 'batchteam', 'regfile', 'commentupdate', 'banlistadd', 'changemembersettings', 'clearactionlog', 'settingsupdate', 'blogsettingsupdate', 'categorynew', 'teamchangeadmin', 'teamaddmember', 'memberadd', 'addnewlog', 'addnewlog2', 'backupcreate', 'backuprestore', 'pluginup', 'plugindown', 'pluginupdate', 'pluginadd', 'pluginoptionsupdate', 'skinupdate', 'skinclone', 'skineditgeneral', 'templateclone', 'templatenew', 'templateupdate', 'skinieimport', 'skinieexport', 'skiniedoimport', 'skinnew', 'deleteblogconfirm', 'activatesetpwd');
124 */
125         if (!in_array($this->action, $aActionsNotToCheck))
126         {
127             if (!$manager->checkTicket())
128                 $this->error(_ERROR_BADTICKET);
129         }
130
131         if (method_exists($this, $methodName))
132             call_user_func(array(&$this, $methodName));
133         else
134             $this->error(_BADACTION . Entity::hsc(" ($action)"));
135
136     }
137
138     /**
139      * @todo document this
140      */
141     function action_showlogin() {
142         global $error;
143         $this->action_login($error);
144     }
145
146     /**
147      * @todo document this
148      */
149     function action_login($msg = '', $passvars = 1) {
150         global $member;
151
152         // skip to overview when allowed
153         if ($member->isLoggedIn() && $member->canLogin()) {
154             $this->action_overview();
155             exit;
156         }
157
158         $this->pagehead();
159
160         echo '<h2>', _LOGIN ,'</h2>';
161         if ($msg) echo _MESSAGE , ': ', Entity::hsc($msg);
162         ?>
163
164         <form action="index.php" method="post"><p>
165         <?php echo _LOGIN_NAME; ?> <br /><input name="login"  tabindex="10" />
166         <br />
167         <?php echo _LOGIN_PASSWORD; ?> <br /><input name="password"  tabindex="20" type="password" />
168         <br />
169         <input name="action" value="login" type="hidden" />
170         <br />
171         <input type="submit" value="<?php echo _LOGIN ?>" tabindex="30" />
172         <br />
173         <small>
174             <input type="checkbox" value="1" name="shared" tabindex="40" id="shared" /><label for="shared"><?php echo _LOGIN_SHARED ?></label>
175             <br /><a href="forgotpassword.html"><?php echo _LOGIN_FORGOT ?></a>
176         </small>
177         <?php           // pass through vars
178
179             $oldaction = postVar('oldaction');
180             if (  ($oldaction != 'logout')  && ($oldaction != 'login')  && $passvars ) {
181                 passRequestVars();
182             }
183
184
185         ?>
186         </p></form>
187         <?php       $this->pagefoot();
188     }
189
190
191     /**
192      * provides a screen with the overview of the actions available
193      * @todo document parameter
194      */
195     function action_overview($msg = '') {
196         global $member;
197
198         $this->pagehead();
199
200         if ($msg)
201             echo _MESSAGE , ': ', $msg;
202
203         /* ---- add items ---- */
204         echo '<h2>' . _OVERVIEW_YRBLOGS . '</h2>';
205
206         $showAll = requestVar('showall');
207
208         if (($member->isAdmin()) && ($showAll == 'yes')) {
209             // Super-Admins have access to all blogs! (no add item support though)
210             $query =  'SELECT bnumber, bname, 1 as tadmin, burl, bshortname'
211                    . ' FROM ' . sql_table('blog')
212                    . ' ORDER BY bname';
213         } else {
214             $query =  'SELECT bnumber, bname, tadmin, burl, bshortname'
215                    . ' FROM ' . sql_table('blog') . ', ' . sql_table('team')
216                    . ' WHERE tblog=bnumber and tmember=' . $member->getID()
217                    . ' ORDER BY bname';
218         }
219         $template['content'] = 'bloglist';
220         $template['superadmin'] = $member->isAdmin();
221         $amount = showlist($query,'table',$template);
222
223         if (($showAll != 'yes') && ($member->isAdmin())) {
224             $total = DB::getValue('SELECT COUNT(*) as result FROM ' . sql_table('blog'));
225             if ($total > $amount)
226                 echo '<p><a href="index.php?action=overview&amp;showall=yes">' . _OVERVIEW_SHOWALL . '</a></p>';
227         }
228
229         if ($amount == 0)
230             echo _OVERVIEW_NOBLOGS;
231
232         if ($amount != 0) {
233             echo '<h2>' . _OVERVIEW_YRDRAFTS . '</h2>';
234             $query =  'SELECT ititle, inumber, bshortname'
235                    . ' FROM ' . sql_table('item'). ', ' . sql_table('blog')
236                    . ' WHERE iauthor='.$member->getID().' and iblog=bnumber and idraft=1';
237             $template['content'] = 'draftlist';
238             $amountdrafts = showlist($query, 'table', $template);
239             if ($amountdrafts == 0)
240                 echo _OVERVIEW_NODRAFTS;
241         }
242                                 
243                 if ($amount != 0) {
244                         $yrBlogs = $member->getAdminBlogs();
245                         if ($showAll != 'yes') {
246                                 $admBlogs = array();
247                                 foreach ($yrBlogs as $value) {
248                                         if ($member->isBlogAdmin(intval($value))) {
249                                                 $admBlogs[] = intval($value);
250                                         }
251                                 }
252                                 $yrBlogs = $admBlogs;
253                         }
254                         
255                         if (count($yrBlogs) > 0) {
256                                 echo '<h2>' . _OVERVIEW_OTHER_DRAFTS . '</h2>';
257                                 $query =  'SELECT ititle, inumber, bshortname, mname'
258                                            . ' FROM ' . sql_table('item'). ', ' . sql_table('blog'). ', ' . sql_table('member')
259                                            . ' WHERE iauthor<>'.$member->getID().' and iblog IN ('.implode(",",$yrBlogs).') and iblog=bnumber and iauthor=mnumber and idraft=1'
260                                            . ' ORDER BY iblog ASC';
261                                 $template['content'] = 'otherdraftlist';
262                                 $amountdrafts = showlist($query, 'table', $template);
263                                 if ($amountdrafts == 0)
264                                         echo _OVERVIEW_NODRAFTS;
265                         }
266         }
267
268         /* ---- user settings ---- */
269         echo '<h2>' . _OVERVIEW_YRSETTINGS . '</h2>';
270         echo '<ul>';
271         echo '<li><a href="index.php?action=editmembersettings">' . _OVERVIEW_EDITSETTINGS. '</a></li>';
272         echo '<li><a href="index.php?action=browseownitems">' . _OVERVIEW_BROWSEITEMS.'</a></li>';
273         echo '<li><a href="index.php?action=browseowncomments">'._OVERVIEW_BROWSECOMM.'</a></li>';
274         echo '</ul>';
275
276         /* ---- general settings ---- */
277         if ($member->isAdmin()) {
278             echo '<h2>' . _OVERVIEW_MANAGEMENT. '</h2>';
279             echo '<ul>';
280             echo '<li><a href="index.php?action=manage">',_OVERVIEW_MANAGE,'</a></li>';
281             echo '</ul>';
282         }
283
284
285         $this->pagefoot();
286     }
287
288     /**
289      * Returns a link to a weblog
290      * @param object BLOG
291      */
292     function bloglink(&$blog) {
293         return '<a href="'.Entity::hsc($blog->getURL()).'" title="'._BLOGLIST_TT_VISIT.'">'. Entity::hsc( $blog->getName() ) .'</a>';
294     }
295
296     /**
297      * @todo document this
298      */
299     function action_manage($msg = '') {
300         global $member;
301
302         $member->isAdmin() or $this->disallow();
303
304         $this->pagehead();
305
306         echo '<p><a href="index.php?action=overview">(',_BACKHOME,')</a></p>';
307
308         if ($msg)
309             echo '<p>' , _MESSAGE , ': ', $msg , '</p>';
310
311
312         echo '<h2>' . _MANAGE_GENERAL. '</h2>';
313
314         echo '<ul>';
315         echo '<li><a href="index.php?action=createnewlog">'._OVERVIEW_NEWLOG.'</a></li>';
316         echo '<li><a href="index.php?action=settingsedit">'._OVERVIEW_SETTINGS.'</a></li>';
317         echo '<li><a href="index.php?action=usermanagement">'._OVERVIEW_MEMBERS.'</a></li>';
318         echo '<li><a href="index.php?action=actionlog">'._OVERVIEW_VIEWLOG.'</a></li>';
319         echo '</ul>';
320
321         echo '<h2>' . _MANAGE_SKINS . '</h2>';
322         echo '<ul>';
323         echo '<li><a href="index.php?action=skinoverview">'._OVERVIEW_SKINS.'</a></li>';
324         echo '<li><a href="index.php?action=templateoverview">'._OVERVIEW_TEMPLATES.'</a></li>';
325         echo '<li><a href="index.php?action=skinieoverview">'._OVERVIEW_SKINIMPORT.'</a></li>';
326         echo '</ul>';
327
328         echo '<h2>' . _MANAGE_EXTRA . '</h2>';
329         echo '<ul>';
330         echo '<li><a href="index.php?action=backupoverview">'._OVERVIEW_BACKUP.'</a></li>';
331         echo '<li><a href="index.php?action=pluginlist">'._OVERVIEW_PLUGINS.'</a></li>';
332         echo '</ul>';
333
334         $this->pagefoot();
335     }
336
337         /**
338          * Admin::action_itemlist()
339          * 
340          * @param       integer $blogid ID for weblog
341          * @return      void
342          */
343         public function action_itemlist($blogid = '')
344         {
345                 global $member, $manager, $CONF;
346                 
347                 if ( $blogid == '' )
348                 {
349                         $blogid = intRequestVar('blogid');
350                 }
351                 
352                 $member->teamRights($blogid) or $member->isAdmin() or $this->disallow();
353                 
354                 $this->pagehead();
355                 $blog =& $manager->getBlog($blogid);
356                 
357                 echo '<p><a href="index.php?action=overview">(',_BACKHOME,')</a></p>';
358                 echo '<h2>' . _ITEMLIST_BLOG . ' ' . $this->bloglink($blog) . '</h2>';
359                 
360                 // start index
361                 if ( postVar('start') )
362                 {
363                         $start = intPostVar('start');
364                 }
365                 else
366                 {
367                         $start = 0;
368                 }
369                 
370                 if ( $start == 0 )
371                 {
372                         echo '<p><a href="index.php?action=createitem&amp;blogid='.$blogid.'">' . _ITEMLIST_ADDNEW . "</a></p>\n";
373                 }
374                 
375                 // amount of items to show
376                 if ( postVar('amount') )
377                 {
378                         $amount = intPostVar('amount');
379                 }
380                 else
381                 {
382                         $amount = intval($CONF['DefaultListSize']);
383                         if ( $amount < 1 )
384                         {
385                                 $amount = 10;
386                         }
387                 }
388                 
389                 $search = postVar('search');    // search through items
390                 
391                 $query = 'SELECT bshortname, cname, mname, ititle, ibody, inumber, idraft, itime'
392                        . ' FROM ' . sql_table('item') . ', ' . sql_table('blog') . ', ' . sql_table('member') . ', ' . sql_table('category')
393                        . ' WHERE iblog=bnumber and iauthor=mnumber and icat=catid and iblog=' . $blogid;
394                 
395                 if ( $search )
396                 {
397                         $query .= " AND ((ititle LIKE " . DB::quoteValue('%'.$search.'%') . ") OR (ibody LIKE " . DB::quoteValue('%'.$search.'%') . ") OR (imore LIKE " . DB::quoteValue('%'.$search.'%') . "))";
398                 }
399                 
400                 // non-blog-admins can only edit/delete their own items
401                 if ( !$member->blogAdminRights($blogid) )
402                 {
403                         $query .= ' and iauthor=' . $member->getID();
404                 }
405                 
406                 $query .= ' ORDER BY itime DESC'
407                         . " LIMIT $start, $amount";
408                 
409                 $template['content'] = 'itemlist';
410                 $template['now'] = $blog->getCorrectTime(time());
411                 
412                 $manager->loadClass("ENCAPSULATE");
413                 $navList = new NavList('itemlist', $start, $amount, 0, 1000, $blogid, $search, 0);
414                 $navList->showBatchList('item',$query,'table',$template);
415                 
416                 $this->pagefoot();
417                 return;
418         }
419
420     /**
421      * @todo document this
422      */
423     function action_batchitem() {
424         global $member, $manager;
425
426         // check if logged in
427         $member->isLoggedIn() or $this->disallow();
428
429         // more precise check will be done for each performed operation
430
431         // get array of itemids from request
432         $selected = requestIntArray('batch');
433         $action = requestVar('batchaction');
434
435         // Show error when no items were selected
436         if (!is_array($selected) || sizeof($selected) == 0)
437             $this->error(_BATCH_NOSELECTION);
438
439         // On move: when no destination blog/category chosen, show choice now
440         $destCatid = intRequestVar('destcatid');
441         if (($action == 'move') && (!$manager->existsCategory($destCatid)))
442             $this->batchMoveSelectDestination('item',$selected);
443
444         // On delete: check if confirmation has been given
445         if (($action == 'delete') && (requestVar('confirmation') != 'yes'))
446             $this->batchAskDeleteConfirmation('item',$selected);
447
448         $this->pagehead();
449
450         echo '<a href="index.php?action=overview">(',_BACKHOME,')</a>';
451         echo '<h2>',_BATCH_ITEMS,'</h2>';
452         echo '<p>',_BATCH_EXECUTING,' <b>',Entity::hsc($action),'</b></p>';
453         echo '<ul>';
454
455
456         // walk over all itemids and perform action
457         foreach ($selected as $itemid) {
458             $itemid = intval($itemid);
459             echo '<li>',_BATCH_EXECUTING,' <b>',Entity::hsc($action),'</b> ',_BATCH_ONITEM,' <b>', $itemid, '</b>...';
460
461             // perform action, display errors if needed
462             switch($action) {
463                 case 'delete':
464                     $error = $this->deleteOneItem($itemid);
465                     break;
466                 case 'move':
467                     $error = $this->moveOneItem($itemid, $destCatid);
468                     break;
469                 default:
470                     $error = _BATCH_UNKNOWN . Entity::hsc($action);
471             }
472
473             echo '<b>',($error ? $error : _BATCH_SUCCESS),'</b>';
474             echo '</li>';
475         }
476
477         echo '</ul>';
478         echo '<b>',_BATCH_DONE,'</b>';
479
480         $this->pagefoot();
481
482
483     }
484
485     /**
486      * @todo document this
487      */
488     function action_batchcomment() {
489         global $member;
490
491         // check if logged in
492         $member->isLoggedIn() or $this->disallow();
493
494         // more precise check will be done for each performed operation
495
496         // get array of itemids from request
497         $selected = requestIntArray('batch');
498         $action = requestVar('batchaction');
499
500         // Show error when no items were selected
501         if (!is_array($selected) || sizeof($selected) == 0)
502             $this->error(_BATCH_NOSELECTION);
503
504         // On delete: check if confirmation has been given
505         if (($action == 'delete') && (requestVar('confirmation') != 'yes'))
506             $this->batchAskDeleteConfirmation('comment',$selected);
507
508         $this->pagehead();
509
510         echo '<a href="index.php?action=overview">(',_BACKHOME,')</a>';
511         echo '<h2>',_BATCH_COMMENTS,'</h2>';
512         echo '<p>',_BATCH_EXECUTING,' <b>',Entity::hsc($action),'</b></p>';
513         echo '<ul>';
514
515         // walk over all itemids and perform action
516         foreach ($selected as $commentid) {
517             $commentid = intval($commentid);
518             echo '<li>',_BATCH_EXECUTING,' <b>',Entity::hsc($action),'</b> ',_BATCH_ONCOMMENT,' <b>', $commentid, '</b>...';
519
520             // perform action, display errors if needed
521             switch($action) {
522                 case 'delete':
523                     $error = $this->deleteOneComment($commentid);
524                     break;
525                 default:
526                     $error = _BATCH_UNKNOWN . Entity::hsc($action);
527             }
528
529             echo '<b>',($error ? $error : _BATCH_SUCCESS),'</b>';
530             echo '</li>';
531         }
532
533         echo '</ul>';
534         echo '<b>',_BATCH_DONE,'</b>';
535
536         $this->pagefoot();
537
538
539     }
540
541     /**
542      * @todo document this
543      */
544     function action_batchmember() {
545         global $member;
546
547         // check if logged in and admin
548         ($member->isLoggedIn() && $member->isAdmin()) or $this->disallow();
549
550         // get array of itemids from request
551         $selected = requestIntArray('batch');
552         $action = requestVar('batchaction');
553
554         // Show error when no members selected
555         if (!is_array($selected) || sizeof($selected) == 0)
556             $this->error(_BATCH_NOSELECTION);
557
558         // On delete: check if confirmation has been given
559         if (($action == 'delete') && (requestVar('confirmation') != 'yes'))
560             $this->batchAskDeleteConfirmation('member',$selected);
561
562         $this->pagehead();
563
564         echo '<a href="index.php?action=usermanagement">(',_MEMBERS_BACKTOOVERVIEW,')</a>';
565         echo '<h2>',_BATCH_MEMBERS,'</h2>';
566         echo '<p>',_BATCH_EXECUTING,' <b>',Entity::hsc($action),'</b></p>';
567         echo '<ul>';
568
569         // walk over all itemids and perform action
570         foreach ($selected as $memberid) {
571             $memberid = intval($memberid);
572             echo '<li>',_BATCH_EXECUTING,' <b>',Entity::hsc($action),'</b> ',_BATCH_ONMEMBER,' <b>', $memberid, '</b>...';
573
574             // perform action, display errors if needed
575             switch($action) {
576                 case 'delete':
577                     $error = $this->deleteOneMember($memberid);
578                     break;
579                 case 'setadmin':
580                     // always succeeds
581                     DB::execute('UPDATE ' . sql_table('member') . ' SET madmin=1 WHERE mnumber='.$memberid);
582                     $error = '';
583                     break;
584                 case 'unsetadmin':
585                     // there should always remain at least one super-admin
586                     $r = DB::getResult('SELECT * FROM '.sql_table('member'). ' WHERE madmin=1 and mcanlogin=1');
587                     if ($r->rowCount() < 2)
588                         $error = _ERROR_ATLEASTONEADMIN;
589                     else
590                         DB::execute('UPDATE ' . sql_table('member') .' SET madmin=0 WHERE mnumber='.$memberid);
591                     break;
592                 default:
593                     $error = _BATCH_UNKNOWN . Entity::hsc($action);
594             }
595
596             echo '<b>',($error ? $error : _BATCH_SUCCESS),'</b>';
597             echo '</li>';
598         }
599
600         echo '</ul>';
601         echo '<b>',_BATCH_DONE,'</b>';
602
603         $this->pagefoot();
604
605
606     }
607
608     /**
609      * @todo document this
610      */
611     function action_batchteam() {
612         global $member;
613
614         $blogid = intRequestVar('blogid');
615
616         // check if logged in and admin
617         ($member->isLoggedIn() && $member->blogAdminRights($blogid)) or $this->disallow();
618
619         // get array of itemids from request
620         $selected = requestIntArray('batch');
621         $action = requestVar('batchaction');
622
623         // Show error when no members selected
624         if (!is_array($selected) || sizeof($selected) == 0)
625             $this->error(_BATCH_NOSELECTION);
626
627         // On delete: check if confirmation has been given
628         if (($action == 'delete') && (requestVar('confirmation') != 'yes'))
629             $this->batchAskDeleteConfirmation('team',$selected);
630
631         $this->pagehead();
632
633         echo '<p><a href="index.php?action=manageteam&amp;blogid=',$blogid,'">(',_BACK,')</a></p>';
634
635         echo '<h2>',_BATCH_TEAM,'</h2>';
636         echo '<p>',_BATCH_EXECUTING,' <b>',Entity::hsc($action),'</b></p>';
637         echo '<ul>';
638
639         // walk over all itemids and perform action
640         foreach ($selected as $memberid) {
641             $memberid = intval($memberid);
642             echo '<li>',_BATCH_EXECUTING,' <b>',Entity::hsc($action),'</b> ',_BATCH_ONTEAM,' <b>', $memberid, '</b>...';
643
644             // perform action, display errors if needed
645             switch($action) {
646                 case 'delete':
647                     $error = $this->deleteOneTeamMember($blogid, $memberid);
648                     break;
649                 case 'setadmin':
650                     // always succeeds
651                     DB::execute('UPDATE '.sql_table('team').' SET tadmin=1 WHERE tblog='.$blogid.' and tmember='.$memberid);
652                     $error = '';
653                     break;
654                 case 'unsetadmin':
655                     // there should always remain at least one admin
656                     $r = DB::getResult('SELECT * FROM '.sql_table('team').' WHERE tadmin=1 and tblog='.$blogid);
657                     if ($r->rowCount() < 2)
658                         $error = _ERROR_ATLEASTONEBLOGADMIN;
659                     else
660                         DB::execute('UPDATE '.sql_table('team').' SET tadmin=0 WHERE tblog='.$blogid.' and tmember='.$memberid);
661                     break;
662                 default:
663                     $error = _BATCH_UNKNOWN . Entity::hsc($action);
664             }
665
666             echo '<b>',($error ? $error : _BATCH_SUCCESS),'</b>';
667             echo '</li>';
668         }
669
670         echo '</ul>';
671         echo '<b>',_BATCH_DONE,'</b>';
672
673         $this->pagefoot();
674
675
676     }
677
678     /**
679      * @todo document this
680      */
681     function action_batchcategory() {
682         global $member, $manager;
683
684         // check if logged in
685         $member->isLoggedIn() or $this->disallow();
686
687         // more precise check will be done for each performed operation
688
689         // get array of itemids from request
690         $selected = requestIntArray('batch');
691         $action = requestVar('batchaction');
692
693         // Show error when no items were selected
694         if (!is_array($selected) || sizeof($selected) == 0)
695             $this->error(_BATCH_NOSELECTION);
696
697         // On move: when no destination blog chosen, show choice now
698         $destBlogId = intRequestVar('destblogid');
699         if (($action == 'move') && (!$manager->existsBlogID($destBlogId)))
700             $this->batchMoveCategorySelectDestination('category',$selected);
701
702         // On delete: check if confirmation has been given
703         if (($action == 'delete') && (requestVar('confirmation') != 'yes'))
704             $this->batchAskDeleteConfirmation('category',$selected);
705
706         $this->pagehead();
707
708         echo '<a href="index.php?action=overview">(',_BACKHOME,')</a>';
709         echo '<h2>',BATCH_CATEGORIES,'</h2>';
710         echo '<p>',_BATCH_EXECUTING,' <b>',Entity::hsc($action),'</b></p>';
711         echo '<ul>';
712
713         // walk over all itemids and perform action
714         foreach ($selected as $catid) {
715             $catid = intval($catid);
716             echo '<li>',_BATCH_EXECUTING,' <b>',Entity::hsc($action),'</b> ',_BATCH_ONCATEGORY,' <b>', $catid, '</b>...';
717
718             // perform action, display errors if needed
719             switch($action) {
720                 case 'delete':
721                     $error = $this->deleteOneCategory($catid);
722                     break;
723                 case 'move':
724                     $error = $this->moveOneCategory($catid, $destBlogId);
725                     break;
726                 default:
727                     $error = _BATCH_UNKNOWN . Entity::hsc($action);
728             }
729
730             echo '<b>',($error ? _ERROR . ': '.$error : _BATCH_SUCCESS),'</b>';
731             echo '</li>';
732         }
733
734         echo '</ul>';
735         echo '<b>',_BATCH_DONE,'</b>';
736
737         $this->pagefoot();
738
739     }
740
741     /**
742      * @todo document this
743      */
744     function batchMoveSelectDestination($type, $ids) {
745         global $manager;
746         $this->pagehead();
747         ?>
748         <h2><?php echo _MOVE_TITLE ?></h2>
749         <form method="post" action="index.php"><div>
750
751             <input type="hidden" name="action" value="batch<?php echo $type ?>" />
752             <input type="hidden" name="batchaction" value="move" />
753             <?php
754                 $manager->addTicketHidden();
755
756                 // insert selected item numbers
757                 $idx = 0;
758                 foreach ($ids as $id)
759                     echo '<input type="hidden" name="batch[',($idx++),']" value="',intval($id),'" />';
760
761                 // show blog/category selection list
762                 $this->selectBlogCategory('destcatid');
763
764             ?>
765
766
767             <input type="submit" value="<?php echo _MOVE_BTN ?>" onclick="return checkSubmit();" />
768
769         </div></form>
770         <?php       $this->pagefoot();
771         exit;
772     }
773
774     /**
775      * @todo document this
776      */
777     function batchMoveCategorySelectDestination($type, $ids) {
778         global $manager;
779         $this->pagehead();
780         ?>
781         <h2><?php echo _MOVECAT_TITLE ?></h2>
782         <form method="post" action="index.php"><div>
783
784             <input type="hidden" name="action" value="batch<?php echo $type ?>" />
785             <input type="hidden" name="batchaction" value="move" />
786             <?php
787                 $manager->addTicketHidden();
788
789                 // insert selected item numbers
790                 $idx = 0;
791                 foreach ($ids as $id)
792                     echo '<input type="hidden" name="batch[',($idx++),']" value="',intval($id),'" />';
793
794                 // show blog/category selection list
795                 $this->selectBlog('destblogid');
796
797             ?>
798
799
800             <input type="submit" value="<?php echo _MOVECAT_BTN ?>" onclick="return checkSubmit();" />
801
802         </div></form>
803         <?php       $this->pagefoot();
804         exit;
805     }
806
807     /**
808      * @todo document this
809      */
810     function batchAskDeleteConfirmation($type, $ids) {
811         global $manager;
812
813         $this->pagehead();
814         ?>
815         <h2><?php echo _BATCH_DELETE_CONFIRM ?></h2>
816         <form method="post" action="index.php"><div>
817
818             <input type="hidden" name="action" value="batch<?php echo $type ?>" />
819             <?php $manager->addTicketHidden() ?>
820             <input type="hidden" name="batchaction" value="delete" />
821             <input type="hidden" name="confirmation" value="yes" />
822             <?php               // insert selected item numbers
823                 $idx = 0;
824                 foreach ($ids as $id)
825                     echo '<input type="hidden" name="batch[',($idx++),']" value="',intval($id),'" />';
826
827                 // add hidden vars for team & comment
828                 if ($type == 'team')
829                 {
830                     echo '<input type="hidden" name="blogid" value="',intRequestVar('blogid'),'" />';
831                 }
832                 if ($type == 'comment')
833                 {
834                     echo '<input type="hidden" name="itemid" value="',intRequestVar('itemid'),'" />';
835                 }
836
837             ?>
838
839             <input type="submit" value="<?php echo _BATCH_DELETE_CONFIRM_BTN ?>" onclick="return checkSubmit();" />
840
841         </div></form>
842         <?php       $this->pagefoot();
843         exit;
844     }
845
846
847     /**
848      * Inserts a HTML select element with choices for all categories to which the current
849      * member has access
850      * @see function selectBlog
851      */
852     function selectBlogCategory($name, $selected = 0, $tabindex = 0, $showNewCat = 0, $iForcedBlogInclude = -1) {
853         Admin::selectBlog($name, 'category', $selected, $tabindex, $showNewCat, $iForcedBlogInclude);
854     }
855
856         /**
857          * Admin::selectBlog()
858          * Inserts a HTML select element with choices for all blogs to which the user has access
859          *  mode = 'blog' => shows blognames and values are blogids
860          *  mode = 'category' => show category names and values are catids
861          * 
862          * @param       string  $name                           name of 
863          * @param       string  $mode                           blog/category
864          * @param       integer $selected                       category ID to be selected
865          * @param       integer $tabindex                       tab index value
866          * @param       integer $showNewCat                     show category to newly be created
867          * @param       integer $iForcedBlogInclude     ID of a blog that always needs to be included,
868          *                                              without checking if the member is on the blog team (-1 = none)
869          * @return      void
870          */
871         public function selectBlog($name, $mode='blog', $selected = 0, $tabindex = 0, $showNewCat = 0, $iForcedBlogInclude = -1)
872         {
873                 global $member, $CONF;
874                 
875                 // 0. get IDs of blogs to which member can post items (+ forced blog)
876                 $aBlogIds = array();
877                 if ( $iForcedBlogInclude != -1 )
878                 {
879                         $aBlogIds[] = intval($iForcedBlogInclude);
880                 }
881                 
882                 if ( !$member->isAdmin() || !array_key_exists('ShowAllBlogs', $CONF) || !$CONF['ShowAllBlogs'] )
883                 {
884                         $query = "SELECT bnumber FROM %s,%s WHERE tblog=bnumber and tmember=%d;";
885                         $query = sprintf($query, sql_table('blog'), sql_table('team'), (integer) $member->getID());
886                 }
887                 else
888                 {
889                         $query = "SELECT bnumber FROM %s ORDER BY bname;";
890                         $query = sprintf($query, sql_table('blog'));
891                 }
892                 
893                 $rblogids = DB::getResult($query);
894                 foreach ( $rblogids as $row )
895                 {
896                         if ( $row['bnumber'] != $iForcedBlogInclude )
897                         {
898                                 $aBlogIds[] = (integer) $row['bnumber'];
899                         }
900                 }
901                 if ( count($aBlogIds) == 0 )
902                 {
903                         return;
904                 }
905                 
906                 echo "<select name=\"{$name}\" tabindex=\"{$tabindex}\">\n";
907                 
908                 // 1. select blogs (we'll create optiongroups)
909                 // (only select those blogs that have the user on the team)
910                 $query = "SELECT bnumber, bname FROM %s WHERE bnumber in (%s) ORDER BY bname;";
911                 $query = sprintf($query, sql_table('blog'), implode(',',$aBlogIds));
912                 $blogs = DB::getResult($query);
913                 
914                 if ( $mode == 'category' )
915                 {
916                         if ( $blogs->rowCount() > 1 )
917                         {
918                                 $multipleBlogs = 1;
919                         }
920                         
921                         foreach ( $blogs as $row )
922                         {
923                                 if ( $multipleBlogs )
924                                 {
925                                         echo '<optgroup label="' . Entity::hsc($row['bname']) . '">' . "\n";
926                                 }
927                                 
928                                 // show selection to create new category when allowed/wanted
929                                 if ( $showNewCat )
930                                 {
931                                         // check if allowed to do so
932                                         if ( $member->blogAdminRights($row['bnumber']) )
933                                         {
934                                                 echo "<option value=\"newcat-{$row['bnumber']}\">" . _ADD_NEWCAT . "</option>\n";
935                                         }
936                                 }
937                                 
938                                 // 2. for each category in that blog
939                                 $query = "SELECT cname, catid FROM %s WHERE cblog=%d ORDER BY cname ASC;";
940                                 $query = sprintf($query, sql_table('category'), (integer) $row['bnumber']);
941                                 $categories = DB::getResult($query);
942                                 foreach ( $categories as $cat )
943                                 {
944                                         if ( $cat['catid'] != $selected )
945                                         {
946                                         echo "<option value=\"{$cat['catid']}\" {$selectText} >" . Entity::hsc($cat['cname']) . "</option>\n";
947                                         }
948                                         else
949                                         {
950                                         echo "<option value=\"{$cat['catid']}\" selected=\"selected\" >" . Entity::hsc($cat['cname']) . "</option>\n";
951                                         }
952                                 }
953                                 
954                                 if ( $multipleBlogs )
955                                 {
956                                         echo "</optgroup>\n";
957                                 }
958                         }
959                 }
960                 else
961                 {
962                         // blog mode
963                         foreach ( $blogs as $row )
964                         {
965                                 if ( $row['bnumber'] != $selected )
966                                 {
967                                         echo "<option value=\"{$row['bnumber']}\">" . Entity::hsc($row['bname']) . "</option>\n";
968                                 }
969                                 else
970                                 {
971                                         echo "<option value=\"{$row['bnumber']}\" selected=\"selected\">" . Entity::hsc($row['bname']) . "</option>\n";
972                                 }
973                         }
974                 }
975                 echo "</select>\n";
976                 return;
977         }
978         
979         /**
980          * Admin::action_browseownitems()
981          * 
982          * @param       void
983          * @return      void
984          */
985         public function action_browseownitems()
986         {
987                 global $member, $manager, $CONF;
988                 
989                 $this->pagehead();
990                 
991                 echo '<p><a href="index.php?action=overview">(' . _BACKHOME . ")</a></p>\n";
992                 echo '<h2>' . _ITEMLIST_YOUR . "</h2>\n";
993                 
994                 // start index
995                 if ( postVar('start') )
996                 {
997                         $start = intPostVar('start');
998                 }
999                 else
1000                 {
1001                         $start = 0;
1002                 }
1003                 
1004                 // amount of items to show
1005                 if ( postVar('amount') )
1006                 {
1007                         $amount = intPostVar('amount');
1008                 }
1009                 else
1010                 {
1011                         $amount = (integer) $CONF['DefaultListSize'];
1012                         if ( $amount < 1 )
1013                         {
1014                                 $amount = 10;
1015                         }
1016                 }
1017                 
1018                 $search = postVar('search');    // search through items
1019                 
1020                 $query = 'SELECT bshortname, cname, mname, ititle, ibody, idraft, inumber, itime'
1021                        . ' FROM '.sql_table('item').', '.sql_table('blog') . ', '.sql_table('member') . ', '.sql_table('category')
1022                        . ' WHERE iauthor='. $member->getID() .' and iauthor=mnumber and iblog=bnumber and icat=catid';
1023                 
1024                 if ( $search )
1025                 {
1026                         $query .= " and ((ititle LIKE " . DB::quoteValue('%'.$search.'%') . ") or (ibody LIKE " . DB::quoteValue('%'.$search.'%') . ") or (imore LIKE " . DB::quoteValue('%'.$search.'%') . "))";
1027                 }
1028                 
1029                 $query .= ' ORDER BY itime DESC'
1030                         . " LIMIT $start, $amount";
1031                 
1032                 $template['content'] = 'itemlist';
1033                 $template['now'] = time();
1034                 
1035                 $manager->loadClass("ENCAPSULATE");
1036                 $navList = new NavList('browseownitems', $start, $amount, 0, 1000, /*$blogid*/ 0, $search, 0);
1037                 $navList->showBatchList('item',$query,'table',$template);
1038                 
1039                 $this->pagefoot();
1040                 return;
1041         }
1042         
1043         /**
1044          * Admin::action_itemcommentlist()
1045          * 
1046          * Show all the comments for a given item
1047          * @param       integer $itemid ID for item
1048          * @return      void
1049          */
1050         public function action_itemcommentlist($itemid = '')
1051         {
1052                 global $member, $manager, $CONF;
1053                 
1054                 if ( $itemid == '' )
1055                 {
1056                         $itemid = intRequestVar('itemid');
1057                 }
1058                 
1059                 // only allow if user is allowed to alter item
1060                 $member->canAlterItem($itemid) or $this->disallow();
1061                 
1062                 $blogid = getBlogIdFromItemId($itemid);
1063                 
1064                 $this->pagehead();
1065                 
1066                 // start index
1067                 if ( postVar('start') )
1068                 {
1069                         $start = intPostVar('start');
1070                 }
1071                 else
1072                 {
1073                         $start = 0;
1074                 }
1075                 
1076                 // amount of items to show
1077                 if ( postVar('amount') )
1078                 {
1079                         $amount = intPostVar('amount');
1080                 }
1081                 else
1082                 {
1083                         $amount = (integer) $CONF['DefaultListSize'];
1084                         if ( $amount < 1 )
1085                         {
1086                                 $amount = 10;
1087                         }
1088                 }
1089                 
1090                 $search = postVar('search');
1091                 
1092                 echo '<p>(<a href="index.php?action=itemlist&amp;blogid=' . $blogid . '">' . _BACKTOOVERVIEW . "</a>)</p>\n";
1093                 echo '<h2>',_COMMENTS,'</h2>';
1094                 
1095                 $query = 'SELECT cbody, cuser, cmail, cemail, mname, ctime, chost, cnumber, cip, citem FROM ' . sql_table('comment') . ' LEFT OUTER JOIN ' . sql_table('member') . ' ON mnumber = cmember WHERE citem = ' . $itemid;
1096                 
1097                 if ( $search )
1098                 {
1099                         $query .= " and cbody LIKE " . DB::quoteValue('%'.$search.'%');
1100                 }
1101                 
1102                 $query .= ' ORDER BY ctime ASC'
1103                         . " LIMIT $start,$amount";
1104                 
1105                 $template['content'] = 'commentlist';
1106                 $template['canAddBan'] = $member->blogAdminRights(getBlogIDFromItemID($itemid));
1107                 
1108                 $manager->loadClass("ENCAPSULATE");
1109                 $navList = new NavList('itemcommentlist', $start, $amount, 0, 1000, 0, $search, $itemid);
1110                 $navList->showBatchList('comment',$query,'table',$template,_NOCOMMENTS);
1111                 
1112                 $this->pagefoot();
1113                 return;
1114         }
1115         
1116         /**
1117          * Admin::action_browseowncomments()
1118          * Browse own comments
1119          * 
1120          * @param       void
1121          * @return      void
1122          */
1123         public function action_browseowncomments()
1124         {
1125                 global $member, $manager, $CONF;
1126                 
1127                 // start index
1128                 if ( postVar('start') )
1129                 {
1130                         $start = intPostVar('start');
1131                 }
1132                 else
1133                 {
1134                         $start = 0;
1135                 }
1136                 
1137                 // amount of items to show
1138                 if ( postVar('amount') )
1139                 {
1140                         $amount = intPostVar('amount');
1141                 }
1142                 else
1143                 {
1144                         $amount = intval($CONF['DefaultListSize']);
1145                         if ( $amount < 1 )
1146                         {
1147                                 $amount = 10;
1148                         }
1149                 }
1150                 
1151                 $search = postVar('search');
1152                 
1153                 $query =  'SELECT cbody, cuser, cmail, mname, ctime, chost, cnumber, cip, citem FROM '.sql_table('comment').' LEFT OUTER JOIN '.sql_table('member').' ON mnumber=cmember WHERE cmember=' . $member->getID();
1154                 
1155                 if ( $search )
1156                 {
1157                         $query .= " and cbody LIKE " . DB::quoteValue('%'.$search.'%');
1158                 }
1159                 
1160                 $query .= ' ORDER BY ctime DESC'
1161                         . " LIMIT $start,$amount";
1162                 
1163                 $this->pagehead();
1164                 
1165                 echo '<p><a href="index.php?action=overview">(' . _BACKHOME . ")</a></p>\n";
1166                 echo '<h2>' . _COMMENTS_YOUR . "</h2>\n";
1167                 
1168                 $template['content'] = 'commentlist';
1169                 $template['canAddBan'] = 0; // doesn't make sense to allow banning yourself
1170                 
1171                 $manager->loadClass("ENCAPSULATE");
1172                 $navList = new NavList('browseowncomments', $start, $amount, 0, 1000, 0, $search, 0);
1173                 $navList->showBatchList('comment',$query,'table',$template,_NOCOMMENTS_YOUR);
1174                 
1175                 $this->pagefoot();
1176                 return;
1177         }
1178         
1179         /**
1180          * Admin::action_blogcommentlist()
1181          * 
1182          * Browse all comments for a weblog
1183          * @param       integer $blogid ID for weblog
1184          * @return      void
1185          */
1186         function action_blogcommentlist($blogid = '')
1187         {
1188                 global $member, $manager, $CONF;
1189                 
1190                 if ( $blogid == '' )
1191                 {
1192                         $blogid = intRequestVar('blogid');
1193                 }
1194                 else
1195                 {
1196                         $blogid = intval($blogid);
1197                 }
1198                 
1199                 $member->teamRights($blogid) or $member->isAdmin() or $this->disallow();
1200                 
1201                 // start index
1202                 if ( postVar('start') )
1203                 {
1204                         $start = intPostVar('start');
1205                 }
1206                 else
1207                 {
1208                         $start = 0;
1209                 }
1210                 
1211                 // amount of items to show
1212                 if ( postVar('amount') )
1213                 {
1214                         $amount = intPostVar('amount');
1215                 }
1216                 else
1217                 {
1218                         $amount = intval($CONF['DefaultListSize']);
1219                         if ( $amount < 1 )
1220                         {
1221                                 $amount = 10;
1222                         }
1223                 }
1224                 
1225                 $search = postVar('search');            // search through comments
1226                 
1227                 $query =  'SELECT cbody, cuser, cemail, cmail, mname, ctime, chost, cnumber, cip, citem FROM '.sql_table('comment').' LEFT OUTER JOIN '.sql_table('member').' ON mnumber=cmember WHERE cblog=' . intval($blogid);
1228                 
1229                 if ( $search != '' )
1230                 {
1231                         $query .= " and cbody LIKE " . DB::quoteValue('%'.$search.'%');
1232                 }
1233                 
1234                 $query .= ' ORDER BY ctime DESC'
1235                         . " LIMIT $start,$amount";
1236                 
1237                 $blog =& $manager->getBlog($blogid);
1238                 
1239                 $this->pagehead();
1240                 
1241                 echo '<p><a href="index.php?action=overview">(' . _BACKHOME . ")</a></p>\n";
1242                 echo '<h2>', _COMMENTS_BLOG , ' ' , $this->bloglink($blog), '</h2>';
1243                 
1244                 $template['content'] = 'commentlist';
1245                 $template['canAddBan'] = $member->blogAdminRights($blogid);
1246                 
1247                 $manager->loadClass("ENCAPSULATE");
1248                 $navList = new NavList('blogcommentlist', $start, $amount, 0, 1000, $blogid, $search, 0);
1249                 $navList->showBatchList('comment',$query,'table',$template, _NOCOMMENTS_BLOG);
1250                 
1251                 $this->pagefoot();
1252                 return;
1253         }
1254         
1255         /**
1256          * Admin::action_createitem()
1257          * Provide a page to item a new item to the given blog
1258          * 
1259          * @param       void
1260          * @return      void
1261          */
1262         public function action_createitem()
1263         {
1264                 global $member, $manager;
1265                 
1266                 $blogid = intRequestVar('blogid');
1267                 
1268                 // check if allowed
1269                 $member->teamRights($blogid) or $this->disallow();
1270                 
1271                 $memberid = $member->getID();
1272                 
1273                 $blog =& $manager->getBlog($blogid);
1274                 
1275                 $this->pagehead();
1276                 
1277                 // generate the add-item form
1278                 $formfactory = new PageFactory($blogid);
1279                 $formfactory->createAddForm('admin');
1280                 
1281                 $this->pagefoot();
1282                 return;
1283         }
1284         
1285         /**
1286          * Admin::action_itemedit()
1287          * 
1288          * @param       void
1289          * @return      void
1290          */
1291         public function action_itemedit()
1292         {
1293                 global $member, $manager;
1294                 
1295                 $itemid = intRequestVar('itemid');
1296                 
1297                 // only allow if user is allowed to alter item
1298                 $member->canAlterItem($itemid) or $this->disallow();
1299                 
1300                 $item =& $manager->getItem($itemid, 1, 1);
1301                 $blog =& $manager->getBlog(getBlogIDFromItemID($itemid));
1302                 
1303                 $manager->notify('PrepareItemForEdit', array('item' => &$item));
1304                 
1305                 if ( $blog->convertBreaks() )
1306                 {
1307                         $item['body'] = removeBreaks($item['body']);
1308                         $item['more'] = removeBreaks($item['more']);
1309                 }
1310                 
1311                 // form to edit blog items
1312                 $this->pagehead();
1313                 $formfactory = new PageFactory($blog->getID());
1314                 $formfactory->createEditForm('admin', $item);
1315                 $this->pagefoot();
1316                 return;
1317         }
1318         
1319     /**
1320      * @todo document this
1321      */
1322     function action_itemupdate() {
1323         global $member, $manager, $CONF;
1324
1325         $itemid = intRequestVar('itemid');
1326         $catid = postVar('catid');
1327
1328         // only allow if user is allowed to alter item
1329         $member->canUpdateItem($itemid, $catid) or $this->disallow();
1330
1331         $actiontype = postVar('actiontype');
1332
1333         // delete actions are handled by itemdelete (which has confirmation)
1334         if ($actiontype == 'delete') {
1335             $this->action_itemdelete();
1336             return;
1337         }
1338
1339         $body   = postVar('body');
1340         $title  = postVar('title');
1341         $more   = postVar('more');
1342         $closed = intPostVar('closed');
1343         $draftid = intPostVar('draftid');
1344
1345         // default action = add now
1346         if (!$actiontype)
1347             $actiontype='addnow';
1348
1349         // create new category if needed
1350         if (strstr($catid,'newcat')) {
1351             // get blogid
1352             list($blogid) = sscanf($catid,"newcat-%d");
1353
1354             // create
1355             $blog =& $manager->getBlog($blogid);
1356             $catid = $blog->createNewCategory();
1357
1358             // show error when sth goes wrong
1359             if (!$catid)
1360                 $this->doError(_ERROR_CATCREATEFAIL);
1361         }
1362
1363         /*
1364             set some variables based on actiontype
1365
1366             actiontypes:
1367                 draft items -> addnow, addfuture, adddraft, delete
1368                 non-draft items -> edit, changedate, delete
1369
1370             variables set:
1371                 $timestamp: set to a nonzero value for future dates or date changes
1372                 $wasdraft: set to 1 when the item used to be a draft item
1373                 $publish: set to 1 when the edited item is not a draft
1374         */
1375         $blogid =  getBlogIDFromItemID($itemid);
1376         $blog   =& $manager->getBlog($blogid);
1377
1378         $wasdrafts = array('adddraft', 'addfuture', 'addnow');
1379         $wasdraft  = in_array($actiontype, $wasdrafts) ? 1 : 0;
1380         $publish   = ($actiontype != 'adddraft' && $actiontype != 'backtodrafts') ? 1 : 0;
1381         if ($actiontype == 'addfuture' || $actiontype == 'changedate') {
1382             $timestamp = mktime(intPostVar('hour'), intPostVar('minutes'), 0, intPostVar('month'), intPostVar('day'), intPostVar('year'));
1383         } else {
1384             $timestamp =0;
1385         }
1386
1387         // edit the item for real
1388         Item::update($itemid, $catid, $title, $body, $more, $closed, $wasdraft, $publish, $timestamp);
1389
1390         $this->updateFuturePosted($blogid);
1391
1392         if ($draftid > 0) {
1393             // delete permission is checked inside Item::delete()
1394             Item::delete($draftid);
1395         }
1396
1397         // show category edit window when we created a new category
1398         // ($catid will then be a new category ID, while postVar('catid') will be 'newcat-x')
1399         if ($catid != intPostVar('catid')) {
1400             $this->action_categoryedit(
1401                 $catid,
1402                 $blog->getID(),
1403                 $CONF['AdminURL'] . 'index.php?action=itemlist&blogid=' . getBlogIDFromItemID($itemid)
1404             );
1405         } else {
1406             // TODO: set start item correctly for itemlist
1407             $this->action_itemlist(getBlogIDFromItemID($itemid));
1408         }
1409     }
1410         
1411         /**
1412          * Admin::action_itemdelete()
1413          * Delete item
1414          * 
1415          * @param       Void
1416          * @return      Void
1417          */
1418         function action_itemdelete()
1419         {
1420                 global $member, $manager;
1421                 
1422                 $itemid = intRequestVar('itemid');
1423                 
1424                 // only allow if user is allowed to alter item
1425                 $member->canAlterItem($itemid) or $this->disallow();
1426                 
1427                 if ( !$manager->existsItem($itemid,1,1) )
1428                 {
1429                         $this->error(_ERROR_NOSUCHITEM);
1430                 }
1431                 
1432                 $item =& $manager->getItem($itemid,1,1);
1433                 $title = Entity::hsc(strip_tags($item['title']));
1434                 $body = strip_tags($item['body']);
1435                 $body = Entity::hsc(Entity::shorten($body,300,'...'));
1436                 
1437                 $this->pagehead();
1438                 echo '<h2>' . _DELETE_CONFIRM . "</h2>\n";
1439                 echo '<p>' . _CONFIRMTXT_ITEM . "</p>\n";
1440                 echo "<div class=\"note\">\n";
1441                 echo "<b>{$title}</b>\n";
1442                 echo "<br />\n";
1443                 echo "{$body}\n";
1444                 echo "</div>\n";
1445                 echo "<form method=\"post\" action=\"index.php\">\n";
1446                 echo "<div>\n";
1447                 echo "<input type=\"hidden\" name=\"action\" value=\"itemdeleteconfirm\" />\n";
1448                 echo $manager->addTicketHidden() . "\n";
1449                 echo "<input type=\"hidden\" name=\"itemid\" value=\"{$itemid}\" />\n";
1450                 echo '<input type="submit" value="' . _DELETE_CONFIRM_BTN . "\"  tabindex=\"10\" />\n";
1451                 echo "</div>\n";
1452                 echo "</form>\n";
1453                 $this->pagefoot();
1454                 return;
1455         }
1456         
1457     /**
1458      * @todo document this
1459      */
1460     function action_itemdeleteconfirm() {
1461         global $member;
1462
1463         $itemid = intRequestVar('itemid');
1464
1465         // only allow if user is allowed to alter item
1466         $member->canAlterItem($itemid) or $this->disallow();
1467
1468         // get blogid first
1469         $blogid = getBlogIdFromItemId($itemid);
1470
1471         // delete item (note: some checks will be performed twice)
1472         $this->deleteOneItem($itemid);
1473
1474         $this->action_itemlist($blogid);
1475     }
1476
1477     /**
1478      * Deletes one item and returns error if something goes wrong
1479      * @param int $itemid
1480      */
1481     function deleteOneItem($itemid) {
1482         global $member, $manager;
1483
1484         // only allow if user is allowed to alter item (also checks if itemid exists)
1485         if (!$member->canAlterItem($itemid))
1486             return _ERROR_DISALLOWED;
1487
1488         // need to get blogid before the item is deleted
1489         $blogid = getBlogIDFromItemId($itemid);
1490
1491         $manager->loadClass('ITEM');
1492         Item::delete($itemid);
1493
1494         // update blog's futureposted
1495         $this->updateFuturePosted($blogid);
1496     }
1497
1498         /**
1499          * Admin::updateFuturePosted()
1500          * Update a blog's future posted flag
1501          * 
1502          * @param integer $blogid
1503          * @return      void
1504          * 
1505          */
1506         function updateFuturePosted($blogid)
1507         {
1508                 global $manager;
1509                 
1510                 $blog =& $manager->getBlog($blogid);
1511                 $currenttime = $blog->getCorrectTime(time());
1512                 
1513                 $query = "SELECT * FROM %s WHERE iblog=%d AND iposted=0 AND itime>'%s'";
1514                 $query = sprintf($query, sql_table('item'), (integer) $blogid, DB::formatDateTime($currenttime));
1515                 $result = DB::getResult($query);
1516                 
1517                 if ( $result->rowCount() > 0 )
1518                 {
1519                                 $blog->setFuturePost();
1520                 }
1521                 else
1522                 {
1523                                 $blog->clearFuturePost();
1524                 }
1525                 return;
1526         }
1527
1528     /**
1529      * @todo document this
1530      */
1531     function action_itemmove() {
1532         global $member, $manager;
1533
1534         $itemid = intRequestVar('itemid');
1535
1536         // only allow if user is allowed to alter item
1537         $member->canAlterItem($itemid) or $this->disallow();
1538
1539         $item =& $manager->getItem($itemid,1,1);
1540
1541         $this->pagehead();
1542         ?>
1543             <h2><?php echo _MOVE_TITLE ?></h2>
1544             <form method="post" action="index.php"><div>
1545                 <input type="hidden" name="action" value="itemmoveto" />
1546                 <input type="hidden" name="itemid" value="<?php echo  $itemid; ?>" />
1547
1548                 <?php
1549
1550                     $manager->addTicketHidden();
1551                     $this->selectBlogCategory('catid',$item['catid'],10,1);
1552                 ?>
1553
1554                 <input type="submit" value="<?php echo _MOVE_BTN ?>" tabindex="10000" onclick="return checkSubmit();" />
1555             </div></form>
1556         <?php
1557         $this->pagefoot();
1558     }
1559
1560     /**
1561      * @todo document this
1562      */
1563     function action_itemmoveto() {
1564         global $member, $manager;
1565
1566         $itemid = intRequestVar('itemid');
1567         $catid = requestVar('catid');
1568
1569         // create new category if needed
1570         if (strstr($catid,'newcat')) {
1571             // get blogid
1572             list($blogid) = sscanf($catid,'newcat-%d');
1573
1574             // create
1575             $blog =& $manager->getBlog($blogid);
1576             $catid = $blog->createNewCategory();
1577
1578             // show error when sth goes wrong
1579             if (!$catid)
1580                 $this->doError(_ERROR_CATCREATEFAIL);
1581         }
1582
1583         // only allow if user is allowed to alter item
1584         $member->canUpdateItem($itemid, $catid) or $this->disallow();
1585
1586         $old_blogid = getBlogIDFromItemId($itemid);
1587
1588         Item::move($itemid, $catid);
1589
1590         // set the futurePosted flag on the blog
1591         $this->updateFuturePosted(getBlogIDFromItemId($itemid));
1592
1593         // reset the futurePosted in case the item is moved from one blog to another
1594         $this->updateFuturePosted($old_blogid);
1595
1596         if ($catid != intRequestVar('catid'))
1597             $this->action_categoryedit($catid, $blog->getID());
1598         else
1599             $this->action_itemlist(getBlogIDFromCatID($catid));
1600     }
1601
1602     /**
1603      * Moves one item to a given category (category existance should be checked by caller)
1604      * errors are returned
1605      * @param int $itemid
1606      * @param int $destCatid category ID to which the item will be moved
1607      */
1608     function moveOneItem($itemid, $destCatid) {
1609         global $member;
1610
1611         // only allow if user is allowed to move item
1612         if (!$member->canUpdateItem($itemid, $destCatid))
1613             return _ERROR_DISALLOWED;
1614
1615         Item::move($itemid, $destCatid);
1616     }
1617
1618     /**
1619      * Adds a item to the chosen blog
1620      */
1621     function action_additem() {
1622         global $manager, $CONF;
1623
1624         $manager->loadClass('ITEM');
1625
1626         $result = Item::createFromRequest();
1627
1628         if ($result['status'] == 'error')
1629             $this->error($result['message']);
1630
1631         $blogid = getBlogIDFromItemID($result['itemid']);
1632         $blog =& $manager->getBlog($blogid);
1633         $btimestamp = $blog->getCorrectTime();
1634         $item       = $manager->getItem(intval($result['itemid']), 1, 1);
1635
1636         if ($result['status'] == 'newcategory') {
1637             $distURI = $manager->addTicketToUrl($CONF['AdminURL'] . 'index.php?action=itemList&blogid=' . intval($blogid));
1638             $this->action_categoryedit($result['catid'], $blogid, $distURI);
1639         } else {
1640             $methodName = 'action_itemList';
1641             call_user_func(array(&$this, $methodName), $blogid);
1642         }
1643     }
1644
1645         /**
1646          * Allows to edit previously made comments
1647          **/
1648         function action_commentedit() {
1649
1650                 global $member, $manager;
1651
1652                 $commentid = intRequestVar('commentid');
1653
1654                 $member->canAlterComment($commentid) or $this->disallow();
1655
1656                 $comment = Comment::getComment($commentid);
1657
1658                 $manager->notify('PrepareCommentForEdit', array('comment' => &$comment) );
1659
1660                 // change <br /> to \n
1661                 $comment['body'] = str_replace('<br />', '', $comment['body']);
1662
1663                 // replaced eregi_replace() below with preg_replace(). ereg* functions are deprecated in PHP 5.3.0
1664                 /* original eregi_replace: eregi_replace("<a href=['\"]([^'\"]+)['\"]( rel=\"nofollow\") ?>[^<]*</a>", "\\1", $comment['body']) */
1665
1666         $comment['body'] = preg_replace("#<a href=['\"]([^'\"]+)['\"]( rel=\"nofollow\") ?>[^<]*</a>#i", "\\1", $comment['body']);
1667
1668         $this->pagehead();
1669
1670         ?>
1671         <h2><?php echo _EDITC_TITLE ?></h2>
1672
1673         <form action="index.php" method="post"><div>
1674
1675         <input type="hidden" name="action" value="commentupdate" />
1676         <?php $manager->addTicketHidden(); ?>
1677         <input type="hidden" name="commentid" value="<?php echo  $commentid; ?>" />
1678         <table><tr>
1679             <th colspan="2"><?php echo _EDITC_TITLE ?></th>
1680         </tr><tr>
1681             <td><?php echo _EDITC_WHO ?></td>
1682             <td>
1683             <?php               if ($comment['member'])
1684                     echo $comment['member'] . " (" . _EDITC_MEMBER . ")";
1685                 else
1686                     echo $comment['user'] . " (" . _EDITC_NONMEMBER . ")";
1687             ?>
1688             </td>
1689         </tr><tr>
1690             <td><?php echo _EDITC_WHEN ?></td>
1691             <td><?php echo  date("Y-m-d @ H:i",$comment['timestamp']); ?></td>
1692         </tr><tr>
1693             <td><?php echo _EDITC_HOST ?></td>
1694             <td><?php echo  $comment['host']; ?></td>
1695         </tr>
1696         <tr>
1697             <td><?php echo _EDITC_URL; ?></td>
1698             <td><input type="text" name="url" size="30" tabindex="6" value="<?php echo $comment['userid']; ?>" /></td>
1699         </tr>
1700         <tr>
1701             <td><?php echo _EDITC_EMAIL; ?></td>
1702             <td><input type="text" name="email" size="30" tabindex="8" value="<?php echo $comment['email']; ?>" /></td>
1703         </tr>
1704         <tr>
1705             <td><?php echo _EDITC_TEXT ?></td>
1706             <td>
1707                 <textarea name="body" tabindex="10" rows="10" cols="50"><?php                   // htmlspecialchars not needed (things should be escaped already)
1708                     echo $comment['body'];
1709                 ?></textarea>
1710             </td>
1711         </tr><tr>
1712             <td><?php echo _EDITC_EDIT ?></td>
1713             <td><input type="submit"  tabindex="20" value="<?php echo _EDITC_EDIT ?>" onclick="return checkSubmit();" /></td>
1714         </tr></table>
1715
1716         </div></form>
1717         <?php
1718         $this->pagefoot();
1719     }
1720
1721     /**
1722      * @todo document this
1723      */
1724     function action_commentupdate() {
1725         global $member, $manager;
1726
1727         $commentid = intRequestVar('commentid');
1728
1729         $member->canAlterComment($commentid) or $this->disallow();
1730
1731         $url = postVar('url');
1732         $email = postVar('email');
1733         $body = postVar('body');
1734
1735                 # replaced eregi() below with preg_match(). ereg* functions are deprecated in PHP 5.3.0
1736                 # original eregi: eregi("[a-zA-Z0-9|\.,;:!\?=\/\\]{90,90}", $body) != FALSE
1737                 # important note that '\' must be matched with '\\\\' in preg* expressions
1738
1739                 // intercept words that are too long
1740                 if (preg_match('#[a-zA-Z0-9|\.,;:!\?=\/\\\\]{90,90}#', $body) != FALSE)
1741                 {
1742                         $this->error(_ERROR_COMMENT_LONGWORD);
1743                 }
1744
1745                 // check length
1746                 if (i18n::strlen($body) < 3)
1747                 {
1748                         $this->error(_ERROR_COMMENT_NOCOMMENT);
1749                 }
1750
1751                 if (i18n::strlen($body) > 5000)
1752                 {
1753                         $this->error(_ERROR_COMMENT_TOOLONG);
1754                 }
1755
1756                 // prepare body
1757                 $body = Comment::prepareBody($body);
1758
1759                 // call plugins
1760                 $manager->notify('PreUpdateComment',array('body' => &$body));
1761
1762                 $query = 'UPDATE ' . sql_table('comment')
1763                         . ' SET cmail = ' . DB::quoteValue($url) . ', cemail = ' . DB::quoteValue($email) . ', cbody = ' . DB::quoteValue($body)
1764                         . ' WHERE cnumber = ' . $commentid;
1765                 DB::execute($query);
1766
1767                 // get itemid
1768                 $res = DB::getValue('SELECT citem FROM '.sql_table('comment').' WHERE cnumber=' . $commentid);
1769                 $itemid = $res;
1770
1771                 if ($member->canAlterItem($itemid))
1772                         $this->action_itemcommentlist($itemid);
1773                 else
1774                         $this->action_browseowncomments();
1775
1776     }
1777         
1778         /**
1779          * Admin::action_commentdelete()
1780          * Update comment
1781          * 
1782          * @param       Void
1783          * @return      Void
1784          */
1785         function action_commentdelete()
1786         {
1787                 global $member, $manager;
1788                 
1789                 $commentid = intRequestVar('commentid');
1790                 $member->canAlterComment($commentid) or $this->disallow();
1791                 $comment = Comment::getComment($commentid);
1792                 
1793                 $body = strip_tags($comment['body']);
1794                 $body = Entity::hsc(Entity::shorten($body, 300, '...'));
1795                 
1796                 if ( $comment['member'] )
1797                 {
1798                         $author = $comment['member'];
1799                 }
1800                 else
1801                 {
1802                         $author = $comment['user'];
1803                 }
1804                 
1805                 $this->pagehead();
1806                 
1807                 echo '<h2>' . _DELETE_CONFIRM . "</h2>\n";
1808                 echo '<p>' . _CONFIRMTXT_COMMENT . "</p>\n";
1809                 echo "<div class=\"note\">\n";
1810                 echo '<b>' . _EDITC_WHO . ":</b>{$author}<br />\n";
1811                 echo '<b>' . _EDITC_TEXT . ":</b>{$body}\n";
1812                 echo "</div>\n";
1813                 echo "<form method=\"post\" action=\"index.php\">\n";
1814                 echo "<div>\n";
1815                 echo "<input type=\"hidden\" name=\"action\" value=\"commentdeleteconfirm\" />\n";
1816                 echo $manager->addTicketHidden() . "\n";
1817                 echo "<input type=\"hidden\" name=\"commentid\" value=\"{$commentid}\" />\n";
1818                 echo '<input type="submit" tabindex="10" value="'. _DELETE_CONFIRM_BTN . "\" />\n";
1819                 echo "</div>\n";
1820                 echo "</form>\n";
1821                 $this->pagefoot();
1822                 return;
1823         }
1824         
1825     /**
1826      * @todo document this
1827      */
1828     function action_commentdeleteconfirm() {
1829         global $member;
1830
1831         $commentid = intRequestVar('commentid');
1832
1833         // get item id first
1834         $res = DB::getValue('SELECT citem FROM '.sql_table('comment') .' WHERE cnumber=' . $commentid);
1835         $itemid = $res;
1836
1837         $error = $this->deleteOneComment($commentid);
1838         if ($error)
1839             $this->doError($error);
1840
1841         if ($member->canAlterItem($itemid))
1842             $this->action_itemcommentlist($itemid);
1843         else
1844             $this->action_browseowncomments();
1845     }
1846
1847     /**
1848      * @todo document this
1849      */
1850     function deleteOneComment($commentid) {
1851         global $member, $manager;
1852
1853         $commentid = intval($commentid);
1854
1855         if (!$member->canAlterComment($commentid))
1856             return _ERROR_DISALLOWED;
1857
1858         $manager->notify('PreDeleteComment', array('commentid' => $commentid));
1859
1860         // delete the comments associated with the item
1861         $query = 'DELETE FROM '.sql_table('comment').' WHERE cnumber=' . $commentid;
1862         DB::execute($query);
1863
1864         $manager->notify('PostDeleteComment', array('commentid' => $commentid));
1865
1866         return '';
1867     }
1868
1869         /**
1870          * Admin::action_usermanagement()
1871          * 
1872          * Usermanagement main
1873          * @param       void
1874          * @return      void
1875          */
1876         public function action_usermanagement()
1877         {
1878                 global $member, $manager;
1879                 
1880                 // check if allowed
1881                 $member->isAdmin() or $this->disallow();
1882                 
1883                 $this->pagehead();
1884                 
1885                 echo '<p><a href="index.php?action=manage">(' . _BACKTOMANAGE . ")</a></p>\n";
1886                 
1887                 echo '<h2>' . _MEMBERS_TITLE . "</h2>\n";
1888                 
1889                 echo '<h3>' . _MEMBERS_CURRENT . "</h3>\n";
1890                 
1891                 // show list of members with actions
1892                 $query =  'SELECT * FROM '.sql_table('member');
1893                 $template['content'] = 'memberlist';
1894                 $template['tabindex'] = 10;
1895                 
1896                 $manager->loadClass("ENCAPSULATE");
1897                 $batch = new Batch('member');
1898                 $batch->showlist($query,'table',$template);
1899                 
1900                 echo '<h3>' . _MEMBERS_NEW .'</h3>';
1901                 echo "<form method=\"post\" action=\"index.php\" name=\"memberedit\">\n";
1902                 echo "<div>\n";
1903                 echo "<input type=\"hidden\" name=\"action\" value=\"memberadd\" />\n";
1904                 $manager->addTicketHidden();
1905                 
1906                 echo '<table frame="box" rules="rules" summary="' . _MEMBERS_NEW . '">' ."\n";
1907                 echo "<tr>\n";
1908                 echo '<th colspan="2">' . _MEMBERS_NEW . "</th>\n";
1909                 echo "</tr>\n";
1910                 echo "<tr>\n";
1911                 echo '<td>' . _MEMBERS_DISPLAY;
1912                 help('shortnames');
1913                 echo '<br />';
1914                 echo '<small>' . _MEMBERS_DISPLAY_INFO . '</small>';
1915                 echo "</td>\n";
1916                 echo "<td><input tabindex=\"10010\" name=\"name\" size=\"32\" maxlength=\"32\" /></td>\n";
1917                 echo "</tr>\n";
1918                 echo "<tr>\n";
1919                 echo '<td>' . _MEMBERS_REALNAME . "</td>\n";
1920                 echo "<td><input name=\"realname\" tabindex=\"10020\" size=\"40\" maxlength=\"60\" /></td>\n";
1921                 echo "</tr>\n";
1922                 echo "<tr>\n";
1923                 echo '<td>' . _MEMBERS_PWD . "</td>\n";
1924                 echo "<td><input name=\"password\" tabindex=\"10030\" size=\"16\" maxlength=\"40\" type=\"password\" /></td>\n";
1925                 echo "</tr>\n";
1926                 echo "<tr>\n";
1927                 echo '<td>' . _MEMBERS_REPPWD . "</td>\n";
1928                 echo "<td><input name=\"repeatpassword\" tabindex=\"10035\" size=\"16\" maxlength=\"40\" type=\"password\" /></td>\n";
1929                 echo "</tr>\n";
1930                 echo "<tr>\n";
1931                 echo '<td>' . _MEMBERS_EMAIL . "</td>\n";
1932                 echo "<td><input name=\"email\" tabindex=\"10040\" size=\"40\" maxlength=\"60\" /></td>\n";
1933                 echo "</tr>\n";
1934                 echo "<tr>\n";
1935                 echo '<td>' . _MEMBERS_URL . "</td>\n";
1936                 echo "<td><input name=\"url\" tabindex=\"10050\" size=\"40\" maxlength=\"100\" /></td>\n";
1937                 echo "</tr>\n";
1938                 echo "<tr>\n";
1939                 echo '<td>' . _MEMBERS_SUPERADMIN;
1940                 help('superadmin');
1941                 echo "</td>\n";
1942                 echo '<td>';
1943                 $this->input_yesno('admin',0,10060);
1944                 echo "</td>\n";
1945                 echo "</tr>\n";
1946                 echo "<tr>\n";
1947                 echo '<td>' . _MEMBERS_CANLOGIN;
1948                 help('canlogin');
1949                 echo "</td>\n";
1950                 echo '<td>';
1951                 $this->input_yesno('canlogin',1,10070);
1952                 echo "</td>\n";
1953                 echo "</tr>\n";
1954                 echo "<tr>\n";
1955                 echo '<td>' . _MEMBERS_NOTES . "</td>\n";
1956                 echo "<td><input name=\"notes\" maxlength=\"100\" size=\"40\" tabindex=\"10080\" /></td>\n";
1957                 echo "</tr>\n";
1958                 echo "<tr>\n";
1959                 echo '<td>' . _MEMBERS_NEW . "</td>\n";
1960                 echo '<td><input type="submit" value="' . _MEMBERS_NEW_BTN . '" tabindex="10090" onclick="return checkSubmit();" />' . "</td>\n";
1961                 echo "</tr>\n";
1962                 echo "</table>\n";
1963                 echo "</div>\n";
1964                 echo "</form>\n";
1965                 $this->pagefoot();
1966                 return;
1967         }
1968         
1969     /**
1970      * Edit member settings
1971      */
1972     function action_memberedit() {
1973         $this->action_editmembersettings(intRequestVar('memberid'));
1974     }
1975
1976         /**
1977          * @todo document this
1978          */
1979         function action_editmembersettings($memberid = '') {
1980                 global $member, $manager, $CONF;
1981                 
1982                 if ($memberid == '')
1983                 {
1984                         $memberid = $member->getID();
1985                 }
1986                 
1987                 // check if allowed
1988                 ($member->getID() == $memberid) or $member->isAdmin() or $this->disallow();
1989                 
1990                 $extrahead = '<script type="text/javascript" src="javascript/numbercheck.js"></script>';
1991                 $this->pagehead($extrahead);
1992                 
1993                 // show message to go back to member overview (only for admins)
1994                 if ($member->isAdmin())
1995                 {
1996                         echo '<a href="index.php?action=usermanagement">(' ._MEMBERS_BACKTOOVERVIEW. ')</a>';
1997                 }
1998                 else
1999                 {
2000                         echo '<a href="index.php?action=overview">(' ._BACKHOME. ')</a>';
2001                 }
2002                 echo '<h2>' . _MEMBERS_EDIT . '</h2>';
2003                 
2004                 $mem = Member::createFromID($memberid);
2005                 ?>
2006                 <form method="post" action="index.php" name="memberedit"><div>
2007                 
2008                 <input type="hidden" name="action" value="changemembersettings" />
2009                 <input type="hidden" name="memberid" value="<?php echo  $memberid; ?>" />
2010                 <?php $manager->addTicketHidden() ?>
2011                 
2012                 <table><tr>
2013                         <th colspan="2"><?php echo _MEMBERS_EDIT ?></th>
2014                 </tr><tr>
2015                         <td><?php echo _MEMBERS_DISPLAY ?> <?php help('shortnames'); ?>
2016                                 <br /><small><?php echo _MEMBERS_DISPLAY_INFO ?></small>
2017                         </td>
2018                         <td>
2019                         <?php if ($CONF['AllowLoginEdit'] || $member->isAdmin()) { ?>
2020                                 <input name="name" tabindex="10" maxlength="32" size="32" value="<?php echo  Entity::hsc($mem->getDisplayName()); ?>" />
2021                         <?php } else {
2022                                 echo Entity::hsc($member->getDisplayName());
2023                            }
2024                         ?>
2025                         </td>
2026                 </tr><tr>
2027                         <td><?php echo _MEMBERS_REALNAME ?></td>
2028                         <td><input name="realname" tabindex="20" maxlength="60" size="40" value="<?php echo  Entity::hsc($mem->getRealName()); ?>" /></td>
2029                 </tr><tr>
2030                 <?php if ($CONF['AllowLoginEdit'] || $member->isAdmin()) { ?>
2031                         <td><?php echo _MEMBERS_PWD ?></td>
2032                         <td><input type="password" tabindex="30" maxlength="40" size="16" name="password" /></td>
2033                 </tr><tr>
2034                         <td><?php echo _MEMBERS_REPPWD ?></td>
2035                         <td><input type="password" tabindex="35" maxlength="40" size="16" name="repeatpassword" /></td>
2036                 <?php } ?>
2037                 </tr><tr>
2038                         <td><?php echo _MEMBERS_EMAIL ?>
2039                                 <br /><small><?php echo _MEMBERS_EMAIL_EDIT ?></small>
2040                         </td>
2041                         <td><input name="email" tabindex="40" size="40" maxlength="60" value="<?php echo  Entity::hsc($mem->getEmail()); ?>" /></td>
2042                 </tr><tr>
2043                         <td><?php echo _MEMBERS_URL ?></td>
2044                         <td><input name="url" tabindex="50" size="40" maxlength="100" value="<?php echo  Entity::hsc($mem->getURL()); ?>" /></td>
2045                 <?php // only allow to change this by super-admins
2046                    // we don't want normal users to 'upgrade' themselves to super-admins, do we? ;-)
2047                    if ($member->isAdmin()) {
2048                 ?>
2049                         </tr><tr>
2050                                 <td><?php echo _MEMBERS_SUPERADMIN ?> <?php help('superadmin'); ?></td>
2051                                 <td><?php $this->input_yesno('admin',$mem->isAdmin(),60); ?></td>
2052                         </tr><tr>
2053                                 <td><?php echo _MEMBERS_CANLOGIN ?> <?php help('canlogin'); ?></td>
2054                                 <td><?php $this->input_yesno('canlogin',$mem->canLogin(),70,1,0,_YES,_NO,$mem->isAdmin()); ?></td>
2055                 <?php } ?>
2056                 </tr><tr>
2057                         <td><?php echo _MEMBERS_NOTES ?></td>
2058                         <td><input name="notes" tabindex="80" size="40" maxlength="100" value="<?php echo  Entity::hsc($mem->getNotes()); ?>" /></td>
2059                 </tr><tr>
2060                         <td><?php echo _MEMBERS_LOCALE ?> <?php help('locale'); ?>
2061                         </td>
2062                         <td>
2063                         
2064                                 <select name="locale" tabindex="85">
2065                                 <?php
2066                                 $locales = i18n::get_available_locale_list();
2067                                 if ( !$mem->getLocale() || !in_array($mem->getLocale(), $locales) )
2068                                 {
2069                                         echo "<option value=\"\" selected=\"selected\">" . Entity::hsc(_MEMBERS_USESITELANG) . "</option>\n";
2070                                 }
2071                                 else
2072                                 {
2073                                         echo "<option value=\"\">" . Entity::hsc(_MEMBERS_USESITELANG) . "</option>\n";
2074                                 }
2075                                 
2076                                 foreach( $locales as $locale )
2077                                 {
2078                                         if( $locale == $mem->getLocale() )
2079                                         {
2080                                                 echo "<option value=\"{$locale}\" selected=\"selected\">{$locale}</option>\n";
2081                                         }
2082                                         else
2083                                         {
2084                                                 echo "<option value=\"{$locale}\">{$locale}</option>\n";
2085                                         }
2086                                 }
2087                                 ?>
2088                                 </select>
2089                                 
2090                         </td>
2091                 </tr>
2092                 <tr>
2093                         <td><?php echo _MEMBERS_USEAUTOSAVE ?> <?php help('autosave'); ?></td>
2094                         <td><?php $this->input_yesno('autosave', $mem->getAutosave(), 87); ?></td>
2095                 </tr>
2096                 <?php
2097                         // plugin options
2098                         $this->_insertPluginOptions('member',$memberid);
2099                 ?>
2100                 <tr>
2101                         <th colspan="2"><?php echo _MEMBERS_EDIT ?></th>
2102                 </tr><tr>
2103                         <td><?php echo _MEMBERS_EDIT ?></td>
2104                         <td><input type="submit" tabindex="90" value="<?php echo _MEMBERS_EDIT_BTN ?>" onclick="return checkSubmit();" /></td>
2105                 </tr></table>
2106                 
2107                 </div></form>
2108                 
2109                 <?php
2110                         echo '<h3>',_PLUGINS_EXTRA,'</h3>';
2111                         
2112                         $manager->notify(
2113                                 'MemberSettingsFormExtras',
2114                                 array(
2115                                         'member' => &$mem
2116                                 )
2117                         );
2118                 $this->pagefoot();
2119         }
2120         
2121     /**
2122      * @todo document this
2123      */
2124     function action_changemembersettings() {
2125         global $member, $CONF, $manager;
2126
2127         $memberid = intRequestVar('memberid');
2128
2129         // check if allowed
2130         ($member->getID() == $memberid) or $member->isAdmin() or $this->disallow();
2131
2132         $name           = trim(strip_tags(postVar('name')));
2133         $realname       = trim(strip_tags(postVar('realname')));
2134         $password       = postVar('password');
2135         $repeatpassword = postVar('repeatpassword');
2136         $email          = strip_tags(postVar('email'));
2137         $url            = strip_tags(postVar('url'));
2138
2139                 # replaced eregi() below with preg_match(). ereg* functions are deprecated in PHP 5.3.0
2140                 # original eregi: !eregi("^https?://", $url)
2141
2142                 // begin if: sometimes user didn't prefix the URL with http:// or https://, this cause a malformed URL. Let's fix it.
2143                 if (!preg_match('#^https?://#', $url) )
2144                 {
2145                         $url = 'http://' . $url;
2146                 }
2147
2148         $admin          = postVar('admin');
2149         $canlogin       = postVar('canlogin');
2150         $notes          = strip_tags(postVar('notes'));
2151         $locale        = postVar('locale');
2152
2153         $mem = Member::createFromID($memberid);
2154
2155         if ($CONF['AllowLoginEdit'] || $member->isAdmin()) {
2156
2157             if (!isValidDisplayName($name))
2158                 $this->error(_ERROR_BADNAME);
2159
2160             if (($name != $mem->getDisplayName()) && Member::exists($name))
2161                 $this->error(_ERROR_NICKNAMEINUSE);
2162
2163             if ($password != $repeatpassword)
2164                 $this->error(_ERROR_PASSWORDMISMATCH);
2165
2166             if ($password && (i18n::strlen($password) < 6))
2167                 $this->error(_ERROR_PASSWORDTOOSHORT);
2168                 
2169             if ($password) {
2170                                 $pwdvalid = true;
2171                                 $pwderror = '';
2172                                 $manager->notify('PrePasswordSet',array('password' => $password, 'errormessage' => &$pwderror, 'valid' => &$pwdvalid));
2173                                 if (!$pwdvalid) {
2174                                         $this->error($pwderror);
2175                                 }
2176                         }
2177                 }
2178                 
2179                 if ( !NOTIFICATION::address_validation($email) )
2180                 {
2181                         $this->error(_ERROR_BADMAILADDRESS);
2182                 }
2183                 if ( !$realname )
2184                 {
2185                         $this->error(_ERROR_REALNAMEMISSING);
2186                 }
2187         if ( ($locale != '') && (!in_array($locale, i18n::get_available_locale_list())) )
2188             $this->error(_ERROR_NOSUCHTRANSLATION);
2189
2190         // check if there will remain at least one site member with both the logon and admin rights
2191         // (check occurs when taking away one of these rights from such a member)
2192         if (    (!$admin && $mem->isAdmin() && $mem->canLogin())
2193              || (!$canlogin && $mem->isAdmin() && $mem->canLogin())
2194            )
2195         {
2196             $r = DB::getResult('SELECT * FROM '.sql_table('member').' WHERE madmin=1 and mcanlogin=1');
2197             if ($r->rowCount() < 2)
2198                 $this->error(_ERROR_ATLEASTONEADMIN);
2199         }
2200
2201         if ($CONF['AllowLoginEdit'] || $member->isAdmin()) {
2202             $mem->setDisplayName($name);
2203             if ($password)
2204                 $mem->setPassword($password);
2205         }
2206
2207         $oldEmail = $mem->getEmail();
2208
2209         $mem->setRealName($realname);
2210         $mem->setEmail($email);
2211         $mem->setURL($url);
2212         $mem->setNotes($notes);
2213         $mem->setLocale($locale);
2214
2215
2216         // only allow super-admins to make changes to the admin status
2217         if ($member->isAdmin()) {
2218             $mem->setAdmin($admin);
2219             $mem->setCanLogin($canlogin);
2220         }
2221
2222         $autosave = postVar ('autosave');
2223         $mem->setAutosave($autosave);
2224
2225         $mem->write();
2226
2227         // store plugin options
2228         $aOptions = requestArray('plugoption');
2229         NucleusPlugin::apply_plugin_options($aOptions);
2230         $manager->notify('PostPluginOptionsUpdate',array('context' => 'member', 'memberid' => $memberid, 'member' => &$mem));
2231
2232         // if email changed, generate new password
2233         if ($oldEmail != $mem->getEmail())
2234         {
2235             $mem->sendActivationLink('addresschange', $oldEmail);
2236             // logout member
2237             $mem->newCookieKey();
2238
2239             // only log out if the member being edited is the current member.
2240             if ($member->getID() == $memberid)
2241                 $member->logout();
2242             $this->action_login(_MSG_ACTIVATION_SENT, 0);
2243             return;
2244         }
2245
2246
2247         if (  ( $mem->getID() == $member->getID() )
2248            && ( $mem->getDisplayName() != $member->getDisplayName() )
2249            ) {
2250             $mem->newCookieKey();
2251             $member->logout();
2252             $this->action_login(_MSG_LOGINAGAIN, 0);
2253         } else {
2254             $this->action_overview(_MSG_SETTINGSCHANGED);
2255         }
2256     }
2257
2258         /**
2259          * Admin::action_memberadd()
2260          * 
2261          * @param       void
2262          * @return      void
2263          * 
2264         */
2265         function action_memberadd()
2266         {
2267                 global $member, $manager;
2268                 
2269                 // check if allowed
2270                 $member->isAdmin() or $this->disallow();
2271                 
2272                 if ( postVar('password') != postVar('repeatpassword') )
2273                 {
2274                         $this->error(_ERROR_PASSWORDMISMATCH);
2275                 }
2276                 
2277                 if ( i18n::strlen(postVar('password')) < 6 )
2278                 {
2279                         $this->error(_ERROR_PASSWORDTOOSHORT);
2280                 }
2281                 
2282                 $res = Member::create(postVar('name'), postVar('realname'), postVar('password'), postVar('email'), postVar('url'), postVar('admin'), postVar('canlogin'), postVar('notes'));
2283                 if ( $res != 1 )
2284                 {
2285                         $this->error($res);
2286                 }
2287                 
2288                 // fire PostRegister event
2289                 $newmem = new Member();
2290                 $newmem->readFromName(postVar('name'));
2291                 $manager->notify('PostRegister',array('member' => &$newmem));
2292                 
2293                 $this->action_usermanagement();
2294                 return;
2295         }
2296
2297     /**
2298      * Account activation
2299      *
2300      * @author dekarma
2301      */
2302     function action_activate() {
2303
2304         $key = getVar('key');
2305         $this->_showActivationPage($key);
2306     }
2307
2308     /**
2309      * @todo document this
2310      */
2311     function _showActivationPage($key, $message = '')
2312     {
2313         global $manager;
2314
2315         // clean up old activation keys
2316         Member::cleanupActivationTable();
2317
2318         // get activation info
2319         $info = Member::getActivationInfo($key);
2320
2321         if (!$info)
2322             $this->error(_ERROR_ACTIVATE);
2323
2324         $mem = Member::createFromId($info['vmember']);
2325
2326         if (!$mem)
2327             $this->error(_ERROR_ACTIVATE);
2328
2329         $text = '';
2330         $title = '';
2331         $bNeedsPasswordChange = true;
2332
2333         switch ($info['vtype'])
2334         {
2335             case 'forgot':
2336                 $title = _ACTIVATE_FORGOT_TITLE;
2337                 $text = _ACTIVATE_FORGOT_TEXT;
2338                 break;
2339             case 'register':
2340                 $title = _ACTIVATE_REGISTER_TITLE;
2341                 $text = _ACTIVATE_REGISTER_TEXT;
2342                 break;
2343             case 'addresschange':
2344                 $title = _ACTIVATE_CHANGE_TITLE;
2345                 $text = _ACTIVATE_CHANGE_TEXT;
2346                 $bNeedsPasswordChange = false;
2347                 Member::activate($key);
2348                 break;
2349         }
2350
2351         $aVars = array(
2352             'memberName' => Entity::hsc($mem->getDisplayName())
2353         );
2354         $title = Template::fill($title, $aVars);
2355         $text = Template::fill($text, $aVars);
2356
2357         $this->pagehead();
2358
2359             echo '<h2>' , $title, '</h2>';
2360             echo '<p>' , $text, '</p>';
2361
2362             if ($message != '')
2363             {
2364                 echo '<p class="error">',$message,'</p>';
2365             }
2366
2367             if ($bNeedsPasswordChange)
2368             {
2369                 ?>
2370                     <div><form action="index.php" method="post">
2371
2372                         <input type="hidden" name="action" value="activatesetpwd" />
2373                         <?php $manager->addTicketHidden() ?>
2374                         <input type="hidden" name="key" value="<?php echo Entity::hsc($key) ?>" />
2375
2376                         <table><tr>
2377                             <td><?php echo _MEMBERS_PWD ?></td>
2378                             <td><input type="password" maxlength="40" size="16" name="password" /></td>
2379                         </tr><tr>
2380                             <td><?php echo _MEMBERS_REPPWD ?></td>
2381                             <td><input type="password" maxlength="40" size="16" name="repeatpassword" /></td>
2382                         <?php
2383
2384                             global $manager;
2385                             $manager->notify('FormExtra', array('type' => 'activation', 'member' => $mem));
2386
2387                         ?>
2388                         </tr><tr>
2389                             <td><?php echo _MEMBERS_SETPWD ?></td>
2390                             <td><input type='submit' value='<?php echo _MEMBERS_SETPWD_BTN ?>' /></td>
2391                         </tr></table>
2392
2393
2394                     </form></div>
2395
2396                 <?php
2397
2398             }
2399
2400         $this->pagefoot();
2401
2402     }
2403
2404     /**
2405      * Account activation - set password part
2406      *
2407      * @author dekarma
2408      */
2409     function action_activatesetpwd() {
2410
2411         $key = postVar('key');
2412
2413         // clean up old activation keys
2414         Member::cleanupActivationTable();
2415
2416         // get activation info
2417         $info = Member::getActivationInfo($key);
2418
2419         if (!$info || ($info['type'] == 'addresschange'))
2420             return $this->_showActivationPage($key, _ERROR_ACTIVATE);
2421
2422         $mem = Member::createFromId($info['vmember']);
2423
2424         if (!$mem)
2425             return $this->_showActivationPage($key, _ERROR_ACTIVATE);
2426
2427         $password       = postVar('password');
2428         $repeatpassword = postVar('repeatpassword');
2429
2430         if ($password != $repeatpassword)
2431             return $this->_showActivationPage($key, _ERROR_PASSWORDMISMATCH);
2432
2433         if ($password && (i18n::strlen($password) < 6))
2434             return $this->_showActivationPage($key, _ERROR_PASSWORDTOOSHORT);
2435             
2436         if ($password) {
2437                         $pwdvalid = true;
2438                         $pwderror = '';
2439                         global $manager;
2440                         $manager->notify('PrePasswordSet',array('password' => $password, 'errormessage' => &$pwderror, 'valid' => &$pwdvalid));
2441                         if (!$pwdvalid) {
2442                                 return $this->_showActivationPage($key,$pwderror);
2443                         }
2444                 }
2445
2446         $error = '';
2447         
2448         $manager->notify('ValidateForm', array('type' => 'activation', 'member' => $mem, 'error' => &$error));
2449         if ($error != '')
2450             return $this->_showActivationPage($key, $error);
2451
2452
2453         // set password
2454         $mem->setPassword($password);
2455         $mem->write();
2456
2457         // do the activation
2458         Member::activate($key);
2459
2460         $this->pagehead();
2461             echo '<h2>',_ACTIVATE_SUCCESS_TITLE,'</h2>';
2462             echo '<p>',_ACTIVATE_SUCCESS_TEXT,'</p>';
2463         $this->pagefoot();
2464     }
2465
2466         /**
2467          * Admin::action_manageteam()
2468          * 
2469          * Manage team
2470          * @param       void
2471          * @return      void
2472          */
2473         public function action_manageteam()
2474         {
2475                 global $member, $manager;
2476                 
2477                 $blogid = intRequestVar('blogid');
2478                 
2479                 // check if allowed
2480                 $member->blogAdminRights($blogid) or $this->disallow();
2481                 
2482                 $this->pagehead();
2483                 
2484                 echo "<p><a href='index.php?action=blogsettings&amp;blogid=$blogid'>(" . _BACK_TO_BLOGSETTINGS . ")</a></p>\n";
2485                 
2486                 echo '<h2>' . _TEAM_TITLE . getBlogNameFromID($blogid) . "</h2>\n";
2487                 
2488                 echo '<h3>' . _TEAM_CURRENT . "</h3>\n";
2489                 
2490                 $query = 'SELECT tblog, tmember, mname, mrealname, memail, tadmin'
2491                        . ' FROM '.sql_table('member').', '.sql_table('team')
2492                        . ' WHERE tmember=mnumber and tblog=' . $blogid;
2493                 
2494                 $template['content'] = 'teamlist';
2495                 $template['tabindex'] = 10;
2496                 
2497                 $manager->loadClass("ENCAPSULATE");
2498                 $batch = new Batch('team');
2499                 $batch->showlist($query, 'table', $template);
2500                 
2501                 echo '<h3>' . _TEAM_ADDNEW . "</h3>\n";
2502                         
2503                 echo "<form method=\"post\" action=\"index.php\">\n";
2504                 echo "<div>\n";
2505                 
2506                 echo "<input type=\"hidden\" name=\"action\" value=\"teamaddmember\" />\n";
2507                 echo "<input type=\"hidden\" name=\"blogid\" value=\"{$blogid}\" />\n";
2508                 $manager->addTicketHidden();
2509                         
2510                 echo '<table frame="box" rules="all" summary="' . _TEAM_ADDNEW . '">' . "\n";
2511                 echo "<tr>\n";
2512                 echo '<td>' . _TEAM_CHOOSEMEMBER . "</td>\n";
2513                 
2514                 // TODO: try to make it so only non-team-members are listed
2515                 echo "<td>\n";
2516                 
2517                 $query =  'SELECT mname as text, mnumber as value FROM '.sql_table('member');
2518                 $template['name'] = 'memberid';
2519                 $template['tabindex'] = 10000;
2520                 showlist($query,'select',$template);
2521                 
2522                 echo "</td>\n";
2523                 echo "</tr>\n";
2524                 echo "<tr>\n";
2525                 echo '<td>' . _TEAM_ADMIN;
2526                 help('teamadmin');
2527                 echo "</td>\n";
2528                 echo '<td>';
2529                 $this->input_yesno('admin',0,10020);
2530                 echo "</td>\n";
2531                 echo "</tr>\n";
2532                 echo "<tr>\n";
2533                 echo '<td>' . _TEAM_ADD . "</td>\n";
2534                 echo '<td><input type="submit" value="' . _TEAM_ADD_BTN . '" tabindex="10030" />' . "</td>\n";
2535                 echo "</tr>\n";
2536                 echo "</table>\n";
2537                 
2538                 echo "</div>\n";
2539                 echo "</form>\n";
2540                 
2541                 $this->pagefoot();
2542                 return;
2543         }
2544         
2545     /**
2546      * Add member to team
2547      */
2548     function action_teamaddmember() {
2549         global $member, $manager;
2550
2551         $memberid = intPostVar('memberid');
2552         $blogid = intPostVar('blogid');
2553         $admin = intPostVar('admin');
2554
2555         // check if allowed
2556         $member->blogAdminRights($blogid) or $this->disallow();
2557
2558         $blog =& $manager->getBlog($blogid);
2559         if (!$blog->addTeamMember($memberid, $admin))
2560             $this->error(_ERROR_ALREADYONTEAM);
2561
2562         $this->action_manageteam();
2563
2564     }
2565
2566     /**
2567      * @todo document this
2568      */
2569     function action_teamdelete() {
2570         global $member, $manager;
2571
2572         $memberid = intRequestVar('memberid');
2573         $blogid = intRequestVar('blogid');
2574
2575         // check if allowed
2576         $member->blogAdminRights($blogid) or $this->disallow();
2577
2578         $teammem = Member::createFromID($memberid);
2579         $blog =& $manager->getBlog($blogid);
2580
2581         $this->pagehead();
2582         ?>
2583             <h2><?php echo _DELETE_CONFIRM ?></h2>
2584
2585             <p><?php echo _CONFIRMTXT_TEAM1 ?><b><?php echo  Entity::hsc($teammem->getDisplayName()) ?></b><?php echo _CONFIRMTXT_TEAM2 ?><b><?php echo  Entity::hsc(strip_tags($blog->getName())) ?></b>
2586             </p>
2587
2588
2589             <form method="post" action="index.php"><div>
2590             <input type="hidden" name="action" value="teamdeleteconfirm" />
2591             <?php $manager->addTicketHidden() ?>
2592             <input type="hidden" name="memberid" value="<?php echo  $memberid; ?>" />
2593             <input type="hidden" name="blogid" value="<?php echo  $blogid; ?>" />
2594             <input type="submit" tabindex="10" value="<?php echo _DELETE_CONFIRM_BTN ?>" />
2595             </div></form>
2596         <?php
2597         $this->pagefoot();
2598     }
2599
2600     /**
2601      * @todo document this
2602      */
2603     function action_teamdeleteconfirm() {
2604         global $member;
2605
2606         $memberid = intRequestVar('memberid');
2607         $blogid = intRequestVar('blogid');
2608
2609         $error = $this->deleteOneTeamMember($blogid, $memberid);
2610         if ($error)
2611             $this->error($error);
2612
2613
2614         $this->action_manageteam();
2615     }
2616
2617     /**
2618      * @todo document this
2619      */
2620     function deleteOneTeamMember($blogid, $memberid) {
2621         global $member, $manager;
2622
2623         $blogid = intval($blogid);
2624         $memberid = intval($memberid);
2625
2626         // check if allowed
2627         if (!$member->blogAdminRights($blogid))
2628             return _ERROR_DISALLOWED;
2629
2630         // check if: - there remains at least one blog admin
2631         //           - (there remains at least one team member)
2632         $tmem = Member::createFromID($memberid);
2633
2634         $manager->notify('PreDeleteTeamMember', array('member' => &$tmem, 'blogid' => $blogid));
2635
2636         if ($tmem->isBlogAdmin($blogid)) {
2637             // check if there are more blog members left and at least one admin
2638             // (check for at least two admins before deletion)
2639             $query = 'SELECT * FROM '.sql_table('team') . ' WHERE tblog='.$blogid.' and tadmin=1';
2640             $r = DB::getResult($query);
2641             if ($r->rowCount() < 2)
2642                 return _ERROR_ATLEASTONEBLOGADMIN;
2643         }
2644
2645         $query = 'DELETE FROM '.sql_table('team')." WHERE tblog=$blogid and tmember=$memberid";
2646         DB::execute($query);
2647
2648         $manager->notify('PostDeleteTeamMember', array('member' => &$tmem, 'blogid' => $blogid));
2649
2650         return '';
2651     }
2652
2653     /**
2654      * @todo document this
2655      */
2656     function action_teamchangeadmin() {
2657         global $member;
2658
2659         $blogid = intRequestVar('blogid');
2660         $memberid = intRequestVar('memberid');
2661
2662         // check if allowed
2663         $member->blogAdminRights($blogid) or $this->disallow();
2664
2665         $mem = Member::createFromID($memberid);
2666
2667         // don't allow when there is only one admin at this moment
2668         if ($mem->isBlogAdmin($blogid)) {
2669             $r = DB::getResult('SELECT * FROM '.sql_table('team') . " WHERE tblog=$blogid and tadmin=1");
2670             if ($r->rowCount() == 1)
2671                 $this->error(_ERROR_ATLEASTONEBLOGADMIN);
2672         }
2673
2674         if ($mem->isBlogAdmin($blogid))
2675             $newval = 0;
2676         else
2677             $newval = 1;
2678
2679         $query = 'UPDATE '.sql_table('team') ." SET tadmin=$newval WHERE tblog=$blogid and tmember=$memberid";
2680         DB::execute($query);
2681
2682         // only show manageteam if member did not change its own admin privileges
2683         if ($member->isBlogAdmin($blogid))
2684             $this->action_manageteam();
2685         else
2686             $this->action_overview(_MSG_ADMINCHANGED);
2687     }
2688         
2689         /**
2690          * Admin::action_blogsettings()
2691          * 
2692          * @param       void
2693          * @return      void
2694          */
2695         public function action_blogsettings()
2696         {
2697                 global $member, $manager;
2698                 
2699                 $blogid = intRequestVar('blogid');
2700                 
2701                 // check if allowed
2702                 $member->blogAdminRights($blogid) or $this->disallow();
2703                 
2704                 $blog =& $manager->getBlog($blogid);
2705                 
2706                 $extrahead = "<script type=\"text/javascript\" src=\"javascript/numbercheck.js\"></script>\n";
2707                 $this->pagehead($extrahead);
2708                 
2709                 echo '<p><a href="index.php?action=overview">(' . _BACKHOME . ")</a></p>\n";
2710                 echo '<h2>' . _EBLOG_TITLE . ": '{$this->bloglink($blog)}'</h2>\n";
2711                 
2712                 echo '<h3>' . _EBLOG_TEAM_TITLE . "</h3>\n";
2713                 
2714                 echo '<p>' . _EBLOG_CURRENT_TEAM_MEMBER;
2715                 
2716                 $query = "SELECT mname, mrealname FROM %s, %s WHERE mnumber=tmember AND tblog=%d;";
2717                 $query = sprintf($query, sql_table('member'), sql_table('team'), (integer) $blogid);
2718                 $res = DB::getResult($query);
2719                 $aMemberNames = array();
2720                 foreach ( $res as $row )
2721                 {
2722                         $aMemberNames[] = Entity::hsc($row['mname']) . ' (' . Entity::hsc($row['mrealname']). ')';
2723                 }
2724                 echo implode(',', $aMemberNames);
2725                         
2726                 echo "</p>\n";
2727                 echo '<p>';
2728                 echo '<a href="index.php?action=manageteam&amp;blogid=' . $blogid . '">' . _EBLOG_TEAM_TEXT . '</a>';
2729                 echo "</p>\n";
2730                 
2731                 echo '<h3>' . _EBLOG_SETTINGS_TITLE . "</h3>\n";
2732                 
2733                 echo "<form method=\"post\" action=\"index.php\">\n";
2734                 echo "<div>\n";
2735                 
2736                 echo "<input type=\"hidden\" name=\"action\" value=\"blogsettingsupdate\" />\n";
2737                 $manager->addTicketHidden() . "\n";
2738                 echo "<input type=\"hidden\" name=\"blogid\" value=\"{$blogid}\" />\n";
2739                 
2740                 echo '<table frame="box" rules="all" summary="' . _EBLOG_SETTINGS_TITLE . '">' . "\n";
2741                 echo "<tfoot>\n";
2742                 echo "<tr>\n";
2743                 echo '<th colspan="2">' . _EBLOG_CHANGE . "</th>\n";
2744                 echo "</tr>\n";
2745                 echo "<tr>\n";
2746                 echo '<td>' . _EBLOG_CHANGE . "</td>\n";
2747                 echo '<td><input type="submit" tabindex="130" value="' . _EBLOG_CHANGE_BTN . '" onclick="return checkSubmit();" />' . "</td>\n";
2748                 echo "</tr>\n";
2749                 echo "</tfoot>\n";
2750                 echo "<tbody>\n";
2751                 echo "<tr>\n";
2752                 echo '<td>' . _EBLOG_NAME . "</td>\n";
2753                 echo '<td><input name="name" tabindex="10" size="40" maxlength="60" value="' . Entity::hsc($blog->getName()) . '" />' . "</td>\n";
2754                 echo "</tr>\n";
2755                 echo "<tr>\n";
2756                 echo '<td>' . _EBLOG_SHORTNAME;
2757                 help('shortblogname');
2758                 echo _EBLOG_SHORTNAME_EXTRA;
2759                 echo "</td>\n";
2760                 echo '<td><input name="shortname" tabindex="20" maxlength="15" size="15" value="' . Entity::hsc($blog->getShortName()) .'" />' . "</td>\n";
2761                 echo "</tr>\n";
2762                 echo "<tr>\n";
2763                 echo '<td>' . _EBLOG_DESC . "</td>\n";
2764                 echo '<td><input name="desc" tabindex="30" maxlength="200" size="40" value="' . Entity::hsc($blog->getDescription()) . '" />' . "</td>\n";
2765                 echo "</tr>\n";
2766                 echo "<tr>\n";
2767                 echo '<td>' . _EBLOG_URL . "</td>\n";
2768                 echo '<td><input name="url" tabindex="40" size="40" maxlength="100" value="' . Entity::hsc($blog->getURL()) . '" />' . "</td>\n";
2769                 echo "</tr>\n";
2770                 echo "<tr>\n";
2771                 echo '<td>' . _EBLOG_DEFSKIN;
2772                 help('blogdefaultskin');
2773                 echo "</td>\n";
2774                 echo "<td>\n";
2775                 
2776                 $query = 'SELECT sdname as text, sdnumber as value FROM ' . sql_table('skin_desc');
2777                 $template['name'] = 'defskin';
2778                 $template['selected'] = $blog->getDefaultSkin();
2779                 $template['tabindex'] = 50;
2780                 showlist($query, 'select', $template);
2781                 
2782                 echo "</td>\n";
2783                 echo "</tr>\n";
2784                 echo "<tr>\n";
2785                 echo '<td>' . _EBLOG_LINEBREAKS;
2786                 help('convertbreaks');
2787                 echo "</td>\n";
2788                 echo '<td>';
2789                 $this->input_yesno('convertbreaks',$blog->convertBreaks(),55);
2790                 echo "</td>\n";
2791                 echo "</tr>\n";
2792                 
2793                 echo "<tr>\n";
2794                 echo '<td>' . _EBLOG_ALLOWPASTPOSTING;
2795                 help('allowpastposting');
2796                 echo "</td>\n";
2797                 echo '<td>';
2798                 $this->input_yesno('allowpastposting',$blog->allowPastPosting(),57);
2799                 echo "</td>\n";
2800                 echo "</tr>\n";
2801                 echo "<tr>\n";
2802                 echo '<td>' . _EBLOG_DISABLECOMMENTS;
2803                 echo "</td>\n";
2804                 echo '<td>';
2805                 $this->input_yesno('comments', $blog->commentsEnabled(), 60);
2806                 echo "</td>\n";
2807                 echo "</tr>\n";
2808                 echo "<tr>\n";
2809                 echo '<td>' . _EBLOG_ANONYMOUS . "</td>\n";
2810                 echo '<td>';
2811                 $this->input_yesno('public',$blog->isPublic(),70);
2812                 echo "</td>\n";
2813                 echo "</tr>\n";
2814                 echo "<tr>\n";
2815                 echo '<td>' . _EBLOG_REQUIREDEMAIL . "</td>\n";
2816                 echo '<td>';
2817                 $this->input_yesno('reqemail', $blog->emailRequired(),72);
2818                 echo "</td>\n";
2819                 echo "</tr>\n";
2820                 echo "<tr>\n";
2821                 echo '<td>' . _EBLOG_NOTIFY;
2822                 help('blognotify');
2823                 echo "</td>\n";
2824                 echo '<td><input name="notify" tabindex="80" maxlength="128" size="40" value="' . Entity::hsc($blog->getNotifyAddress()) . '" />' . "</td>\n";
2825                 echo "</tr>\n";
2826                 
2827                 echo "<tr>\n";
2828                 echo '<td>' . _EBLOG_NOTIFY_ON . "</td>\n";
2829                 echo "<td>\n";
2830                 
2831                 if ( !$blog->notifyOnComment() )
2832                 {
2833                         echo "<input name=\"notifyComment\" value=\"3\" type=\"checkbox\" tabindex=\"81\" id=\"notifyComment\" />\n";
2834                 }
2835                 else
2836                 {
2837                         echo "<input name=\"notifyComment\" value=\"3\" type=\"checkbox\" tabindex=\"81\" id=\"notifyComment\" checked=\"checked\"/>\n";
2838                 }
2839                 echo '<label for="notifyComment">' . _EBLOG_NOTIFY_COMMENT . "</label><br />\n";
2840                 
2841                 if ( !$blog->notifyOnVote() )
2842                 {
2843                         echo "<input name=\"notifyVote\" value=\"5\" type=\"checkbox\" tabindex=\"82\" id=\"notifyVote\" />\n";
2844                 }
2845                 else
2846                 {
2847                         echo "<input name=\"notifyVote\" value=\"5\" type=\"checkbox\" tabindex=\"82\" id=\"notifyVote\" checked=\"checked\" />\n";
2848                 }
2849                 
2850                 echo '<label for="notifyVote">' . _EBLOG_NOTIFY_KARMA . "</label><br />\n";
2851                 
2852                 if ( !$blog->notifyOnNewItem() )
2853                 {
2854                         echo "<input name=\"notifyNewItem\" value=\"7\" type=\"checkbox\" tabindex=\"83\" id=\"notifyNewItem\" />\n";
2855                 
2856                 }
2857                 else
2858                 {
2859                         echo "<input name=\"notifyNewItem\" value=\"7\" type=\"checkbox\" tabindex=\"83\" id=\"notifyNewItem\" checked=\"checked\" />\n";
2860                 }
2861                 
2862                 echo '<label for="notifyNewItem">' . _EBLOG_NOTIFY_ITEM . "</label>\n";
2863                 
2864                 echo "</td>\n";
2865                 echo "</tr>\n";
2866                 echo "<tr>\n";
2867                 echo '<td>' . _EBLOG_MAXCOMMENTS;
2868                 help('blogmaxcomments');
2869                 echo "</td>\n";
2870                 echo '<td><input name="maxcomments" tabindex="90" size="3" value="' . Entity::hsc($blog->getMaxComments()) . '" />' . "</td>\n";
2871                 echo "</tr>\n";
2872                 echo "<tr>\n";
2873                 echo '<td>' . _EBLOG_UPDATE;
2874                 help('blogupdatefile');
2875                 echo "</td>\n";
2876                 echo '<td><input name="update" tabindex="100" size="40" maxlength="60" value="' . Entity::hsc($blog->getUpdateFile()) .'" />' . "</td>\n";
2877                 echo "</tr>\n";
2878                 echo "<tr>\n";
2879                 echo '<td>' . _EBLOG_DEFCAT . "</td>\n";
2880                 echo "<td>\n";
2881                 $query =  "SELECT cname as text, catid as value FROM %s WHERE cblog=%d;";
2882                 $query = sprintf($query, sql_table('category'), (integer) $blog->getID());
2883                 $template['name'] = 'defcat';
2884                 $template['selected'] = $blog->getDefaultCategory();
2885                 $template['tabindex'] = 110;
2886                 showlist($query, 'select', $template);
2887                 echo "</td>\n";
2888                 echo "</tr>\n";
2889                 echo "<tr>\n";
2890                 echo '<td>' . _EBLOG_OFFSET;
2891                 help('blogtimeoffset');
2892                 echo "<br />\n";
2893                 echo _EBLOG_STIME;
2894                 echo ' <b>' . i18n::formatted_datetime('%H:%M', time()) . '</b><br />';
2895                 echo _EBLOG_BTIME;
2896                 echo '<b>' . i18n::formatted_datetime('%H:%M', $blog->getCorrectTime()) . '</b>';
2897                 echo "</td>\n";
2898                 echo '<td><input name="timeoffset" tabindex="120" size="3" value="' . Entity::hsc($blog->getTimeOffset()) .'" />' . "</td>\n";
2899                 echo "</tr>\n";
2900                 echo "<tr>\n";
2901                 echo '<td>' . _EBLOG_SEARCH;
2902                 help('blogsearchable');
2903                 echo "</td>\n";
2904                 echo '<td>';
2905                 $this->input_yesno('searchable', $blog->getSearchable(), 122);
2906                 echo "</td>\n";
2907                 echo "</tr>\n";
2908                 
2909                 // plugin options
2910                 $this->_insertPluginOptions('blog', $blogid);
2911                 
2912                 echo "</tbody>\n";
2913                 echo "</table>\n";
2914                 
2915                 echo "</div>\n";
2916                 echo "</form>\n";
2917                 
2918                 echo '<h3>' . _EBLOG_CAT_TITLE . "</h3>\n";
2919                 
2920                 $query = 'SELECT * FROM '.sql_table('category').' WHERE cblog='.$blog->getID().' ORDER BY cname';
2921                 $template['content'] = 'categorylist';
2922                 $template['tabindex'] = 200;
2923                 
2924                 $manager->loadClass("ENCAPSULATE");
2925                 $batch = new Batch('category');
2926                 $batch->showlist($query,'table',$template);
2927                 
2928                 echo "<form action=\"index.php\" method=\"post\">\n";
2929                 echo "<div>\n";
2930                 echo "<input name=\"action\" value=\"categorynew\" type=\"hidden\" />\n";
2931                 $manager->addTicketHidden() . "\n";
2932                 echo "<input name=\"blogid\" value=\"{$blog->getID()}\" type=\"hidden\" />\n";
2933                 
2934                 echo '<table frame="box" rules="all" summary="' . _EBLOG_CAT_CREATE . '">' . "\n";
2935                 echo "<thead>\n";
2936                 echo "<tr>\n";
2937                 echo '<th colspan="2">' . _EBLOG_CAT_CREATE . "</th>\n";
2938                 echo "</tr>\n";
2939                 echo "</thead>\n";
2940                 echo "<tbody>\n";
2941                 echo "<tr>\n";
2942                 echo '<td>' . _EBLOG_CAT_NAME . "</td>\n";
2943                 echo "<td><input name=\"cname\" size=\"40\" maxlength=\"40\" tabindex=\"300\" /></td>\n";
2944                 echo "</tr>\n";
2945                 echo "<tr>\n";
2946                 echo '<td>' . _EBLOG_CAT_DESC . "</td>\n";
2947                 echo "<td><input name=\"cdesc\" size=\"40\" maxlength=\"200\" tabindex=\"310\" /></td>\n";
2948                 echo "</tr>\n";
2949                 echo "<tr>\n";
2950                 echo '<td>' . _EBLOG_CAT_CREATE . "</td>\n";
2951                 echo '<td><input type="submit" value="' . _EBLOG_CAT_CREATE . '" tabindex="320" />' . "</td>\n";
2952                 echo "</tr>\n";
2953                 echo "</tbody>\n";
2954                 echo "</table>\n";
2955                 echo "</div>\n";
2956                 echo "</form>\n";
2957                 
2958                 echo '<h3>' . _PLUGINS_EXTRA . "</h3>\n";
2959                 $manager->notify('BlogSettingsFormExtras', array('blog' => &$blog));
2960                 
2961                 $this->pagefoot();
2962                 return;
2963         }
2964
2965     /**
2966      * @todo document this
2967      */
2968     function action_categorynew() {
2969         global $member, $manager;
2970
2971         $blogid = intRequestVar('blogid');
2972
2973         $member->blogAdminRights($blogid) or $this->disallow();
2974
2975         $cname = postVar('cname');
2976         $cdesc = postVar('cdesc');
2977
2978         if (!isValidCategoryName($cname))
2979             $this->error(_ERROR_BADCATEGORYNAME);
2980
2981         $query = 'SELECT * FROM '.sql_table('category') . ' WHERE cname=' . DB::quoteValue($cname).' and cblog=' . intval($blogid);
2982         $res = DB::getResult($query);
2983         if ($res->rowCount() > 0)
2984             $this->error(_ERROR_DUPCATEGORYNAME);
2985
2986         $blog       =& $manager->getBlog($blogid);
2987         $newCatID   =  $blog->createNewCategory($cname, $cdesc);
2988
2989         $this->action_blogsettings();
2990     }
2991
2992     /**
2993      * @todo document this
2994      */
2995     function action_categoryedit($catid = '', $blogid = '', $desturl = '') {
2996         global $member, $manager;
2997
2998         if ($blogid == '')
2999             $blogid = intGetVar('blogid');
3000         else
3001             $blogid = intval($blogid);
3002         if ($catid == '')
3003             $catid = intGetVar('catid');
3004         else
3005             $catid = intval($catid);
3006
3007         $member->blogAdminRights($blogid) or $this->disallow();
3008
3009         $res = DB::getRow('SELECT * FROM '.sql_table('category')." WHERE cblog=$blogid AND catid=$catid");
3010
3011         $cname = $res['cname'];
3012         $cdesc = $res['cdesc'];
3013
3014         $extrahead = '<script type="text/javascript" src="javascript/numbercheck.js"></script>';
3015         $this->pagehead($extrahead);
3016
3017         echo "<p><a href='index.php?action=blogsettings&amp;blogid=$blogid'>(",_BACK_TO_BLOGSETTINGS,")</a></p>";
3018
3019         ?>
3020         <h2><?php echo _EBLOG_CAT_UPDATE ?> '<?php echo Entity::hsc($cname) ?>'</h2>
3021         <form method='post' action='index.php'><div>
3022         <input name="blogid" type="hidden" value="<?php echo $blogid ?>" />
3023         <input name="catid" type="hidden" value="<?php echo $catid ?>" />
3024         <input name="desturl" type="hidden" value="<?php echo Entity::hsc($desturl) ?>" />
3025         <input name="action" type="hidden" value="categoryupdate" />
3026         <?php $manager->addTicketHidden(); ?>
3027
3028         <table><tr>
3029             <th colspan="2"><?php echo _EBLOG_CAT_UPDATE ?></th>
3030         </tr><tr>
3031             <td><?php echo _EBLOG_CAT_NAME ?></td>
3032             <td><input type="text" name="cname" value="<?php echo Entity::hsc($cname) ?>" size="40" maxlength="40" /></td>
3033         </tr><tr>
3034             <td><?php echo _EBLOG_CAT_DESC ?></td>
3035             <td><input type="text" name="cdesc" value="<?php echo Entity::hsc($cdesc) ?>" size="40" maxlength="200" /></td>
3036         </tr>
3037         <?php
3038             // insert plugin options
3039             $this->_insertPluginOptions('category',$catid);
3040         ?>
3041         <tr>
3042             <th colspan="2"><?php echo _EBLOG_CAT_UPDATE ?></th>
3043         </tr><tr>
3044             <td><?php echo _EBLOG_CAT_UPDATE ?></td>
3045             <td><input type="submit" value="<?php echo _EBLOG_CAT_UPDATE_BTN ?>" /></td>
3046         </tr></table>
3047
3048         </div></form>
3049         <?php
3050         $this->pagefoot();
3051     }
3052
3053     /**
3054      * @todo document this
3055      */
3056     function action_categoryupdate() {
3057         global $member, $manager;
3058
3059         $blogid = intPostVar('blogid');
3060         $catid = intPostVar('catid');
3061         $cname = postVar('cname');
3062         $cdesc = postVar('cdesc');
3063         $desturl = postVar('desturl');
3064
3065         $member->blogAdminRights($blogid) or $this->disallow();
3066
3067         if (!isValidCategoryName($cname))
3068             $this->error(_ERROR_BADCATEGORYNAME);
3069
3070         $query = 'SELECT * FROM '.sql_table('category').' WHERE cname=' . DB::quoteValue($cname).' and cblog=' . intval($blogid) . " and not(catid=$catid)";
3071         $res = DB::getResult($query);
3072         if ($res->rowCount() > 0)
3073             $this->error(_ERROR_DUPCATEGORYNAME);
3074
3075         $query =  'UPDATE '.sql_table('category').' SET'
3076                . ' cname=' . DB::quoteValue($cname) . ','
3077                . ' cdesc=' . DB::quoteValue($cdesc)
3078                . ' WHERE catid=' . $catid;
3079
3080         DB::execute($query);
3081
3082         // store plugin options
3083         $aOptions = requestArray('plugoption');
3084         NucleusPlugin::apply_plugin_options($aOptions);
3085         $manager->notify('PostPluginOptionsUpdate',array('context' => 'category', 'catid' => $catid));
3086
3087
3088         if ($desturl) {
3089             redirect($desturl);
3090             exit;
3091         } else {
3092             $this->action_blogsettings();
3093         }
3094     }
3095
3096     /**
3097      * @todo document this
3098      */
3099     function action_categorydelete() {
3100         global $member, $manager;
3101
3102         $blogid = intRequestVar('blogid');
3103         $catid = intRequestVar('catid');
3104
3105         $member->blogAdminRights($blogid) or $this->disallow();
3106
3107         $blog =& $manager->getBlog($blogid);
3108
3109         // check if the category is valid
3110         if (!$blog->isValidCategory($catid))
3111             $this->error(_ERROR_NOSUCHCATEGORY);
3112
3113         // don't allow deletion of default category
3114         if ($blog->getDefaultCategory() == $catid)
3115             $this->error(_ERROR_DELETEDEFCATEGORY);
3116
3117         // check if catid is the only category left for blogid
3118         $query = 'SELECT catid FROM '.sql_table('category').' WHERE cblog=' . $blogid;
3119         $res = DB::getResult($query);
3120         if ($res->rowCount() == 1)
3121             $this->error(_ERROR_DELETELASTCATEGORY);
3122
3123
3124         $this->pagehead();
3125         ?>
3126             <h2><?php echo _DELETE_CONFIRM ?></h2>
3127
3128             <div>
3129             <?php echo _CONFIRMTXT_CATEGORY ?><b><?php echo  Entity::hsc($blog->getCategoryName($catid)) ?></b>
3130             </div>
3131
3132             <form method="post" action="index.php"><div>
3133             <input type="hidden" name="action" value="categorydeleteconfirm" />
3134             <?php $manager->addTicketHidden() ?>
3135             <input type="hidden" name="blogid" value="<?php echo $blogid ?>" />
3136             <input type="hidden" name="catid" value="<?php echo $catid ?>" />
3137             <input type="submit" tabindex="10" value="<?php echo _DELETE_CONFIRM_BTN ?>" />
3138             </div></form>
3139         <?php
3140         $this->pagefoot();
3141     }
3142
3143     /**
3144      * @todo document this
3145      */
3146     function action_categorydeleteconfirm() {
3147         global $member, $manager;
3148
3149         $blogid = intRequestVar('blogid');
3150         $catid = intRequestVar('catid');
3151
3152         $member->blogAdminRights($blogid) or $this->disallow();
3153
3154         $error = $this->deleteOneCategory($catid);
3155         if ($error)
3156             $this->error($error);
3157
3158         $this->action_blogsettings();
3159     }
3160         
3161         /**
3162          * Admin::deleteOneCategory()
3163          * Delete a category by its id
3164          * 
3165          * @param       String  $catid  category id for deleting
3166          * @return      Void
3167          */
3168         function deleteOneCategory($catid)
3169         {
3170                 global $manager, $member;
3171                 
3172                 $catid = intval($catid);
3173                 $blogid = getBlogIDFromCatID($catid);
3174                 
3175                 if ( !$member->blogAdminRights($blogid) )
3176                 {
3177                         return ERROR_DISALLOWED;
3178                 }
3179                 
3180                 // get blog
3181                 $blog =& $manager->getBlog($blogid);
3182                 
3183                 // check if the category is valid
3184                 if ( !$blog || !$blog->isValidCategory($catid) )
3185                 {
3186                         return _ERROR_NOSUCHCATEGORY;
3187                 }
3188                 
3189                 $destcatid = $blog->getDefaultCategory();
3190                 
3191                 // don't allow deletion of default category
3192                 if ( $blog->getDefaultCategory() == $catid )
3193                 {
3194                         return _ERROR_DELETEDEFCATEGORY;
3195                 }
3196                 
3197                 // check if catid is the only category left for blogid
3198                 $query = 'SELECT catid FROM '.sql_table('category').' WHERE cblog=' . $blogid;
3199                 $res = DB::getResult($query);
3200                 if ( $res->rowCount() == 1 )
3201                 {
3202                         return _ERROR_DELETELASTCATEGORY;
3203                 }
3204                 
3205                 $manager->notify('PreDeleteCategory', array('catid' => $catid));
3206                 
3207                 // change category for all items to the default category
3208                 $query = 'UPDATE '.sql_table('item')." SET icat=$destcatid WHERE icat=$catid";
3209                 DB::execute($query);
3210                 
3211                 // delete all associated plugin options
3212                 NucleusPlugin::delete_option_values('category', $catid);
3213                 
3214                 // delete category
3215                 $query = 'DELETE FROM '.sql_table('category').' WHERE catid=' .$catid;
3216                 DB::execute($query);
3217                 
3218                 $manager->notify('PostDeleteCategory', array('catid' => $catid));
3219                 return;
3220         }
3221         
3222         /**
3223          * Admin::action_blogsettingsupdate
3224          * Updating blog settings
3225          * 
3226          * @param       Void
3227          * @return      Void
3228          */
3229         function action_blogsettingsupdate()
3230         {
3231                 global $member, $manager;
3232                 
3233                 $blogid = intRequestVar('blogid');
3234                 
3235                 $member->blogAdminRights($blogid) or $this->disallow();
3236                 
3237                 $blog =& $manager->getBlog($blogid);
3238                 
3239                 $notify_address = trim(postVar('notify'));
3240                 $shortname              = trim(postVar('shortname'));
3241                 $updatefile     = trim(postVar('update'));
3242                 
3243                 $notifyComment  = intPostVar('notifyComment');
3244                 $notifyVote             = intPostVar('notifyVote');
3245                 $notifyNewItem  = intPostVar('notifyNewItem');
3246                 
3247                 if ( $notifyComment == 0 )
3248                 {
3249                         $notifyComment = 1;
3250                 }
3251                 if ( $notifyVote == 0 )
3252                 {
3253                         $notifyVote = 1;
3254                 }
3255                 if ( $notifyNewItem == 0 )
3256                 {
3257                         $notifyNewItem = 1;
3258                 }
3259                 $notifyType = $notifyComment * $notifyVote * $notifyNewItem;
3260                 
3261                 if ( $notify_address && !NOTIFICATION::address_validation($notify_address) )
3262                 {
3263                         $this->error(_ERROR_BADNOTIFY);
3264                 }
3265                 
3266                 if ( !isValidShortName($shortname) )
3267                 {
3268                         $this->error(_ERROR_BADSHORTBLOGNAME);
3269                 }
3270                 
3271                 if ( ($blog->getShortName() != $shortname) && $manager->existsBlog($shortname) )
3272                 {
3273                         $this->error(_ERROR_DUPSHORTBLOGNAME);
3274                 }
3275                 // check if update file is writable
3276                 if ( $updatefile && !is_writeable($updatefile) )
3277                 {
3278                         $this->error(_ERROR_UPDATEFILE);
3279                 }
3280                 
3281                 $blog->setName(trim(postVar('name')));
3282                 $blog->setShortName($shortname);
3283                 $blog->setNotifyAddress($notify_address);
3284                 $blog->setNotifyType($notifyType);
3285                 $blog->setMaxComments(postVar('maxcomments'));
3286                 $blog->setCommentsEnabled(postVar('comments'));
3287                 $blog->setTimeOffset(postVar('timeoffset'));
3288                 $blog->setUpdateFile($updatefile);
3289                 $blog->setURL(trim(postVar('url')));
3290                 $blog->setDefaultSkin(intPostVar('defskin'));
3291                 $blog->setDescription(trim(postVar('desc')));
3292                 $blog->setPublic(postVar('public'));
3293                 $blog->setConvertBreaks(intPostVar('convertbreaks'));
3294                 $blog->setAllowPastPosting(intPostVar('allowpastposting'));
3295                 $blog->setDefaultCategory(intPostVar('defcat'));
3296                 $blog->setSearchable(intPostVar('searchable'));
3297                 $blog->setEmailRequired(intPostVar('reqemail'));
3298                 $blog->writeSettings();
3299                 
3300                 // store plugin options
3301                 $aOptions = requestArray('plugoption');
3302                 NucleusPlugin::apply_plugin_options($aOptions);
3303                 $manager->notify('PostPluginOptionsUpdate',array('context' => 'blog', 'blogid' => $blogid, 'blog' => &$blog));
3304                 
3305                 $this->action_overview(_MSG_SETTINGSCHANGED);
3306                 return;
3307         }
3308
3309     /**
3310      * @todo document this
3311      */
3312     function action_deleteblog() {
3313         global $member, $CONF, $manager;
3314
3315         $blogid = intRequestVar('blogid');
3316
3317         $member->blogAdminRights($blogid) or $this->disallow();
3318
3319         // check if blog is default blog
3320         if ($CONF['DefaultBlog'] == $blogid)
3321             $this->error(_ERROR_DELDEFBLOG);
3322
3323         $blog =& $manager->getBlog($blogid);
3324
3325         $this->pagehead();
3326         ?>
3327             <h2><?php echo _DELETE_CONFIRM ?></h2>
3328
3329             <p><?php echo _WARNINGTXT_BLOGDEL ?>
3330             </p>
3331
3332             <div>
3333             <?php echo _CONFIRMTXT_BLOG ?><b><?php echo  Entity::hsc($blog->getName()) ?></b>
3334             </div>
3335
3336             <form method="post" action="index.php"><div>
3337             <input type="hidden" name="action" value="deleteblogconfirm" />
3338             <?php $manager->addTicketHidden() ?>
3339             <input type="hidden" name="blogid" value="<?php echo  $blogid; ?>" />
3340             <input type="submit" tabindex="10" value="<?php echo _DELETE_CONFIRM_BTN ?>" />
3341             </div></form>
3342         <?php
3343         $this->pagefoot();
3344     }
3345         
3346         /**
3347          * Admin::action_deleteblogconfirm()
3348          * Delete Blog
3349          * 
3350          * @param       Void
3351          * @return      Void
3352          */
3353         function action_deleteblogconfirm()
3354         {
3355                 global $member, $CONF, $manager;
3356                 
3357                 $blogid = intRequestVar('blogid');
3358                 $manager->notify('PreDeleteBlog', array('blogid' => $blogid));
3359                 $member->blogAdminRights($blogid) or $this->disallow();
3360                 
3361                 // check if blog is default blog
3362                 if ( $CONF['DefaultBlog'] == $blogid )
3363                 {
3364                         $this->error(_ERROR_DELDEFBLOG);
3365                 }
3366                 
3367                 // delete all comments
3368                 $query = 'DELETE FROM '.sql_table('comment').' WHERE cblog='.$blogid;
3369                 DB::execute($query);
3370                 
3371                 // delete all items
3372                 $query = 'DELETE FROM '.sql_table('item').' WHERE iblog='.$blogid;
3373                 DB::execute($query);
3374                 
3375                 // delete all team members
3376                 $query = 'DELETE FROM '.sql_table('team').' WHERE tblog='.$blogid;
3377                 DB::execute($query);
3378                 
3379                 // delete all bans
3380                 $query = 'DELETE FROM '.sql_table('ban').' WHERE blogid='.$blogid;
3381                 DB::execute($query);
3382                 
3383                 // delete all categories
3384                 $query = 'DELETE FROM '.sql_table('category').' WHERE cblog='.$blogid;
3385                 DB::execute($query);
3386                 
3387                 // delete all associated plugin options
3388                 NucleusPlugin::delete_option_values('blog', $blogid);
3389                 
3390                 // delete the blog itself
3391                 $query = 'DELETE FROM '.sql_table('blog').' WHERE bnumber='.$blogid;
3392                 DB::execute($query);
3393                 
3394                 $manager->notify('PostDeleteBlog', array('blogid' => $blogid));
3395                 
3396                 $this->action_overview(_DELETED_BLOG);
3397                 return;
3398         }
3399         
3400     /**
3401      * @todo document this
3402      */
3403     function action_memberdelete() {
3404         global $member, $manager;
3405
3406         $memberid = intRequestVar('memberid');
3407
3408         ($member->getID() == $memberid) or $member->isAdmin() or $this->disallow();
3409
3410         $mem = Member::createFromID($memberid);
3411
3412         $this->pagehead();
3413         ?>
3414             <h2><?php echo _DELETE_CONFIRM ?></h2>
3415
3416             <p><?php echo _CONFIRMTXT_MEMBER ?><b><?php echo Entity::hsc($mem->getDisplayName()) ?></b>
3417             </p>
3418
3419             <p>
3420             <?php echo _WARNINGTXT_NOTDELMEDIAFILES ?>
3421             </p>
3422
3423             <form method="post" action="index.php"><div>
3424             <input type="hidden" name="action" value="memberdeleteconfirm" />
3425             <?php $manager->addTicketHidden() ?>
3426             <input type="hidden" name="memberid" value="<?php echo  $memberid; ?>" />
3427             <input type="submit" tabindex="10" value="<?php echo _DELETE_CONFIRM_BTN ?>" />
3428             </div></form>
3429         <?php
3430         $this->pagefoot();
3431     }
3432
3433     /**
3434      * @todo document this
3435      */
3436     function action_memberdeleteconfirm() {
3437         global $member;
3438
3439         $memberid = intRequestVar('memberid');
3440
3441         ($member->getID() == $memberid) or $member->isAdmin() or $this->disallow();
3442
3443         $error = $this->deleteOneMember($memberid);
3444         if ($error)
3445             $this->error($error);
3446
3447         if ($member->isAdmin())
3448             $this->action_usermanagement();
3449         else
3450             $this->action_overview(_DELETED_MEMBER);
3451     }
3452         
3453         /**
3454          * Admin::deleteOneMember()
3455          * Delete a member by id
3456          * 
3457          * @static
3458          * @params      Integer $memberid       member id
3459          * @return      String  null string or error messages
3460          */
3461         function deleteOneMember($memberid)
3462         {
3463                 global $manager;
3464                 
3465                 $memberid = intval($memberid);
3466                 $mem = Member::createFromID($memberid);
3467                 
3468                 if ( !$mem->canBeDeleted() )
3469                 {
3470                         return _ERROR_DELETEMEMBER;
3471                 }
3472                 
3473                 $manager->notify('PreDeleteMember', array('member' => &$mem));
3474                 
3475                 /* unlink comments from memberid */
3476                 if ( $memberid )
3477                 {
3478                         $query = "UPDATE %s SET cmember=0, cuser=%s WHERE cmember=%d";
3479                         $query = sprintf($query, sql_table('comment'), DB::quoteValue($mem->getDisplayName()), $memberid);
3480                         DB::execute($query);
3481                 }
3482                 
3483                 $query = 'DELETE FROM '.sql_table('member').' WHERE mnumber='.$memberid;
3484                 DB::execute($query);
3485                 
3486                 $query = 'DELETE FROM '.sql_table('team').' WHERE tmember='.$memberid;
3487                 DB::execute($query);
3488                 
3489                 $query = 'DELETE FROM '.sql_table('activation').' WHERE vmember='.$memberid;
3490                 DB::execute($query);
3491                 
3492                 // delete all associated plugin options
3493                 NucleusPlugin::delete_option_values('member', $memberid);
3494                 
3495                 $manager->notify('PostDeleteMember', array('member' => &$mem));
3496                 
3497                 return '';
3498         }
3499         
3500     /**
3501      * @todo document this
3502      */
3503     function action_createnewlog() {
3504         global $member, $CONF, $manager;
3505
3506         // Only Super-Admins can do this
3507         $member->isAdmin() or $this->disallow();
3508
3509         $this->pagehead();
3510
3511         echo '<p><a href="index.php?action=manage">(',_BACKTOMANAGE,')</a></p>';
3512         ?>
3513         <h2><?php echo _EBLOG_CREATE_TITLE ?></h2>
3514
3515         <h3><?php echo _ADMIN_NOTABILIA ?></h3>
3516
3517         <p><?php echo _ADMIN_PLEASE_READ ?></p>
3518
3519         <p><?php echo _ADMIN_HOW_TO_ACCESS ?></p>
3520
3521         <ol>
3522             <li><?php echo _ADMIN_SIMPLE_WAY ?></li>
3523             <li><?php echo _ADMIN_ADVANCED_WAY ?></li>
3524         </ol>
3525
3526         <h3><?php echo _ADMIN_HOW_TO_CREATE ?></h3>
3527
3528         <p>
3529         <?php echo _EBLOG_CREATE_TEXT ?>
3530         </p>
3531
3532         <form method="post" action="index.php"><div>
3533
3534         <input type="hidden" name="action" value="addnewlog" />
3535         <?php $manager->addTicketHidden() ?>
3536
3537
3538         <table><tr>
3539             <td><?php echo _EBLOG_NAME ?></td>
3540             <td><input name="name" tabindex="10" size="40" maxlength="60" /></td>
3541         </tr><tr>
3542             <td><?php echo _EBLOG_SHORTNAME ?>
3543                 <?php help('shortblogname'); ?>
3544             </td>
3545             <td><input name="shortname" tabindex="20" maxlength="15" size="15" /></td>
3546         </tr><tr>
3547             <td><?php echo _EBLOG_DESC ?></td>
3548             <td><input name="desc" tabindex="30" maxlength="200" size="40" /></td>
3549         </tr><tr>
3550             <td><?php echo _EBLOG_DEFSKIN ?>
3551                 <?php help('blogdefaultskin'); ?>
3552             </td>
3553             <td>
3554                 <?php
3555                     $query =  'SELECT sdname as text, sdnumber as value'
3556                            . ' FROM '.sql_table('skin_desc');
3557                     $template['name'] = 'defskin';
3558                     $template['tabindex'] = 50;
3559                     $template['selected'] = $CONF['BaseSkin'];  // set default selected skin to be globally defined base skin
3560                     showlist($query,'select',$template);
3561                 ?>
3562             </td>
3563         </tr><tr>
3564             <td><?php echo _EBLOG_OFFSET ?>
3565                 <?php help('blogtimeoffset'); ?>
3566                 <br /><?php echo _EBLOG_STIME ?> <b><?php echo i18n::formatted_datetime('%H:%M',time()); ?></b>
3567             </td>
3568             <td><input name="timeoffset" tabindex="110" size="3" value="0" /></td>
3569         </tr><tr>
3570             <td><?php echo _EBLOG_ADMIN ?>
3571                 <?php help('teamadmin'); ?>
3572             </td>
3573             <td><?php echo _EBLOG_ADMIN_MSG ?></td>
3574         </tr><tr>
3575             <td><?php echo _EBLOG_CREATE ?></td>
3576             <td><input type="submit" tabindex="120" value="<?php echo _EBLOG_CREATE_BTN ?>" onclick="return checkSubmit();" /></td>
3577         </tr></table>
3578
3579         </div></form>
3580         <?php
3581         $this->pagefoot();
3582     }
3583
3584     /**
3585      * @todo document this
3586      */
3587     function action_addnewlog() {
3588         global $member, $manager, $CONF;
3589
3590         // Only Super-Admins can do this
3591         $member->isAdmin() or $this->disallow();
3592
3593         $bname          = trim(postVar('name'));
3594         $bshortname     = trim(postVar('shortname'));
3595         $btimeoffset    = postVar('timeoffset');
3596         $bdesc          = trim(postVar('desc'));
3597         $bdefskin       = postVar('defskin');
3598
3599         if (!isValidShortName($bshortname))
3600             $this->error(_ERROR_BADSHORTBLOGNAME);
3601
3602         if ($manager->existsBlog($bshortname))
3603             $this->error(_ERROR_DUPSHORTBLOGNAME);
3604
3605         $manager->notify(
3606             'PreAddBlog',
3607             array(
3608                 'name' => &$bname,
3609                 'shortname' => &$bshortname,
3610                 'timeoffset' => &$btimeoffset,
3611                 'description' => &$bdesc,
3612                 'defaultskin' => &$bdefskin
3613             )
3614         );
3615
3616
3617         // create blog
3618                 $query = sprintf('INSERT INTO %s (bname, bshortname, bdesc, btimeoffset, bdefskin) VALUES (%s, %s, %s, %s, %s)',
3619                         sql_table('blog'),
3620                         DB::quoteValue($bname),
3621                         DB::quoteValue($bshortname),
3622                         DB::quoteValue($bdesc),
3623                         DB::quoteValue($btimeoffset),
3624                         DB::quoteValue($bdefskin)
3625                 );
3626         DB::execute($query);
3627         $blogid = DB::getInsertId();
3628         $blog   =& $manager->getBlog($blogid);
3629
3630         // create new category
3631         $catdefname = (defined('_EBLOGDEFAULTCATEGORY_NAME') ? _EBLOGDEFAULTCATEGORY_NAME : 'General');
3632         $catdefdesc = (defined('_EBLOGDEFAULTCATEGORY_DESC') ? _EBLOGDEFAULTCATEGORY_DESC : 'Items that do not fit in other categories');
3633                 $query = sprintf('INSERT INTO %s (cblog, cname, cdesc) VALUES (%d, %s, %s)',
3634                         sql_table('category'),
3635                         $blogid,
3636                         DB::quoteValue($catdefname),
3637                         DB::quoteValue($catdefdesc)
3638                 );
3639         DB::execute($query);
3640         $catid = DB::getInsertId();
3641
3642         // set as default category
3643         $blog->setDefaultCategory($catid);
3644         $blog->writeSettings();
3645
3646         // create team member
3647         $memberid = $member->getID();
3648         $query = sprintf('INSERT INTO %s (tmember, tblog, tadmin) VALUES (%d, %d, 1)', sql_table('team'), $memberid, $blogid);
3649         DB::execute($query);
3650
3651         $itemdeftitle = (defined('_EBLOG_FIRSTITEM_TITLE') ? _EBLOG_FIRSTITEM_TITLE : 'First Item');
3652         $itemdefbody = (defined('_EBLOG_FIRSTITEM_BODY') ? _EBLOG_FIRSTITEM_BODY : 'This is the first item in your weblog. Feel free to delete it.');
3653
3654         $blog->additem($blog->getDefaultCategory(),$itemdeftitle,$itemdefbody,'',$blogid, $memberid,$blog->getCorrectTime(),0,0,0);
3655
3656         
3657         $manager->notify(
3658             'PostAddBlog',
3659             array(
3660                 'blog' => &$blog
3661             )
3662         );
3663
3664         $manager->notify(
3665             'PostAddCategory',
3666             array(
3667                 'blog' => &$blog,
3668                 'name' => _EBLOGDEFAULTCATEGORY_NAME,
3669                 'description' => _EBLOGDEFAULTCATEGORY_DESC,
3670                 'catid' => $catid
3671             )
3672         );
3673
3674         $this->pagehead();
3675         ?>
3676         <h2><?php echo _BLOGCREATED_TITLE ?></h2>
3677
3678         <p><?php echo sprintf(_BLOGCREATED_ADDEDTXT, Entity::hsc($bname)) ?></p>
3679
3680         <ol>
3681             <li><a href="#index_php"><?php echo sprintf(_BLOGCREATED_SIMPLEWAY, Entity::hsc($bshortname)) ?></a></li>
3682             <li><a href="#skins"><?php echo _BLOGCREATED_ADVANCEDWAY ?></a></li>
3683         </ol>
3684
3685         <h3><a id="index_php"><?php echo sprintf(_BLOGCREATED_SIMPLEDESC1, Entity::hsc($bshortname)) ?></a></h3>
3686
3687         <p><?php echo sprintf(_BLOGCREATED_SIMPLEDESC2, Entity::hsc($bshortname)) ?></p>
3688 <pre><code>&lt;?php
3689
3690 $CONF['Self'] = '<b><?php echo Entity::hsc($bshortname) ?>.php</b>';
3691
3692 include('<i>./config.php</i>');
3693
3694 selectBlog('<b><?php echo Entity::hsc($bshortname) ?></b>');
3695 selector();
3696
3697 ?&gt;</code></pre>
3698
3699         <p><?php echo _BLOGCREATED_SIMPLEDESC3 ?></p>
3700
3701         <p><?php echo _BLOGCREATED_SIMPLEDESC4 ?></p>
3702
3703         <form action="index.php" method="post"><div>
3704             <input type="hidden" name="action" value="addnewlog2" />
3705             <?php $manager->addTicketHidden() ?>
3706             <input type="hidden" name="blogid" value="<?php echo intval($blogid) ?>" />
3707             <table><tr>
3708                 <td><?php echo _EBLOG_URL ?></td>
3709                 <td><input name="url" maxlength="100" size="40" value="<?php echo Entity::hsc($CONF['IndexURL'].$bshortname.'.php') ?>" /></td>
3710             </tr><tr>
3711                 <td><?php echo _EBLOG_CREATE ?></td>
3712                 <td><input type="submit" value="<?php echo _EBLOG_CREATE_BTN ?>" onclick="return checkSubmit();" /></td>
3713             </tr></table>
3714         </div></form>
3715
3716         <h3><a id="skins"><?php echo _BLOGCREATED_ADVANCEDWAY2 ?></a></h3>
3717
3718         <p><?php echo _BLOGCREATED_ADVANCEDWAY3 ?></p>
3719
3720         <form action="index.php" method="post"><div>
3721             <input type="hidden" name="action" value="addnewlog2" />
3722             <?php $manager->addTicketHidden() ?>
3723             <input type="hidden" name="blogid" value="<?php echo intval($blogid) ?>" />
3724             <table><tr>
3725                 <td><?php echo _EBLOG_URL ?></td>
3726                 <td><input name="url" maxlength="100" size="40" /></td>
3727             </tr><tr>
3728                 <td><?php echo _EBLOG_CREATE ?></td>
3729                 <td><input type="submit" value="<?php echo _EBLOG_CREATE_BTN ?>" onclick="return checkSubmit();" /></td>
3730             </tr></table>
3731         </div></form>
3732
3733         <?php       $this->pagefoot();
3734
3735     }
3736
3737     /**
3738      * @todo document this
3739      */
3740     function action_addnewlog2() {
3741         global $member, $manager;
3742
3743         $member->blogAdminRights($blogid) or $this->disallow();
3744
3745         $burl   = requestVar('url');
3746         $blogid = intRequestVar('blogid');
3747
3748         $blog =& $manager->getBlog($blogid);
3749         $blog->setURL(trim($burl));
3750         $blog->writeSettings();
3751
3752         $this->action_overview(_MSG_NEWBLOG);
3753     }
3754
3755     /**
3756      * @todo document this
3757      */
3758     function action_skinieoverview() {
3759         global $member, $DIR_LIBS, $manager;
3760
3761         $member->isAdmin() or $this->disallow();
3762
3763         // load skinie class
3764         include_once($DIR_LIBS . 'skinie.php');
3765
3766         $this->pagehead();
3767
3768         echo '<p><a href="index.php?action=manage">(',_BACKTOMANAGE,')</a></p>';
3769
3770     ?>
3771         <h2><?php echo _SKINIE_TITLE_IMPORT ?></h2>
3772
3773                 <p><label for="skinie_import_local"><?php echo _SKINIE_LOCAL ?></label>
3774                 <?php                   global $DIR_SKINS;
3775
3776                     $candidates = SkinImport::searchForCandidates($DIR_SKINS);
3777
3778                     if (sizeof($candidates) > 0) {
3779                         ?>
3780                             <form method="post" action="index.php"><div>
3781                                 <input type="hidden" name="action" value="skinieimport" />
3782                                 <?php $manager->addTicketHidden() ?>
3783                                 <input type="hidden" name="mode" value="file" />
3784                                 <select name="skinfile" id="skinie_import_local">
3785                                 <?php                                   foreach ($candidates as $skinname => $skinfile) {
3786                                         $html = Entity::hsc($skinfile);
3787                                         echo '<option value="',$html,'">',$skinname,'</option>';
3788                                     }
3789                                 ?>
3790                                 </select>
3791                                 <input type="submit" value="<?php echo _SKINIE_BTN_IMPORT ?>" />
3792                             </div></form>
3793                         <?php                   } else {
3794                         echo _SKINIE_NOCANDIDATES;
3795                     }
3796                 ?>
3797                 </p>
3798
3799                 <p><em><?php echo _OR ?></em></p>
3800
3801                 <form method="post" action="index.php"><p>
3802                     <?php $manager->addTicketHidden() ?>
3803                     <input type="hidden" name="action" value="skinieimport" />
3804                     <input type="hidden" name="mode" value="url" />
3805                     <label for="skinie_import_url"><?php echo _SKINIE_FROMURL ?></label>
3806                     <input type="text" name="skinfile" id="skinie_import_url" size="60" value="http://" />
3807                     <input type="submit" value="<?php echo _SKINIE_BTN_IMPORT ?>" />
3808                 </p></form>
3809
3810
3811         <h2><?php echo _SKINIE_TITLE_EXPORT ?></h2>
3812         <form method="post" action="index.php"><div>
3813             <input type="hidden" name="action" value="skinieexport" />
3814             <?php $manager->addTicketHidden() ?>
3815
3816             <p><?php echo _SKINIE_EXPORT_INTRO ?></p>
3817
3818             <table><tr>
3819                 <th colspan="2"><?php echo _SKINIE_EXPORT_SKINS ?></th>
3820             </tr><tr>
3821     <?php       // show list of skins
3822         $res = DB::getResult('SELECT * FROM '.sql_table('skin_desc'));
3823         foreach ( $res as $row) {
3824             $id = 'skinexp' . $row['sdnumber'];
3825             echo '<td><input type="checkbox" name="skin[',$row['sdnumber'],']"  id="',$id,'" />';
3826             echo '<label for="',$id,'">',Entity::hsc($row['sdname']),'</label></td>';
3827             echo '<td>',Entity::hsc($row['sddesc']),'</td>';
3828             echo '</tr><tr>';
3829         }
3830
3831         echo '<th colspan="2">',_SKINIE_EXPORT_TEMPLATES,'</th></tr><tr>';
3832
3833         // show list of templates
3834         $res = DB::getResult('SELECT * FROM '.sql_table('template_desc'));
3835         foreach ( $res as $row ) {
3836             $id = 'templateexp' . $row['tdnumber'];
3837             echo '<td><input type="checkbox" name="template[',$row['tdnumber'],']" id="',$id,'" />';
3838             echo '<label for="',$id,'">',Entity::hsc($row['tdname']),'</label></td>';
3839             echo '<td>',Entity::hsc($row['tddesc']),'</td>';
3840             echo '</tr><tr>';
3841         }
3842
3843     ?>
3844                 <th colspan="2"><?php echo _SKINIE_EXPORT_EXTRA ?></th>
3845             </tr><tr>
3846                 <td colspan="2"><textarea cols="40" rows="5" name="info"></textarea></td>
3847             </tr><tr>
3848                 <th colspan="2"><?php echo _SKINIE_TITLE_EXPORT ?></th>
3849             </tr><tr>
3850                 <td colspan="2"><input type="submit" value="<?php echo _SKINIE_BTN_EXPORT ?>" /></td>
3851             </tr></table>
3852         </div></form>
3853
3854     <?php
3855         $this->pagefoot();
3856
3857     }
3858
3859     /**
3860      * @todo document this
3861      */
3862     function action_skinieimport() {
3863         global $member, $DIR_LIBS, $DIR_SKINS, $manager;
3864
3865         $member->isAdmin() or $this->disallow();
3866
3867         // load skinie class
3868         include_once($DIR_LIBS . 'skinie.php');
3869
3870         $skinFileRaw= postVar('skinfile');
3871         $mode       = postVar('mode');
3872
3873         $importer = new SkinImport();
3874
3875         // get full filename
3876         if ($mode == 'file')
3877         {
3878             $skinFile = $DIR_SKINS . $skinFileRaw . '/skinbackup.xml';
3879
3880             // backwards compatibilty (in v2.0, exports were saved as skindata.xml)
3881             if (!file_exists($skinFile))
3882                 $skinFile = $DIR_SKINS . $skinFileRaw . '/skindata.xml';
3883         } else {
3884             $skinFile = $skinFileRaw;
3885         }
3886
3887         // read only metadata
3888         $error = $importer->readFile($skinFile, 1);
3889
3890         // clashes
3891         $skinNameClashes = $importer->checkSkinNameClashes();
3892         $templateNameClashes = $importer->checkTemplateNameClashes();
3893         $hasNameClashes = (count($skinNameClashes) > 0) || (count($templateNameClashes) > 0);
3894
3895         if ($error) $this->error($error);
3896
3897         $this->pagehead();
3898
3899         echo '<p><a href="index.php?action=skinieoverview">(',_BACK,')</a></p>';
3900         ?>
3901         <h2><?php echo _SKINIE_CONFIRM_TITLE ?></h2>
3902
3903         <ul>
3904             <li><p><strong><?php echo _SKINIE_INFO_GENERAL ?></strong> <?php echo Entity::hsc($importer->getInfo()) ?></p></li>
3905             <li><p><strong><?php echo _SKINIE_INFO_SKINS ?></strong> <?php echo implode(' <em>'._AND.'</em> ',$importer->getSkinNames()) ?></p></li>
3906             <li><p><strong><?php echo _SKINIE_INFO_TEMPLATES ?></strong> <?php echo implode(' <em>'._AND.'</em> ',$importer->getTemplateNames()) ?></p></li>
3907             <?php
3908                 if ($hasNameClashes)
3909                 {
3910             ?>
3911             <li><p><strong style="color: red;"><?php echo _SKINIE_INFO_SKINCLASH ?></strong> <?php echo implode(' <em>'._AND.'</em> ',$skinNameClashes) ?></p></li>
3912             <li><p><strong style="color: red;"><?php echo _SKINIE_INFO_TEMPLCLASH ?></strong> <?php echo implode(' <em>'._AND.'</em> ',$templateNameClashes) ?></p></li>
3913             <?php
3914                 } // if (hasNameClashes)
3915             ?>
3916         </ul>
3917
3918         <form method="post" action="index.php"><div>
3919             <input type="hidden" name="action" value="skiniedoimport" />
3920             <?php $manager->addTicketHidden() ?>
3921             <input type="hidden" name="skinfile" value="<?php echo Entity::hsc(postVar('skinfile')) ?>" />
3922             <input type="hidden" name="mode" value="<?php echo Entity::hsc($mode) ?>" />
3923             <input type="submit" value="<?php echo _SKINIE_CONFIRM_IMPORT ?>" />
3924             <?php
3925                 if ($hasNameClashes)
3926                 {
3927             ?>
3928             <br />
3929             <input type="checkbox" name="overwrite" value="1" id="cb_overwrite" /><label for="cb_overwrite"><?php echo _SKINIE_CONFIRM_OVERWRITE ?></label>
3930             <?php
3931                 } // if (hasNameClashes)
3932             ?>
3933         </div></form>
3934
3935
3936         <?php
3937         $this->pagefoot();
3938     }
3939
3940     /**
3941      * @todo document this
3942      */
3943     function action_skiniedoimport() {
3944         global $member, $DIR_LIBS, $DIR_SKINS;
3945
3946         $member->isAdmin() or $this->disallow();
3947
3948         // load skinie class
3949         include_once($DIR_LIBS . 'skinie.php');
3950
3951         $skinFileRaw= postVar('skinfile');
3952         $mode       = postVar('mode');
3953
3954         $allowOverwrite = intPostVar('overwrite');
3955
3956         // get full filename
3957         if ($mode == 'file')
3958         {
3959             $skinFile = $DIR_SKINS . $skinFileRaw . '/skinbackup.xml';
3960
3961             // backwards compatibilty (in v2.0, exports were saved as skindata.xml)
3962             if (!file_exists($skinFile))
3963                 $skinFile = $DIR_SKINS . $skinFileRaw . '/skindata.xml';
3964
3965         } else {
3966             $skinFile = $skinFileRaw;
3967         }
3968
3969         $importer = new SkinImport();
3970
3971         $error = $importer->readFile($skinFile);
3972
3973         if ($error)
3974             $this->error($error);
3975
3976         $error = $importer->writeToDatabase($allowOverwrite);
3977
3978         if ($error)
3979             $this->error($error);
3980
3981         $this->pagehead();
3982
3983         echo '<p><a href="index.php?action=manage">(',_BACKTOMANAGE,')</a></p>';
3984     ?>
3985         <h2><?php echo _SKINIE_DONE ?></h2>
3986
3987         <ul>
3988             <li><p><strong><?php echo _SKINIE_INFO_GENERAL ?></strong> <?php echo Entity::hsc($importer->getInfo()) ?></p></li>
3989             <li><p><strong><?php echo _SKINIE_INFO_IMPORTEDSKINS ?></strong> <?php echo implode(' <em>'._AND.'</em> ',$importer->getSkinNames()) ?></p></li>
3990             <li><p><strong><?php echo _SKINIE_INFO_IMPORTEDTEMPLS ?></strong> <?php echo implode(' <em>'._AND.'</em> ',$importer->getTemplateNames()) ?></p></li>
3991         </ul>
3992
3993     <?php       $this->pagefoot();
3994
3995     }
3996
3997     /**
3998      * @todo document this
3999      */
4000     function action_skinieexport() {
4001         global $member, $DIR_LIBS;
4002
4003         $member->isAdmin() or $this->disallow();
4004
4005         // load skinie class
4006         include_once($DIR_LIBS . 'skinie.php');
4007
4008         $aSkins = requestIntArray('skin');
4009         $aTemplates = requestIntArray('template');
4010
4011         if (!is_array($aTemplates)) $aTemplates = array();
4012         if (!is_array($aSkins)) $aSkins = array();
4013
4014         $skinList = array_keys($aSkins);
4015         $templateList = array_keys($aTemplates);
4016
4017         $info = postVar('info');
4018
4019         $exporter = new SkinExport();
4020         foreach ($skinList as $skinId) {
4021             $exporter->addSkin($skinId);
4022         }
4023         foreach ($templateList as $templateId) {
4024             $exporter->addTemplate($templateId);
4025         }
4026         $exporter->setInfo($info);
4027
4028         $exporter->export();
4029     }
4030
4031     /**
4032      * @todo document this
4033      */
4034     function action_templateoverview() {
4035         global $member, $manager;
4036
4037         $member->isAdmin() or $this->disallow();
4038
4039         $this->pagehead();
4040
4041         echo '<p><a href="index.php?action=manage">(',_BACKTOMANAGE,')</a></p>';
4042
4043         echo '<h2>' . _TEMPLATE_TITLE . '</h2>';
4044         echo '<h3>' . _TEMPLATE_AVAILABLE_TITLE . '</h3>';
4045
4046         $query = 'SELECT * FROM '.sql_table('template_desc').' ORDER BY tdname';
4047         $template['content'] = 'templatelist';
4048         $template['tabindex'] = 10;
4049         showlist($query,'table',$template);
4050
4051         echo '<h3>' . _TEMPLATE_NEW_TITLE . '</h3>';
4052
4053         ?>
4054         <form method="post" action="index.php"><div>
4055
4056         <input name="action" value="templatenew" type="hidden" />
4057         <?php $manager->addTicketHidden() ?>
4058         <table><tr>
4059             <td><?php echo _TEMPLATE_NAME ?> <?php help('shortnames'); ?></td>
4060             <td><input name="name" tabindex="10010" maxlength="20" size="20" /></td>
4061         </tr><tr>
4062             <td><?php echo _TEMPLATE_DESC ?></td>
4063             <td><input name="desc" tabindex="10020" maxlength="200" size="50" /></td>
4064         </tr><tr>
4065             <td><?php echo _TEMPLATE_CREATE ?></td>
4066             <td><input type="submit" tabindex="10030" value="<?php echo _TEMPLATE_CREATE_BTN ?>" onclick="return checkSubmit();" /></td>
4067         </tr></table>
4068
4069         </div></form>
4070
4071         <?php
4072         $this->pagefoot();
4073     }
4074
4075     /**
4076      * @todo document this
4077      */
4078     function action_templateedit($msg = '') {
4079         global $member, $manager;
4080
4081         $templateid = intRequestVar('templateid');
4082
4083         $member->isAdmin() or $this->disallow();
4084
4085         $extrahead = '<script type="text/javascript" src="javascript/templateEdit.js"></script>';
4086         $extrahead .= '<script type="text/javascript">setTemplateEditText('.DB::quoteValue(_EDITTEMPLATE_EMPTY).');</script>';
4087
4088         $this->pagehead($extrahead);
4089
4090         $templatename = Template::getNameFromId($templateid);
4091         $templatedescription = Template::getDesc($templateid);
4092         $template =& $manager->getTemplate($templatename);
4093
4094         ?>
4095         <p>
4096         <a href="index.php?action=templateoverview">(<?php echo _TEMPLATE_BACK ?>)</a>
4097         </p>
4098
4099         <h2><?php echo _TEMPLATE_EDIT_TITLE ?> '<?php echo  Entity::hsc($templatename); ?>'</h2>
4100
4101         <?php                   if ($msg) echo "<p>"._MESSAGE.": $msg</p>";
4102         ?>
4103
4104         <p><?php echo _TEMPLATE_EDIT_MSG ?></p>
4105
4106         <form method="post" action="index.php">
4107         <div>
4108
4109         <input type="hidden" name="action" value="templateupdate" />
4110         <?php $manager->addTicketHidden() ?>
4111         <input type="hidden" name="templateid" value="<?php echo  $templateid; ?>" />
4112
4113         <table><tr>
4114             <th colspan="2"><?php echo _TEMPLATE_SETTINGS ?></th>
4115         </tr><tr>
4116             <td><?php echo _TEMPLATE_NAME ?> <?php help('shortnames'); ?></td>
4117             <td><input name="tname" tabindex="4" size="20" maxlength="20" value="<?php echo  Entity::hsc($templatename) ?>" /></td>
4118         </tr><tr>
4119             <td><?php echo _TEMPLATE_DESC ?></td>
4120             <td><input name="tdesc" tabindex="5" size="50" maxlength="200" value="<?php echo  Entity::hsc($templatedescription) ?>" /></td>
4121         </tr><tr>
4122             <th colspan="2"><?php echo _TEMPLATE_UPDATE ?></th>
4123         </tr><tr>
4124             <td><?php echo _TEMPLATE_UPDATE ?></td>
4125             <td>
4126                 <input type="submit" tabindex="6" value="<?php echo _TEMPLATE_UPDATE_BTN ?>" onclick="return checkSubmit();" />
4127                 <input type="reset" tabindex="7" value="<?php echo _TEMPLATE_RESET_BTN ?>" />
4128             </td>
4129         </tr><tr>
4130             <th colspan="2"><?php echo _TEMPLATE_ITEMS ?> <?php help('templateitems'); ?></th>
4131 <?php   $this->_templateEditRow($template, _TEMPLATE_ITEMHEADER, 'ITEM_HEADER', '', 8);
4132     $this->_templateEditRow($template, _TEMPLATE_ITEMBODY, 'ITEM', '', 9, 1);
4133     $this->_templateEditRow($template, _TEMPLATE_ITEMFOOTER, 'ITEM_FOOTER', '', 10);
4134     $this->_templateEditRow($template, _TEMPLATE_MORELINK, 'MORELINK', 'morelink', 20);
4135     $this->_templateEditRow($template, _TEMPLATE_EDITLINK, 'EDITLINK', 'editlink', 25);
4136     $this->_templateEditRow($template, _TEMPLATE_NEW, 'NEW', 'new', 30);
4137 ?>
4138         </tr><tr>
4139             <th colspan="2"><?php echo _TEMPLATE_COMMENTS_ANY ?> <?php help('templatecomments'); ?></th>
4140 <?php   $this->_templateEditRow($template, _TEMPLATE_CHEADER, 'COMMENTS_HEADER', 'commentheaders', 40);
4141     $this->_templateEditRow($template, _TEMPLATE_CBODY, 'COMMENTS_BODY', 'commentbody', 50, 1);
4142     $this->_templateEditRow($template, _TEMPLATE_CFOOTER, 'COMMENTS_FOOTER', 'commentheaders', 60);
4143     $this->_templateEditRow($template, _TEMPLATE_CONE, 'COMMENTS_ONE', 'commentwords', 70);
4144     $this->_templateEditRow($template, _TEMPLATE_CMANY, 'COMMENTS_MANY', 'commentwords', 80);
4145     $this->_templateEditRow($template, _TEMPLATE_CMORE, 'COMMENTS_CONTINUED', 'commentcontinued', 90);
4146     $this->_templateEditRow($template, _TEMPLATE_CMEXTRA, 'COMMENTS_AUTH', 'memberextra', 100);
4147 ?>
4148         </tr><tr>
4149             <th colspan="2"><?php echo _TEMPLATE_COMMENTS_NONE ?> <?php help('templatecomments'); ?></th>
4150 <?php
4151     $this->_templateEditRow($template, _TEMPLATE_CNONE, 'COMMENTS_NONE', '', 110);
4152 ?>
4153         </tr><tr>
4154             <th colspan="2"><?php echo _TEMPLATE_COMMENTS_TOOMUCH ?> <?php help('templatecomments'); ?></th>
4155 <?php   $this->_templateEditRow($template, _TEMPLATE_CTOOMUCH, 'COMMENTS_TOOMUCH', '', 120);
4156 ?>
4157         </tr><tr>
4158             <th colspan="2"><?php echo _TEMPLATE_ARCHIVELIST ?> <?php help('templatearchivelists'); ?></th>
4159 <?php   $this->_templateEditRow($template, _TEMPLATE_AHEADER, 'ARCHIVELIST_HEADER', '', 130);
4160     $this->_templateEditRow($template, _TEMPLATE_AITEM, 'ARCHIVELIST_LISTITEM', '', 140);
4161     $this->_templateEditRow($template, _TEMPLATE_AFOOTER, 'ARCHIVELIST_FOOTER', '', 150);
4162 ?>
4163         </tr><tr>
4164             <th colspan="2"><?php echo _TEMPLATE_BLOGLIST ?> <?php help('templatebloglists'); ?></th>
4165 <?php   $this->_templateEditRow($template, _TEMPLATE_BLOGHEADER, 'BLOGLIST_HEADER', '', 160);
4166     $this->_templateEditRow($template, _TEMPLATE_BLOGITEM, 'BLOGLIST_LISTITEM', '', 170);
4167     $this->_templateEditRow($template, _TEMPLATE_BLOGFOOTER, 'BLOGLIST_FOOTER', '', 180);
4168 ?>
4169         </tr><tr>
4170             <th colspan="2"><?php echo _TEMPLATE_CATEGORYLIST ?> <?php help('templatecategorylists'); ?></th>
4171 <?php   $this->_templateEditRow($template, _TEMPLATE_CATHEADER, 'CATLIST_HEADER', '', 190);
4172     $this->_templateEditRow($template, _TEMPLATE_CATITEM, 'CATLIST_LISTITEM', '', 200);
4173     $this->_templateEditRow($template, _TEMPLATE_CATFOOTER, 'CATLIST_FOOTER', '', 210);
4174 ?>
4175         </tr><tr>
4176             <th colspan="2"><?php echo _TEMPLATE_DATETIME ?></th>
4177 <?php   $this->_templateEditRow($template, _TEMPLATE_DHEADER, 'DATE_HEADER', 'dateheads', 220);
4178     $this->_templateEditRow($template, _TEMPLATE_DFOOTER, 'DATE_FOOTER', 'dateheads', 230);
4179     $this->_templateEditRow($template, _TEMPLATE_DFORMAT, 'FORMAT_DATE', 'datetime', 240);
4180     $this->_templateEditRow($template, _TEMPLATE_TFORMAT, 'FORMAT_TIME', 'datetime', 250);
4181     $this->_templateEditRow($template, _TEMPLATE_LOCALE, 'LOCALE', 'locale', 260);
4182 ?>
4183         </tr><tr>
4184             <th colspan="2"><?php echo _TEMPLATE_IMAGE ?> <?php help('templatepopups'); ?></th>
4185 <?php   $this->_templateEditRow($template, _TEMPLATE_PCODE, 'POPUP_CODE', '', 270);
4186     $this->_templateEditRow($template, _TEMPLATE_ICODE, 'IMAGE_CODE', '', 280);
4187     $this->_templateEditRow($template, _TEMPLATE_MCODE, 'MEDIA_CODE', '', 290);
4188 ?>
4189         </tr><tr>
4190             <th colspan="2"><?php echo _TEMPLATE_SEARCH ?></th>
4191 <?php   $this->_templateEditRow($template, _TEMPLATE_SHIGHLIGHT, 'SEARCH_HIGHLIGHT', 'highlight',300);
4192     $this->_templateEditRow($template, _TEMPLATE_SNOTFOUND, 'SEARCH_NOTHINGFOUND', 'nothingfound',310);
4193 ?>
4194         </tr><tr>
4195             <th colspan="2"><?php echo _TEMPLATE_PLUGIN_FIELDS ?></th>
4196 <?php
4197         $tab = 600;
4198         $pluginfields = array();
4199         $manager->notify('TemplateExtraFields',array('fields'=>&$pluginfields));
4200
4201         foreach ($pluginfields as $pfkey=>$pfvalue) {
4202             echo "</tr><tr>\n";
4203             echo '<th colspan="2">' . Entity::hen($pfkey) . "</th>\n";
4204             foreach ($pfvalue as $pffield=>$pfdesc) {
4205                 $this->_templateEditRow($template, $pfdesc, $pffield, '',++$tab,0);
4206             }
4207         }
4208 ?>
4209         </tr><tr>
4210             <th colspan="2"><?php echo _TEMPLATE_UPDATE ?></th>
4211         </tr><tr>
4212             <td><?php echo _TEMPLATE_UPDATE ?></td>
4213             <td>
4214                 <input type="submit" tabindex="800" value="<?php echo _TEMPLATE_UPDATE_BTN ?>" onclick="return checkSubmit();" />
4215                 <input type="reset" tabindex="810" value="<?php echo _TEMPLATE_RESET_BTN ?>" />
4216             </td>
4217         </tr></table>
4218
4219         </div>
4220         </form>
4221         <?php
4222         $this->pagefoot();
4223     }
4224
4225     /**
4226      * @todo document this
4227      */
4228     function _templateEditRow(&$template, $description, $name, $help = '', $tabindex = 0, $big = 0) {
4229         static $count = 1;
4230         if (!isset($template[$name])) $template[$name] = '';
4231     ?>
4232         </tr><tr>
4233             <td><?php echo $description ?> <?php if ($help) help('template'.$help); ?></td>
4234             <td id="td<?php echo $count ?>"><textarea class="templateedit" name="<?php echo $name ?>" tabindex="<?php echo $tabindex ?>" cols="50" rows="<?php echo $big?10:5 ?>" id="textarea<?php echo $count ?>"><?php echo  Entity::hsc($template[$name]); ?></textarea></td>
4235     <?php       $count++;
4236     }
4237
4238     /**
4239      * @todo document this
4240      */
4241     function action_templateupdate() {
4242         global $member,$manager;
4243
4244         $templateid = intRequestVar('templateid');
4245
4246         $member->isAdmin() or $this->disallow();
4247
4248         $name = postVar('tname');
4249         $desc = postVar('tdesc');
4250
4251         if (!isValidTemplateName($name))
4252             $this->error(_ERROR_BADTEMPLATENAME);
4253
4254         if ((Template::getNameFromId($templateid) != $name) && Template::exists($name))
4255             $this->error(_ERROR_DUPTEMPLATENAME);
4256
4257
4258         $name = DB::quoteValue($name);
4259         $desc = DB::quoteValue($desc);
4260
4261         // 1. Remove all template parts
4262         $query = 'DELETE FROM '.sql_table('template').' WHERE tdesc=' . $templateid;
4263         DB::execute($query);
4264
4265         // 2. Update description
4266         $query =  'UPDATE '.sql_table('template_desc').' SET'
4267                . ' tdname=' . $name . ','
4268                . ' tddesc=' . $desc
4269                . ' WHERE tdnumber=' . $templateid;
4270         DB::execute($query);
4271
4272         // 3. Add non-empty template parts
4273         $this->addToTemplate($templateid, 'ITEM_HEADER', postVar('ITEM_HEADER'));
4274         $this->addToTemplate($templateid, 'ITEM', postVar('ITEM'));
4275         $this->addToTemplate($templateid, 'ITEM_FOOTER', postVar('ITEM_FOOTER'));
4276         $this->addToTemplate($templateid, 'MORELINK', postVar('MORELINK'));
4277         $this->addToTemplate($templateid, 'EDITLINK', postVar('EDITLINK'));
4278         $this->addToTemplate($templateid, 'NEW', postVar('NEW'));
4279         $this->addToTemplate($templateid, 'COMMENTS_HEADER', postVar('COMMENTS_HEADER'));
4280         $this->addToTemplate($templateid, 'COMMENTS_BODY', postVar('COMMENTS_BODY'));
4281         $this->addToTemplate($templateid, 'COMMENTS_FOOTER', postVar('COMMENTS_FOOTER'));
4282         $this->addToTemplate($templateid, 'COMMENTS_CONTINUED', postVar('COMMENTS_CONTINUED'));
4283         $this->addToTemplate($templateid, 'COMMENTS_TOOMUCH', postVar('COMMENTS_TOOMUCH'));
4284         $this->addToTemplate($templateid, 'COMMENTS_AUTH', postVar('COMMENTS_AUTH'));
4285         $this->addToTemplate($templateid, 'COMMENTS_ONE', postVar('COMMENTS_ONE'));
4286         $this->addToTemplate($templateid, 'COMMENTS_MANY', postVar('COMMENTS_MANY'));
4287         $this->addToTemplate($templateid, 'COMMENTS_NONE', postVar('COMMENTS_NONE'));
4288         $this->addToTemplate($templateid, 'ARCHIVELIST_HEADER', postVar('ARCHIVELIST_HEADER'));
4289         $this->addToTemplate($templateid, 'ARCHIVELIST_LISTITEM', postVar('ARCHIVELIST_LISTITEM'));
4290         $this->addToTemplate($templateid, 'ARCHIVELIST_FOOTER', postVar('ARCHIVELIST_FOOTER'));
4291         $this->addToTemplate($templateid, 'BLOGLIST_HEADER', postVar('BLOGLIST_HEADER'));
4292         $this->addToTemplate($templateid, 'BLOGLIST_LISTITEM', postVar('BLOGLIST_LISTITEM'));
4293         $this->addToTemplate($templateid, 'BLOGLIST_FOOTER', postVar('BLOGLIST_FOOTER'));
4294         $this->addToTemplate($templateid, 'CATLIST_HEADER', postVar('CATLIST_HEADER'));
4295         $this->addToTemplate($templateid, 'CATLIST_LISTITEM', postVar('CATLIST_LISTITEM'));
4296         $this->addToTemplate($templateid, 'CATLIST_FOOTER', postVar('CATLIST_FOOTER'));
4297         $this->addToTemplate($templateid, 'DATE_HEADER', postVar('DATE_HEADER'));
4298         $this->addToTemplate($templateid, 'DATE_FOOTER', postVar('DATE_FOOTER'));
4299         $this->addToTemplate($templateid, 'FORMAT_DATE', postVar('FORMAT_DATE'));
4300         $this->addToTemplate($templateid, 'FORMAT_TIME', postVar('FORMAT_TIME'));
4301         $this->addToTemplate($templateid, 'LOCALE', postVar('LOCALE'));
4302         $this->addToTemplate($templateid, 'SEARCH_HIGHLIGHT', postVar('SEARCH_HIGHLIGHT'));
4303         $this->addToTemplate($templateid, 'SEARCH_NOTHINGFOUND', postVar('SEARCH_NOTHINGFOUND'));
4304         $this->addToTemplate($templateid, 'POPUP_CODE', postVar('POPUP_CODE'));
4305         $this->addToTemplate($templateid, 'MEDIA_CODE', postVar('MEDIA_CODE'));
4306         $this->addToTemplate($templateid, 'IMAGE_CODE', postVar('IMAGE_CODE'));
4307
4308         $pluginfields = array();
4309         $manager->notify('TemplateExtraFields',array('fields'=>&$pluginfields));
4310         foreach ($pluginfields as $pfkey=>$pfvalue) {
4311             foreach ($pfvalue as $pffield=>$pfdesc) {
4312                 $this->addToTemplate($templateid, $pffield, postVar($pffield));
4313             }
4314         }
4315
4316         // jump back to template edit
4317         $this->action_templateedit(_TEMPLATE_UPDATED);
4318
4319     }
4320
4321         /**
4322          * Admin::addToTemplate()
4323          * 
4324          * @param       Integer $id     ID for template
4325          * @param       String  $partname       parts name
4326          * @param       String  $content        template contents
4327          * @return      Integer record index
4328          * 
4329          */
4330         function addToTemplate($id, $partname, $content)
4331         {
4332                 // don't add empty parts:
4333                 if ( !trim($content) )
4334                 {
4335                         return -1;
4336                 }
4337                 
4338                 $partname = DB::quoteValue($partname);
4339                 $content = DB::quoteValue($content);
4340                 
4341                 $query = "INSERT INTO %s (tdesc, tpartname, tcontent) VALUES (%d, %s, %s)";
4342                 $query = sprintf($query, sql_table('template'), (integer) $id, $partname, $content);
4343                 if ( DB::execute($query) === FALSE )
4344                 {
4345                         $err = DB::getError();
4346                         exit(_ADMIN_SQLDIE_QUERYERROR . $err[2]);
4347                 }
4348                 return DB::getInsertId();
4349         }
4350         
4351     /**
4352      * @todo document this
4353      */
4354     function action_templatedelete() {
4355         global $member, $manager;
4356
4357         $member->isAdmin() or $this->disallow();
4358
4359         $templateid = intRequestVar('templateid');
4360         // TODO: check if template can be deleted
4361
4362         $this->pagehead();
4363
4364         $name = Template::getNameFromId($templateid);
4365         $desc = Template::getDesc($templateid);
4366
4367         ?>
4368             <h2><?php echo _DELETE_CONFIRM ?></h2>
4369
4370             <p>
4371             <?php echo _CONFIRMTXT_TEMPLATE ?><b><?php echo Entity::hsc($name) ?></b> (<?php echo  Entity::hsc($desc) ?>)
4372             </p>
4373
4374             <form method="post" action="index.php"><div>
4375                 <input type="hidden" name="action" value="templatedeleteconfirm" />
4376                 <?php $manager->addTicketHidden() ?>
4377                 <input type="hidden" name="templateid" value="<?php echo  $templateid ?>" />
4378                 <input type="submit" tabindex="10" value="<?php echo _DELETE_CONFIRM_BTN ?>" />
4379             </div></form>
4380         <?php
4381         $this->pagefoot();
4382     }
4383
4384     /**
4385      * @todo document this
4386      */
4387     function action_templatedeleteconfirm() {
4388         global $member, $manager;
4389
4390         $templateid = intRequestVar('templateid');
4391
4392         $member->isAdmin() or $this->disallow();
4393
4394         $manager->notify('PreDeleteTemplate', array('templateid' => $templateid));
4395
4396         // 1. delete description
4397         DB::execute('DELETE FROM '.sql_table('template_desc').' WHERE tdnumber=' . $templateid);
4398
4399         // 2. delete parts
4400         DB::execute('DELETE FROM '.sql_table('template').' WHERE tdesc=' . $templateid);
4401
4402         $manager->notify('PostDeleteTemplate', array('templateid' => $templateid));
4403
4404         $this->action_templateoverview();
4405     }
4406
4407     /**
4408      * @todo document this
4409      */
4410     function action_templatenew() {
4411         global $member;
4412
4413         $member->isAdmin() or $this->disallow();
4414
4415         $name = postVar('name');
4416         $desc = postVar('desc');
4417
4418         if (!isValidTemplateName($name))
4419             $this->error(_ERROR_BADTEMPLATENAME);
4420
4421         if (Template::exists($name))
4422             $this->error(_ERROR_DUPTEMPLATENAME);
4423
4424         $newTemplateId = Template::createNew($name, $desc);
4425
4426         $this->action_templateoverview();
4427     }
4428
4429     /**
4430      * @todo document this
4431      */
4432     function action_templateclone() {
4433         global $member;
4434
4435         $templateid = intRequestVar('templateid');
4436
4437         $member->isAdmin() or $this->disallow();
4438
4439         // 1. read old template
4440         $name = Template::getNameFromId($templateid);
4441         $desc = Template::getDesc($templateid);
4442
4443         // 2. create desc thing
4444         $name = "cloned" . $name;
4445
4446         // if a template with that name already exists:
4447         if (Template::exists($name)) {
4448             $i = 1;
4449             while (Template::exists($name . $i))
4450                 $i++;
4451             $name .= $i;
4452         }
4453
4454         $newid = Template::createNew($name, $desc);
4455
4456         // 3. create clone
4457         // go through parts of old template and add them to the new one
4458         $res = DB::getResult('SELECT tpartname, tcontent FROM '.sql_table('template').' WHERE tdesc=' . $templateid);
4459         foreach ( $res as $row ) {
4460             $this->addToTemplate($newid, $row['tpartname'], $row['tcontent']);
4461         }
4462
4463         $this->action_templateoverview();
4464     }
4465         
4466         /**
4467          * Admin::action_skinoverview()
4468          * 
4469          * @param       void
4470          * @return      void
4471          */
4472         public function action_skinoverview()
4473         {
4474                 global $member, $manager;
4475                 
4476                 $member->isAdmin() or $this->disallow();
4477                 
4478                 $this->pagehead();
4479                 
4480                 echo '<p><a href="index.php?action=manage">(' . _BACKTOMANAGE . ")</a></p>\n";
4481                 echo '<h2>' . _SKIN_EDIT_TITLE . "</h2>\n";
4482                 echo '<h3>' . _SKIN_AVAILABLE_TITLE . "</h3>\n";
4483                 
4484                 $query = 'SELECT * FROM '.sql_table('skin_desc').' ORDER BY sdname;';
4485                 $template['content'] = 'skinlist';
4486                 $template['tabindex'] = 10;
4487                 
4488                 showlist($query,'table',$template);
4489                 
4490                 echo '<h3>' . _SKIN_NEW_TITLE . "</h3>\n";
4491                 echo "<form method=\"post\" action=\"index.php\">\n";
4492                 echo "<div>\n";
4493                 echo "<input name=\"action\" value=\"skinnew\" type=\"hidden\" />\n";
4494                 
4495                 $manager->addTicketHidden() . "\n";
4496                 
4497                 echo "<table frame=\"box\" rules=\"all\" summary=\"skinoverview\">\n";
4498                 echo "<tr>\n";
4499                 echo "<td>" . _SKIN_NAME;
4500                 echo help('shortnames');
4501                 echo "</td>\n";
4502                 echo "<td><input name=\"name\" tabindex=\"10010\" maxlength=\"20\" size=\"20\" /></td>\n";
4503                 echo "</tr>\n";
4504                 echo "<tr>\n";
4505                 echo "<td>" . _SKIN_DESC . "</td>\n";
4506                 echo "<td><input name=\"desc\" tabindex=\"10020\" maxlength=\"200\" size=\"50\" /></td>\n";
4507                 echo "</tr>\n";
4508                 echo "<tr>\n";
4509                 echo '<td>' . _SKIN_CREATE . "</td>\n";
4510                 echo '<td><input type="submit" tabindex="10030" value="' . _SKIN_CREATE_BTN . '" onclick="return checkSubmit();" />' . "</td>\n";
4511                 echo "</tr>\n";
4512                 echo "</table>\n";
4513                 
4514                 echo "</div>\n";
4515                 echo "</form>\n";
4516                 
4517                 $this->pagefoot();
4518                 return;
4519         }
4520         
4521     /**
4522      * @todo document this
4523      */
4524     function action_skinnew() {
4525         global $member;
4526
4527         $member->isAdmin() or $this->disallow();
4528
4529         $name = trim(postVar('name'));
4530         $desc = trim(postVar('desc'));
4531
4532         if (!isValidSkinName($name))
4533             $this->error(_ERROR_BADSKINNAME);
4534
4535         if (Skin::exists($name))
4536             $this->error(_ERROR_DUPSKINNAME);
4537
4538         $newId = Skin::createNew($name, $desc);
4539
4540         $this->action_skinoverview();
4541     }
4542
4543         /**
4544          * Admin::action_skinedit()
4545          * @param       void
4546          * @return      void
4547          */
4548         public function action_skinedit()
4549         {
4550                 global $member, $manager;
4551                 
4552                 $skinid = intRequestVar('skinid');
4553                 
4554                 $member->isAdmin() or $this->disallow();
4555                 
4556                 $skin = new SKIN($skinid);
4557                 $default_skin_types = $skin->getDefaultTypes();
4558                 $available_skin_types = $skin->getAvailableTypes();
4559                 
4560                 $this->pagehead();
4561                 
4562                 echo "<p>";
4563                 echo '( <a href="index.php?action=skinoverview">' . _SKIN_BACK . "</a> )";
4564                 echo "</p>\n";
4565                 echo '<h2>' . _SKIN_EDITONE_TITLE . $skin->getName() . "</h2>\n";
4566                 
4567                 echo '<h3>' . _SKIN_PARTS_TITLE . "</h3>\n";
4568                 echo _SKIN_PARTS_MSG . "\n";
4569                 echo "<ul>\n";
4570                 
4571                 $tabindex = 10;
4572                 foreach ( $default_skin_types as $type => $friendly_name )
4573                 {
4574                         echo "<li>\n";
4575                         echo "<a tabindex=\"{$tabindex}\" href=\"index.php?action=skinedittype&amp;skinid={$skinid}&amp;type={$type}\">";
4576                         echo $friendly_name;
4577                         echo "</a>\n";
4578                         help("skinpart{$type}");
4579                         echo "</li>\n";
4580                         $tabindex++;
4581                 }
4582                 echo "</ul>\n";
4583                 
4584                 echo '<h3>' . _SKIN_PARTS_SPECIAL . '</h3>';
4585                 echo "<form method=\"get\" action=\"index.php\">\n";
4586                 echo "<input type=\"hidden\" name=\"action\" value=\"skinedittype\" />\n";
4587                 echo "<input type=\"hidden\" name=\"skinid\" value=\"{$skinid}\" />\n";
4588                 echo "<input type=\"text\" name=\"type\" tabindex=\"89\" size=\"20\" maxlength=\"20\" />\n";
4589                 echo '<input type="submit" tabindex="140" value="' . _SKIN_CREATE . "\" onclick=\"return checkSubmit();\" />\n";
4590                 echo "</form>\n";
4591                 
4592                 /* NOTE: special skin parts has FALSE in its value */
4593                 if ( in_array(FALSE, array_values($available_skin_types)) )
4594                 {
4595                         $tabstart = 75;
4596                         
4597                         echo '<ul>';
4598                         foreach ( $available_skin_types as $type => $friendly_name )
4599                         {
4600                                 if ( !$friendly_name )
4601                                 {
4602                                         $tabstart++;
4603                                         echo "<li>\n";
4604                                         echo "<a tabindex=\"{$tabstart}\" href=\"index.php?action=skinedittype&amp;skinid={$skinid}&amp;type=" . Entity::hsc(strtolower($type)) . '">';
4605                                         echo Entity::hsc(ucfirst($type));
4606                                         echo "</a>\n";
4607                                         $tabstart++;
4608                                         echo "(<a tabindex=\"{$tabstart}\" href=\"index.php?action=skinremovetype&amp;skinid={$skinid}&amp;type=" . Entity::hsc(strtolower($type)) . '">';
4609                                         echo _LISTS_DELETE;
4610                                         echo "</a>)\n";
4611                                         echo "</li>\n";
4612                                 }
4613                         }
4614                         echo '</ul>';
4615                 }
4616                 
4617                 echo '<h3>' . _SKIN_GENSETTINGS_TITLE . "</h3>\n";
4618                 echo "<form method=\"post\" action=\"index.php\">\n";
4619                 echo "<div>\n";
4620                 echo "<input type=\"hidden\" name=\"action\" value=\"skineditgeneral\" />\n";
4621                 $manager->addTicketHidden() . "\n";
4622                 echo "<input type=\"hidden\" name=\"skinid\" value=\"{$skinid}\" />\n";
4623                 
4624                 echo '<table frame="box" rules="all" summary="' . _SKIN_GENSETTINGS_TITLE . '">' . "\n";
4625                 echo "<tr>\n";
4626                 echo '<td>';
4627                 echo _SKIN_NAME;
4628                 help('shortnames');
4629                 echo "</td>\n";
4630                 echo '<td><input type="text" name="name" tabindex="90" value="' . Entity::hsc($skin->getName()) . '" maxlength="20" size="20" />' . "</td>\n";
4631                 echo "</tr>\n";
4632                 echo "<tr>\n";
4633                 echo '<td>' . _SKIN_DESC . "</td>\n";
4634                 echo '<td><input type="text" name="desc" tabindex="100" value="' . Entity::hsc($skin->getDescription()) . '" maxlength="200" size="50" />' . "</td>\n";
4635                 echo "</tr>\n";
4636                 echo "<tr>\n";
4637                 echo '<td>' . _SKIN_TYPE . "</td>\n";
4638                 echo '<td><input type="text" name="type" tabindex="110" value="' . Entity::hsc($skin->getContentType()) . '" maxlength="40" size="20" />' . "</td>\n";
4639                 echo "</tr>\n";
4640                 echo "<tr>\n";
4641                 echo '<td>';
4642                 echo _SKIN_INCLUDE_MODE;
4643                 help('includemode');
4644                 echo "</td>\n";
4645                 echo '<td>';
4646                 $this->input_yesno('inc_mode', $skin->getIncludeMode(), 120, 'skindir', 'normal', _PARSER_INCMODE_SKINDIR, _PARSER_INCMODE_NORMAL);
4647                 echo "</td>\n";
4648                 echo "</tr>\n";
4649                 echo "<tr>\n";
4650                 echo '<td>';
4651                 echo _SKIN_INCLUDE_PREFIX;
4652                 help('includeprefix');
4653                 echo "</td>\n";
4654                 echo '<td><input type="text" name="inc_prefix" tabindex="130" value="' . Entity::hsc($skin->getIncludePrefix()) . '" maxlength="40" size="20" />' . "</td>\n";
4655                 echo "</tr>\n";
4656                 echo "<tr>\n";
4657                 echo '<td>' . _SKIN_CHANGE . "</td>\n";
4658                 echo '<td><input type="submit" tabindex="140" value="' . _SKIN_CHANGE_BTN . '" onclick="return checkSubmit();" />' . "</td>\n";
4659                 echo "</tr>\n";
4660                 echo "</table>\n";
4661                 
4662                 echo "</div>\n";
4663                 echo "</form>\n";
4664                 $this->pagefoot();
4665                 return;
4666         }
4667
4668     /**
4669      * @todo document this
4670      */
4671     function action_skineditgeneral() {
4672         global $member;
4673
4674         $skinid = intRequestVar('skinid');
4675
4676         $member->isAdmin() or $this->disallow();
4677
4678         $name = postVar('name');
4679         $desc = postVar('desc');
4680         $type = postVar('type');
4681         $inc_mode = postVar('inc_mode');
4682         $inc_prefix = postVar('inc_prefix');
4683
4684         $skin = new SKIN($skinid);
4685
4686         // 1. Some checks
4687         if (!isValidSkinName($name))
4688             $this->error(_ERROR_BADSKINNAME);
4689
4690         if (($skin->getName() != $name) && Skin::exists($name))
4691             $this->error(_ERROR_DUPSKINNAME);
4692
4693         if (!$type) $type = 'text/html';
4694         if (!$inc_mode) $inc_mode = 'normal';
4695
4696         // 2. Update description
4697         $skin->updateGeneralInfo($name, $desc, $type, $inc_mode, $inc_prefix);
4698
4699         $this->action_skinedit();
4700
4701     }
4702
4703         /**
4704          * Admin::action_skinedittype()
4705          * 
4706          * @param       string  $msg    message for pageheader
4707          * @return      void
4708          */
4709         public function action_skinedittype($msg = '')
4710         {
4711                 global $member, $manager;
4712                 
4713                 $skinid = intRequestVar('skinid');
4714                 $type = requestVar('type');
4715                 
4716                 $member->isAdmin() or $this->disallow();
4717                 
4718                 $type = trim($type);
4719                 $type = strtolower($type);
4720                 
4721                 if ( !isValidShortName($type) )
4722                 {
4723                         $this->error(_ERROR_SKIN_PARTS_SPECIAL_FORMAT);
4724                 }
4725                 
4726                 $skin = new SKIN($skinid);
4727                 $skin_types = $skin->getAvailableTypes();
4728                 if ( !array_key_exists($type, $skin_types) || !$skin_types[$type] )
4729                 {
4730                         $friendlyName = ucfirst($type);
4731                 }
4732                 else
4733                 {
4734                         $friendlyName = $skin_types[$type];
4735                 }
4736                 
4737                 $this->pagehead();
4738                 
4739                 echo '<p>(<a href="index.php?action=skinoverview">' . _SKIN_GOBACK . "</a>)</p>\n";
4740                 
4741                 echo '<h2>' . _SKIN_EDITPART_TITLE . " '" . Entity::hsc($skin->getName()) . "': " . Entity::hsc($friendlyName) . "</h2>\n";
4742                 
4743                 if ( $msg != '')
4744                 {
4745                         echo "<p>" . _MESSAGE . ": $msg</p>\n";
4746                 }
4747                 
4748                 echo "<form method=\"post\" action=\"index.php\">\n";
4749                 echo "<div>\n";
4750                 
4751                 echo "<input type=\"hidden\" name=\"action\" value=\"skinupdate\" />\n";
4752                 $manager->addTicketHidden() . "\n";
4753                 echo "<input type=\"hidden\" name=\"skinid\" value=\"{$skinid}\" />\n";
4754                 echo "<input type=\"hidden\" name=\"type\" value=\"{$type}\" />\n";
4755                 
4756                 echo '<input type="submit" value="' . _SKIN_UPDATE_BTN . '" onclick="return checkSubmit();" />' . "\n";
4757                 echo '<input type="reset" value="' . _SKIN_RESET_BTN . '" />' . "\n";
4758                 echo '(skin type: ' . Entity::hsc($friendlyName) . ")\n";
4759                 
4760                 if ( !array_key_exists($type, $skin_types) || !$skin_types[$type] )
4761                 {
4762                         help('skinpartspecial');
4763                 }
4764                 else
4765                 {
4766                         help('skinpart' . $type);
4767                 }
4768                 echo "<br />\n";
4769                 
4770                 echo "<textarea class=\"skinedit\" tabindex=\"10\" rows=\"20\" cols=\"80\" name=\"content\">\n";
4771                 echo Entity::hsc($skin->getContent($type)) . "\n";
4772                 echo "</textarea>\n";
4773                 
4774                 echo "<br />\n";
4775                 echo '<input type="submit" tabindex="20" value="' . _SKIN_UPDATE_BTN . '" onclick="return checkSubmit();" />' . "\n";
4776                 echo '<input type="reset" value="' . _SKIN_RESET_BTN . '" />' . "\n";
4777                 echo '(skin type: ' . Entity::hsc($friendlyName) . ")\n";
4778                 
4779                 echo "<br />\n";
4780                 echo "<br />\n";
4781                 echo _SKIN_ALLOWEDVARS;
4782                 
4783                 $actions = $skin->getAllowedActionsForType($type);
4784                 
4785                 sort($actions);
4786                 
4787                 while ( $current = array_shift($actions) )
4788                 {
4789                         // skip deprecated vars
4790                         if ( in_array($current, array('ifcat', 'imagetext', 'vars')) )
4791                         {
4792                                 continue;
4793                         }
4794                         
4795                         echo helplink("skinvar-{$current}") . "{$current}</a>\n";
4796                         
4797                         if ( count($actions) != 0 )
4798                         {
4799                                 echo ", ";
4800                         }
4801                 }
4802                 
4803                 echo "<br />\n";
4804                 echo "<br />\n";
4805                 echo _SKINEDIT_ALLOWEDBLOGS;
4806                 
4807                 $query = 'SELECT bshortname, bname FROM '.sql_table('blog');
4808                 showlist($query, 'table', array('content'=>'shortblognames'));
4809                 
4810                 echo "<br />\n";
4811                 echo _SKINEDIT_ALLOWEDTEMPLATESS;
4812                 
4813                 $query = 'SELECT tdname as name, tddesc as description FROM '.sql_table('template_desc');
4814                 showlist($query, 'table', array('content'=>'shortnames'));
4815                 
4816                 echo "</div>\n";
4817                 echo "</form>\n";
4818                 
4819                 $this->pagefoot();
4820                 
4821                 return;
4822         }
4823
4824     /**
4825      * @todo document this
4826      */
4827     function action_skinupdate() {
4828         global $member;
4829
4830         $skinid = intRequestVar('skinid');
4831         $content = trim(postVar('content'));
4832         $type = postVar('type');
4833
4834         $member->isAdmin() or $this->disallow();
4835
4836         $skin = new SKIN($skinid);
4837         $skin->update($type, $content);
4838
4839         $this->action_skinedittype(_SKIN_UPDATED);
4840     }
4841
4842     /**
4843      * @todo document this
4844      */
4845     function action_skindelete() {
4846         global $member, $manager, $CONF;
4847
4848         $skinid = intRequestVar('skinid');
4849
4850         $member->isAdmin() or $this->disallow();
4851
4852         // don't allow default skin to be deleted
4853         if ($skinid == $CONF['BaseSkin'])
4854             $this->error(_ERROR_DEFAULTSKIN);
4855
4856         // don't allow deletion of default skins for blogs
4857         $query = 'SELECT bname FROM '.sql_table('blog').' WHERE bdefskin=' . $skinid;
4858         $r = DB::getValue($query);
4859         if ( $r )
4860             $this->error(_ERROR_SKINDEFDELETE . Entity::hsc($r));
4861
4862         $this->pagehead();
4863
4864         $skin = new SKIN($skinid);
4865         $name = $skin->getName();
4866         $desc = $skin->getDescription();
4867
4868         ?>
4869             <h2><?php echo _DELETE_CONFIRM ?></h2>
4870
4871             <p>
4872                 <?php echo _CONFIRMTXT_SKIN ?><b><?php echo Entity::hsc($name) ?></b> (<?php echo  Entity::hsc($desc) ?>)
4873             </p>
4874
4875             <form method="post" action="index.php"><div>
4876                 <input type="hidden" name="action" value="skindeleteconfirm" />
4877                 <?php $manager->addTicketHidden() ?>
4878                 <input type="hidden" name="skinid" value="<?php echo  $skinid ?>" />
4879                 <input type="submit" tabindex="10" value="<?php echo _DELETE_CONFIRM_BTN ?>" />
4880             </div></form>
4881         <?php
4882         $this->pagefoot();
4883     }
4884
4885     /**
4886      * @todo document this
4887      */
4888     function action_skindeleteconfirm() {
4889         global $member, $CONF, $manager;
4890
4891         $skinid = intRequestVar('skinid');
4892
4893         $member->isAdmin() or $this->disallow();
4894
4895         // don't allow default skin to be deleted
4896         if ($skinid == $CONF['BaseSkin'])
4897             $this->error(_ERROR_DEFAULTSKIN);
4898
4899         // don't allow deletion of default skins for blogs
4900         $query = 'SELECT bname FROM '.sql_table('blog').' WHERE bdefskin=' . $skinid;
4901         $r = DB::getValue($query);
4902         if ($r)
4903             $this->error(_ERROR_SKINDEFDELETE .$r);
4904
4905         $manager->notify('PreDeleteSkin', array('skinid' => $skinid));
4906
4907         // 1. delete description
4908         DB::execute('DELETE FROM '.sql_table('skin_desc').' WHERE sdnumber=' . $skinid);
4909
4910         // 2. delete parts
4911         DB::execute('DELETE FROM '.sql_table('skin').' WHERE sdesc=' . $skinid);
4912
4913         $manager->notify('PostDeleteSkin', array('skinid' => $skinid));
4914
4915         $this->action_skinoverview();
4916     }
4917         
4918         /**
4919          * Admin::action_skinremovetype()
4920          *
4921          * @param       void
4922          * @return      void
4923          */
4924         public function action_skinremovetype()
4925         {
4926                 global $member, $manager, $CONF;
4927                 
4928                 $skinid = intRequestVar('skinid');
4929                 $skintype = requestVar('type');
4930                 
4931                 if ( !isValidShortName($skintype) )
4932                 {
4933                         $this->error(_ERROR_SKIN_PARTS_SPECIAL_DELETE);
4934                 }
4935                 
4936                 $member->isAdmin() or $this->disallow();
4937                 
4938                 // don't allow default skinparts to be deleted
4939                 $skin = new Skin($skinid);
4940                 $default_skin_types = $skin->getDefaultTypes();
4941                 if ( array_key_exists($skintype, $default_skin_types) )
4942                 {
4943                         $this->error(_ERROR_SKIN_PARTS_SPECIAL_DELETE);
4944                 }
4945                 
4946                 $name = $skin->getName();
4947                 $desc = $skin->getDescription();
4948                 
4949                 $this->pagehead();
4950                 
4951                 echo '<h2>' . _DELETE_CONFIRM . "</h2>\n";
4952                 echo "<p>\n";
4953                 echo _CONFIRMTXT_SKIN_PARTS_SPECIAL;
4954                 echo Entity::hsc($skintype);
4955                 echo  '(' . Entity::hsc($name) . ')</b>';
4956                 echo ' (' . Entity::hsc($desc) . ')';
4957                 echo "</p>\n";
4958                 
4959                 echo "<form method=\"post\" action=\"index.php\">\n";
4960                 echo "<div>\n";
4961                 echo "<input type=\"hidden\" name=\"action\" value=\"skinremovetypeconfirm\" />\n";
4962                 $manager->addTicketHidden();
4963                 echo "<input type=\"hidden\" name=\"skinid\" value=\"{$skinid}\" />\n";
4964                 echo '<input type="hidden" name="type" value="' . Entity::hsc($skintype) . '" />' . "\n";
4965                 echo '<input type="submit" tabindex="10" value="' . _DELETE_CONFIRM_BTN . '" />' . "\n";
4966                 echo "</div>\n";
4967                 echo "</form>\n";
4968                 $this->pagefoot();
4969                 return;
4970         }
4971         
4972         /**
4973          * Admin::action_skinremovetypeconfirm()
4974          * 
4975          * @param       void
4976          * @return      void
4977          */
4978         public function action_skinremovetypeconfirm()
4979         {
4980                 global $member, $CONF, $manager;
4981                 
4982                 $skinid = intRequestVar('skinid');
4983                 $skintype = requestVar('type');
4984                 
4985                 if ( !isValidShortName($skintype) )
4986                 {
4987                         $this->error(_ERROR_SKIN_PARTS_SPECIAL_DELETE);
4988                 }
4989                 
4990                 $member->isAdmin() or $this->disallow();
4991                 
4992                 // don't allow default skinparts to be deleted
4993                 $skin = new Skin($skinid);
4994                 $default_skin_types = $skin->getDefaultTypes();
4995                 if ( array_key_exists($skintype, $default_skin_types) )
4996                 {
4997                         $this->error(_ERROR_SKIN_PARTS_SPECIAL_DELETE);
4998                 }
4999                 
5000                 $data = array(
5001                         'skinid'        => $skinid,
5002                         'skintype'      => $skintype
5003                 );
5004                 $manager->notify('PreDeleteSkinPart', $data);
5005                 
5006                 // delete part
5007                 $query = "DELETE FROM %s WHERE sdesc=%d AND stype='%s';";
5008                 $query = sprintf($query, sql_table('skin'), (integer) $skinid, $skintype);
5009                 DB::execute($query);
5010                 
5011                 $data = array(
5012                         'skinid'        => $skinid,
5013                         'skintype'      => $skintype
5014                 );
5015                 $manager->notify('PostDeleteSkinPart', $data);
5016                 
5017                 $this->action_skinedit();
5018                 return;
5019         }
5020         
5021     /**
5022      * @todo document this
5023      */
5024     function action_skinclone() {
5025         global $member;
5026
5027         $skinid = intRequestVar('skinid');
5028
5029         $member->isAdmin() or $this->disallow();
5030
5031         // 1. read skin to clone
5032         $skin = new SKIN($skinid);
5033
5034         $name = "clone_" . $skin->getName();
5035
5036         // if a skin with that name already exists:
5037         if (Skin::exists($name)) {
5038             $i = 1;
5039             while (Skin::exists($name . $i))
5040                 $i++;
5041             $name .= $i;
5042         }
5043
5044         // 2. create skin desc
5045         $newid = Skin::createNew(
5046             $name,
5047             $skin->getDescription(),
5048             $skin->getContentType(),
5049             $skin->getIncludeMode(),
5050             $skin->getIncludePrefix()
5051         );
5052         
5053         $query = "SELECT stype FROM " . sql_table('skin') . " WHERE sdesc = " . $skinid;
5054         $res = DB::getResult($query);
5055         foreach ( $res as $row) {
5056             $this->skinclonetype($skin, $newid, $row['stype']);
5057         }
5058
5059         $this->action_skinoverview();
5060
5061     }
5062
5063         /**
5064          * Admin::skinclonetype()
5065          * 
5066          * @param       String  $skin   Skin object
5067          * @param       Integer $newid  ID for this clone
5068          * @param       String  $type   type of skin
5069          * @return      Void
5070          */
5071         function skinclonetype($skin, $newid, $type)
5072         {
5073                 $newid = intval($newid);
5074                 $content = $skin->getContent($type);
5075                 
5076                 if ( $content )
5077                 {
5078                         $query = "INSERT INTO %s (sdesc, scontent, stype) VALUES (%d, '%s', '%s')";
5079                         $query = sprintf($query, sql_table('skin'), (integer) $newid, $content, $type);
5080                         DB::execute($query);
5081                 }
5082                 return;
5083         }
5084         
5085         /**
5086          * Admin::action_settingsedit()
5087          * 
5088          * @param       Void
5089          * @return      Void
5090          */
5091         function action_settingsedit() {
5092                 global $member, $manager, $CONF, $DIR_NUCLEUS, $DIR_MEDIA;
5093
5094                 $member->isAdmin() or $this->disallow();
5095
5096                 $this->pagehead();
5097
5098                 echo '<p><a href="index.php?action=manage">(',_BACKTOMANAGE,')</a></p>';
5099                 ?>
5100
5101                 <h2><?php echo _SETTINGS_TITLE ?></h2>
5102
5103                 <form action="index.php" method="post">
5104                 <div>
5105
5106                 <input type="hidden" name="action" value="settingsupdate" />
5107                 <?php $manager->addTicketHidden() ?>
5108
5109                 <table><tr>
5110                         <th colspan="2"><?php echo _SETTINGS_SUB_GENERAL ?></th>
5111                 </tr><tr>
5112                         <td><?php echo _SETTINGS_DEFBLOG ?> <?php help('defaultblog'); ?></td>
5113                         <td>
5114                                 <?php
5115                                         $query =  'SELECT bname as text, bnumber as value'
5116                                                    . ' FROM '.sql_table('blog');
5117                                         $template['name'] = 'DefaultBlog';
5118                                         $template['selected'] = $CONF['DefaultBlog'];
5119                                         $template['tabindex'] = 10;
5120                                         showlist($query,'select',$template);
5121                                 ?>
5122                         </td>
5123                 </tr><tr>
5124                         <td><?php echo _SETTINGS_BASESKIN ?> <?php help('baseskin'); ?></td>
5125                         <td>
5126                                 <?php
5127                                         $query =  'SELECT sdname as text, sdnumber as value'
5128                                                    . ' FROM '.sql_table('skin_desc');
5129                                         $template['name'] = 'BaseSkin';
5130                                         $template['selected'] = $CONF['BaseSkin'];
5131                                         $template['tabindex'] = 1;
5132                                         showlist($query,'select',$template);
5133                                 ?>
5134                         </td>
5135                 </tr><tr>
5136                         <td><?php echo _SETTINGS_ADMINMAIL ?></td>
5137                         <td><input name="AdminEmail" tabindex="10010" size="40" value="<?php echo  Entity::hsc($CONF['AdminEmail']) ?>" /></td>
5138                 </tr><tr>
5139                         <td><?php echo _SETTINGS_SITENAME ?></td>
5140                         <td><input name="SiteName" tabindex="10020" size="40" value="<?php echo  Entity::hsc($CONF['SiteName']) ?>" /></td>
5141                 </tr><tr>
5142                         <td><?php echo _SETTINGS_SITEURL ?></td>
5143                         <td><input name="IndexURL" tabindex="10030" size="40" value="<?php echo  Entity::hsc($CONF['IndexURL']) ?>" /></td>
5144                 </tr><tr>
5145                         <td><?php echo _SETTINGS_ADMINURL ?></td>
5146                         <td><input name="AdminURL" tabindex="10040" size="40" value="<?php echo  Entity::hsc($CONF['AdminURL']) ?>" /></td>
5147                 </tr><tr>
5148                         <td><?php echo _SETTINGS_PLUGINURL ?> <?php help('pluginurl'); ?></td>
5149                         <td><input name="PluginURL" tabindex="10045" size="40" value="<?php echo  Entity::hsc($CONF['PluginURL']) ?>" /></td>
5150                 </tr><tr>
5151                         <td><?php echo _SETTINGS_SKINSURL ?> <?php help('skinsurl'); ?></td>
5152                         <td><input name="SkinsURL" tabindex="10046" size="40" value="<?php echo  Entity::hsc($CONF['SkinsURL']) ?>" /></td>
5153                 </tr><tr>
5154                         <td><?php echo _SETTINGS_ACTIONSURL ?> <?php help('actionurl'); ?></td>
5155                         <td><input name="ActionURL" tabindex="10047" size="40" value="<?php echo  Entity::hsc($CONF['ActionURL']) ?>" /></td>
5156                 </tr><tr>
5157                         <td><?php echo _SETTINGS_LOCALE ?> <?php help('locale'); ?>
5158                         </td>
5159                         <td>
5160                                 <select name="Locale" tabindex="10050">
5161                         <?php
5162                                 $locales = i18n::get_available_locale_list();
5163                                 if ( !i18n::get_current_locale() || !in_array(i18n::get_current_locale(), $locales) )
5164                                 {
5165                                         echo "<option value=\"\" selected=\"selected\">en_Latn_US</option>\n";
5166                                 }
5167                                 else
5168                                 {
5169                                         echo "<option value=\"\">en_Latn_US</option>\n";
5170                                 }
5171                                 
5172                                 foreach ( $locales as $locale )
5173                                 {
5174                                         if ( $locale == 'en_Latn_US' )
5175                                         {
5176                                                 continue;
5177                                         }
5178                                         if ( $locale == i18n::get_current_locale() )
5179                                         {
5180                                                 echo "<option value=\"{$locale}\" selected=\"selected\">{$locale}</option>\n";
5181                                         }
5182                                         else
5183                                         {
5184                                                 echo "<option value=\"{$locale}\">{$locale}</option>\n";
5185                                         }
5186                                 }
5187                         ?>
5188                         </select>
5189
5190                         </td>
5191                 </tr><tr>
5192                         <td><?php echo _SETTINGS_DISABLESITE ?> <?php help('disablesite'); ?>
5193                         </td>
5194                         <td><?php $this->input_yesno('DisableSite',$CONF['DisableSite'],10060); ?>
5195                                         <br />
5196                                 <?php echo _SETTINGS_DISABLESITEURL ?> <input name="DisableSiteURL" tabindex="10070" size="40" value="<?php echo  Entity::hsc($CONF['DisableSiteURL']) ?>" />
5197                         </td>
5198                 </tr><tr>
5199                         <td><?php echo _SETTINGS_DIRS ?></td>
5200                         <td><?php echo  Entity::hsc($DIR_NUCLEUS) ?>
5201                                 <i><?php echo _SETTINGS_SEECONFIGPHP ?></i></td>
5202                 </tr><tr>
5203                         <td><?php echo _SETTINGS_DBLOGIN ?></td>
5204                         <td><i><?php echo _SETTINGS_SEECONFIGPHP ?></i></td>
5205                 </tr><tr>
5206                         <td>
5207                         <?php
5208                                 echo _SETTINGS_JSTOOLBAR
5209                                 /* =_SETTINGS_DISABLEJS
5210
5211                                         I temporary changed the meaning of DisableJsTools, until I can find a good
5212                                         way to select the javascript version to use
5213
5214                                         now, its:
5215                                                 0 : IE
5216                                                 1 : all javascript disabled
5217                                                 2 : 'simpler' javascript (for mozilla/opera/mac)
5218                                 */
5219                            ?>
5220                         </td>
5221                         <td><?php /* $this->input_yesno('DisableJsTools',$CONF['DisableJsTools'],10075); */ ?>
5222                                 <select name="DisableJsTools" tabindex="10075">
5223                         <?php                              $extra = ($CONF['DisableJsTools'] == 1) ? 'selected="selected"' : '';
5224                                         echo "<option $extra value='1'>",_SETTINGS_JSTOOLBAR_NONE,"</option>";
5225                                         $extra = ($CONF['DisableJsTools'] == 2) ? 'selected="selected"' : '';
5226                                         echo "<option $extra value='2'>",_SETTINGS_JSTOOLBAR_SIMPLE,"</option>";
5227                                         $extra = ($CONF['DisableJsTools'] == 0) ? 'selected="selected"' : '';
5228                                         echo "<option $extra value='0'>",_SETTINGS_JSTOOLBAR_FULL,"</option>";
5229                         ?>
5230                                 </select>
5231                         </td>
5232                 </tr><tr>
5233                         <td><?php echo _SETTINGS_URLMODE ?> <?php help('urlmode'); ?></td>
5234                                            <td><?php
5235
5236                                            $this->input_yesno('URLMode',$CONF['URLMode'],10077,
5237                                                           'normal','pathinfo',_SETTINGS_URLMODE_NORMAL,_SETTINGS_URLMODE_PATHINFO);
5238
5239                                            echo ' ', _SETTINGS_URLMODE_HELP;
5240
5241                                                          ?>
5242
5243                                            </td>
5244                 </tr><tr>
5245                         <td><?php echo _SETTINGS_DEBUGVARS ?> <?php help('debugvars'); ?></td>
5246                                            <td><?php
5247
5248                                                 $this->input_yesno('DebugVars',$CONF['DebugVars'],10078);
5249
5250                                                          ?>
5251
5252                                            </td>
5253                 </tr><tr>
5254                         <td><?php echo _SETTINGS_DEFAULTLISTSIZE ?> <?php help('defaultlistsize'); ?></td>
5255                         <td>
5256                         <?php
5257                                 if (!array_key_exists('DefaultListSize',$CONF)) {
5258                                         DB::execute("INSERT INTO ".sql_table('config')." VALUES ('DefaultListSize', '10')");
5259                                         $CONF['DefaultListSize'] = 10;
5260                                 }
5261                         ?>
5262                                 <input name="DefaultListSize" tabindex="10079" size="40" value="<?php echo  Entity::hsc((intval($CONF['DefaultListSize']) < 1 ? '10' : $CONF['DefaultListSize'])) ?>" />
5263                         </td>
5264                 </tr><tr>
5265                         <td><?php echo _SETTINGS_ADMINCSS ?> 
5266                         </td>
5267                         <td>
5268
5269                                 <select name="AdminCSS" tabindex="10080">
5270                                 <?php                      // show a dropdown list of all available admin css files
5271                                 global $DIR_NUCLEUS;
5272                                 
5273                                 $dirhandle = opendir($DIR_NUCLEUS."styles/");
5274
5275                                 while ($filename = readdir($dirhandle) )
5276                                 {
5277
5278                                         # replaced ereg() below with preg_match(). ereg* functions are deprecated in PHP 5.3.0
5279                                         # original ereg: ereg("^(.*)\.php$",$filename,$matches)
5280
5281                                         if (preg_match('#^admin_(.*)\.css$#', $filename, $matches) )
5282                                         {
5283
5284                                                 $name = $matches[1];
5285                                                 echo "<option value=\"$name\"";
5286
5287                                                 if ($name == $CONF['AdminCSS'])
5288                                                 {
5289                                                         echo " selected=\"selected\"";
5290                                                 }
5291
5292                                                 echo ">$name</option>";
5293
5294                                         }
5295
5296                                 }
5297
5298                                 closedir($dirhandle);
5299
5300                                 ?>
5301                                 </select>
5302
5303                         </td>
5304                 </tr><tr>
5305                         <th colspan="2"><?php echo _SETTINGS_MEDIA ?> <?php help('media'); ?></th>
5306                 </tr><tr>
5307                         <td><?php echo _SETTINGS_MEDIADIR ?></td>
5308                         <td><?php echo  Entity::hsc($DIR_MEDIA) ?>
5309                                 <i><?php echo _SETTINGS_SEECONFIGPHP ?></i>
5310                                 <?php                              if (!is_dir($DIR_MEDIA))
5311                                                 echo "<br /><b>" . _WARNING_NOTADIR . "</b>";
5312                                         if (!is_readable($DIR_MEDIA))
5313                                                 echo "<br /><b>" . _WARNING_NOTREADABLE . "</b>";
5314                                         if (!is_writeable($DIR_MEDIA))
5315                                                 echo "<br /><b>" . _WARNING_NOTWRITABLE . "</b>";
5316                                 ?>
5317                         </td>
5318                 </tr><tr>
5319                         <td><?php echo _SETTINGS_MEDIAURL ?></td>
5320                         <td>
5321                                 <input name="MediaURL" tabindex="10090" size="40" value="<?php echo  Entity::hsc($CONF['MediaURL']) ?>" />
5322                         </td>
5323                 </tr><tr>
5324                         <td><?php echo _SETTINGS_ALLOWUPLOAD ?></td>
5325                         <td><?php $this->input_yesno('AllowUpload',$CONF['AllowUpload'],10090); ?></td>
5326                 </tr><tr>
5327                         <td><?php echo _SETTINGS_ALLOWUPLOADTYPES ?></td>
5328                         <td>
5329                                 <input name="AllowedTypes" tabindex="10100" size="40" value="<?php echo  Entity::hsc($CONF['AllowedTypes']) ?>" />
5330                         </td>
5331                 </tr><tr>
5332                         <td><?php echo _SETTINGS_MAXUPLOADSIZE ?></td>
5333                         <td>
5334                                 <input name="MaxUploadSize" tabindex="10105" size="40" value="<?php echo  Entity::hsc($CONF['MaxUploadSize']) ?>" />
5335                         </td>
5336                 </tr><tr>
5337                         <td><?php echo _SETTINGS_MEDIAPREFIX ?></td>
5338                         <td><?php $this->input_yesno('MediaPrefix',$CONF['MediaPrefix'],10110); ?></td>
5339
5340                 </tr><tr>
5341                         <th colspan="2"><?php echo _SETTINGS_MEMBERS ?></th>
5342                 </tr><tr>
5343                         <td><?php echo _SETTINGS_CHANGELOGIN ?></td>
5344                         <td><?php $this->input_yesno('AllowLoginEdit',$CONF['AllowLoginEdit'],10120); ?></td>
5345                 </tr><tr>
5346                         <td><?php echo _SETTINGS_ALLOWCREATE ?>
5347                                 <?php help('allowaccountcreation'); ?>
5348                         </td>
5349                         <td><?php $this->input_yesno('AllowMemberCreate',$CONF['AllowMemberCreate'],10130); ?>
5350                         </td>
5351                 </tr><tr>
5352                         <td><?php echo _SETTINGS_NEWLOGIN ?> <?php help('allownewmemberlogin'); ?>
5353                                 <br /><?php echo _SETTINGS_NEWLOGIN2 ?>
5354                         </td>
5355                         <td><?php $this->input_yesno('NewMemberCanLogon',$CONF['NewMemberCanLogon'],10140); ?>
5356                         </td>
5357                 </tr><tr>
5358                         <td><?php echo _SETTINGS_MEMBERMSGS ?>
5359                                 <?php help('messageservice'); ?>
5360                         </td>
5361                         <td><?php $this->input_yesno('AllowMemberMail',$CONF['AllowMemberMail'],10150); ?>
5362                         </td>
5363                 </tr><tr>
5364                         <td><?php echo _SETTINGS_NONMEMBERMSGS ?>
5365                                 <?php help('messageservice'); ?>
5366                         </td>
5367                         <td><?php $this->input_yesno('NonmemberMail',$CONF['NonmemberMail'],10155); ?>
5368                         </td>
5369                 </tr><tr>
5370                         <td><?php echo _SETTINGS_PROTECTMEMNAMES ?>
5371                                 <?php help('protectmemnames'); ?>
5372                         </td>
5373                         <td><?php $this->input_yesno('ProtectMemNames',$CONF['ProtectMemNames'],10156); ?>
5374                         </td>
5375
5376
5377
5378                 </tr><tr>
5379                         <th colspan="2"><?php echo _SETTINGS_COOKIES_TITLE ?> <?php help('cookies'); ?></th>
5380                 </tr><tr>
5381                         <td><?php echo _SETTINGS_COOKIEPREFIX ?></td>
5382                         <td><input name="CookiePrefix" tabindex="10159" size="40" value="<?php echo  Entity::hsc($CONF['CookiePrefix']) ?>" /></td>
5383                 </tr><tr>
5384                         <td><?php echo _SETTINGS_COOKIEDOMAIN ?></td>
5385                         <td><input name="CookieDomain" tabindex="10160" size="40" value="<?php echo  Entity::hsc($CONF['CookieDomain']) ?>" /></td>
5386                 </tr><tr>
5387                         <td><?php echo _SETTINGS_COOKIEPATH ?></td>
5388                         <td><input name="CookiePath" tabindex="10170" size="40" value="<?php echo  Entity::hsc($CONF['CookiePath']) ?>" /></td>
5389                 </tr><tr>
5390                         <td><?php echo _SETTINGS_COOKIESECURE ?></td>
5391                         <td><?php $this->input_yesno('CookieSecure',$CONF['CookieSecure'],10180); ?></td>
5392                 </tr><tr>
5393                         <td><?php echo _SETTINGS_COOKIELIFE ?></td>
5394                         <td><?php $this->input_yesno('SessionCookie',$CONF['SessionCookie'],10190,
5395                                                           1,0,_SETTINGS_COOKIESESSION,_SETTINGS_COOKIEMONTH); ?>
5396                         </td>
5397                 </tr><tr>
5398                         <td><?php echo _SETTINGS_LASTVISIT ?></td>
5399                         <td><?php $this->input_yesno('LastVisit',$CONF['LastVisit'],10200); ?></td>
5400
5401
5402
5403                 </tr><tr>
5404                         <th colspan="2"><?php echo _SETTINGS_UPDATE ?></th>
5405                 </tr><tr>
5406                         <td><?php echo _SETTINGS_UPDATE ?></td>
5407                         <td><input type="submit" tabindex="10210" value="<?php echo _SETTINGS_UPDATE_BTN ?>" onclick="return checkSubmit();" /></td>
5408                 </tr></table>
5409
5410                 </div>
5411                 </form>
5412
5413                 <?php
5414                         echo '<h2>',_PLUGINS_EXTRA,'</h2>';
5415
5416                         $manager->notify(
5417                                 'GeneralSettingsFormExtras',
5418                                 array()
5419                         );
5420
5421                 $this->pagefoot();
5422         }
5423         
5424         /**
5425          * Admin::action_settingsupdate()
5426          * Update $CONFIG and redirect
5427          * 
5428          * @param       void
5429          * @return      void
5430          */
5431         function action_settingsupdate() {
5432                 global $member, $CONF;
5433                 
5434                 $member->isAdmin() or $this->disallow();
5435                 
5436                 // check if email address for admin is valid
5437                 if ( !NOTIFICATION::address_validation(postVar('AdminEmail')) )
5438                 {
5439                         $this->error(_ERROR_BADMAILADDRESS);
5440                 }
5441                 
5442                 // save settings
5443                 $this->updateConfig('DefaultBlog',        postVar('DefaultBlog'));
5444                 $this->updateConfig('BaseSkin',          postVar('BaseSkin'));
5445                 $this->updateConfig('IndexURL',          postVar('IndexURL'));
5446                 $this->updateConfig('AdminURL',          postVar('AdminURL'));
5447                 $this->updateConfig('PluginURL',                postVar('PluginURL'));
5448                 $this->updateConfig('SkinsURL',          postVar('SkinsURL'));
5449                 $this->updateConfig('ActionURL',                postVar('ActionURL'));
5450                 $this->updateConfig('Locale',              postVar('Locale'));
5451                 $this->updateConfig('AdminEmail',          postVar('AdminEmail'));
5452                 $this->updateConfig('SessionCookie',    postVar('SessionCookie'));
5453                 $this->updateConfig('AllowMemberCreate',postVar('AllowMemberCreate'));
5454                 $this->updateConfig('AllowMemberMail',  postVar('AllowMemberMail'));
5455                 $this->updateConfig('NonmemberMail',    postVar('NonmemberMail'));
5456                 $this->updateConfig('ProtectMemNames',  postVar('ProtectMemNames'));
5457                 $this->updateConfig('SiteName',          postVar('SiteName'));
5458                 $this->updateConfig('NewMemberCanLogon',postVar('NewMemberCanLogon'));
5459                 $this->updateConfig('DisableSite',        postVar('DisableSite'));
5460                 $this->updateConfig('DisableSiteURL',   postVar('DisableSiteURL'));
5461                 $this->updateConfig('LastVisit',                postVar('LastVisit'));
5462                 $this->updateConfig('MediaURL',          postVar('MediaURL'));
5463                 $this->updateConfig('AllowedTypes',      postVar('AllowedTypes'));
5464                 $this->updateConfig('AllowUpload',        postVar('AllowUpload'));
5465                 $this->updateConfig('MaxUploadSize',    postVar('MaxUploadSize'));
5466                 $this->updateConfig('MediaPrefix',        postVar('MediaPrefix'));
5467                 $this->updateConfig('AllowLoginEdit',   postVar('AllowLoginEdit'));
5468                 $this->updateConfig('DisableJsTools',   postVar('DisableJsTools'));
5469                 $this->updateConfig('CookieDomain',      postVar('CookieDomain'));
5470                 $this->updateConfig('CookiePath',          postVar('CookiePath'));
5471                 $this->updateConfig('CookieSecure',      postVar('CookieSecure'));
5472                 $this->updateConfig('URLMode',            postVar('URLMode'));
5473                 $this->updateConfig('CookiePrefix',      postVar('CookiePrefix'));
5474                 $this->updateConfig('DebugVars',                        postVar('DebugVars'));
5475                 $this->updateConfig('DefaultListSize',            postVar('DefaultListSize'));
5476                 $this->updateConfig('AdminCSS',           postVar('AdminCSS'));
5477                 
5478                 // load new config and redirect (this way, the new locale will be used is necessary)
5479                 // note that when changing cookie settings, this redirect might cause the user
5480                 // to have to log in again.
5481                 getConfig();
5482                 redirect($CONF['AdminURL'] . '?action=manage');
5483                 exit;
5484         }
5485
5486         /**
5487          * Admin::action_systemoverview()
5488          * Output system overview
5489          * 
5490          * @param       void
5491          * @return      void
5492          */
5493         function action_systemoverview()
5494         {
5495                 global $member, $nucleus, $CONF;
5496                 
5497                 $this->pagehead();
5498                 
5499                 echo '<h2>' . _ADMIN_SYSTEMOVERVIEW_HEADING . "</h2>\n";
5500                 
5501                 if ( $member->isLoggedIn() && $member->isAdmin() )
5502                 {
5503                         // Information about the used PHP and MySQL installation
5504                         echo '<h3>' . _ADMIN_SYSTEMOVERVIEW_PHPANDMYSQL . "</h3>\n\n";
5505                         
5506                         // Version of PHP MySQL
5507                         echo '<table frame="box" rules="all" summary="' . _ADMIN_SYSTEMOVERVIEW_VERSIONS . "\" class=\"systemoverview\">\n";
5508                         echo "<thead>\n";
5509                         echo "<tr>\n";
5510                         echo '<th colspan="2">' . _ADMIN_SYSTEMOVERVIEW_VERSIONS . "</th>\n";
5511                         echo "</tr>\n";
5512                         echo "</thead>\n";
5513                         echo "<tbody>\n";
5514                         echo "<tr>\n";
5515                         echo '<td>' . _ADMIN_SYSTEMOVERVIEW_PHPVERSION . "</td>\n";
5516                         echo '<td>' . phpversion() . "</td>\n";
5517                         echo "</tr>\n";
5518                         echo "<tr>\n";
5519                         echo '<td>' . _ADMIN_SYSTEMOVERVIEW_MYSQLVERSION . "</td>\n";
5520                         echo '<td>' . DB::getAttribute(PDO::ATTR_SERVER_VERSION) . ' (' . DB::getAttribute(PDO::ATTR_CLIENT_VERSION) . ')' . "</td>\n";
5521                         echo "</tr>\n";
5522                         echo "</tbody>\n";
5523                         echo "</table>\n\n";
5524                         
5525                         // Important PHP settings
5526                         echo '<table frame="box" rules="all" summary="' . _ADMIN_SYSTEMOVERVIEW_SETTINGS . "\" class=\"systemoverview\">\n";
5527                         echo "<thead>\n";
5528                         echo "<tr>\n";
5529                         echo '<th colspan="2">' . _ADMIN_SYSTEMOVERVIEW_SETTINGS . "</th>\n";
5530                         echo "</tr>\n";
5531                         echo "</thead>\n";
5532                         echo "<tbody>\n";
5533                         echo "<tr>\n";
5534                         echo '<td>magic_quotes_gpc' . "</td>\n";
5535                         $mqg = get_magic_quotes_gpc() ? 'On' : 'Off';
5536                         echo '<td>' . $mqg . "</td>\n";
5537                         echo "</tr>\n";
5538                         echo "<tr>\n";
5539                         echo '<td>magic_quotes_runtime' . "</td>\n";
5540                         $mqr = get_magic_quotes_runtime() ? 'On' : 'Off';
5541                         echo '<td>' . $mqr . "</td>\n";
5542                         echo "</tr>\n";
5543                         echo "<tr>\n";
5544                         echo '<td>register_globals' . "</td>\n";
5545                         $rg = ini_get('register_globals') ? 'On' : 'Off';
5546                         echo '<td>' . $rg . "</td>\n";
5547                         echo "</tr>\n";
5548                         echo "</tbody>\n";
5549                         echo "</table>\n\n";
5550                         
5551                         // Information about GD library
5552                         $gdinfo = gd_info();
5553                         echo '<table frame="box" rules="all" summary="' . _ADMIN_SYSTEMOVERVIEW_GDLIBRALY . "\" class=\"systemoverview\">\n";
5554                         echo "<thead>\n";
5555                         echo "<tr>\n";
5556                         echo '<th colspan="2">' . _ADMIN_SYSTEMOVERVIEW_GDLIBRALY . "</th>\n";
5557                         echo "</tr>\n";
5558                         echo "</thead>\n";
5559                         echo "<tbody>\n";
5560                         foreach ( $gdinfo as $key=>$value )
5561                         {
5562                                 if ( is_bool($value) )
5563                                 {
5564                                         $value = $value ? _ADMIN_SYSTEMOVERVIEW_ENABLE : _ADMIN_SYSTEMOVERVIEW_DISABLE;
5565                                 }
5566                                 else
5567                                 {
5568                                         $value = Entity::hsc($value);
5569                                 }
5570                                 echo "<tr>\n";
5571                                 echo '<td>' . $key . "</td>\n";
5572                                 echo '<td>' . $value . "</td>\n";
5573                                 echo "</tr>\n";
5574                         }
5575                         echo "</tbody>\n";
5576                         echo "</table>\n\n";
5577
5578                         // Check if special modules are loaded
5579                         ob_start();
5580                         phpinfo(INFO_MODULES);
5581                         $im = ob_get_contents();
5582                         ob_clean();
5583                         echo '<table frame="box" rules="all" summary="' . _ADMIN_SYSTEMOVERVIEW_MODULES . "\" class=\"systemoverview\">\n";
5584                         echo "<thead>\n";
5585                         echo "<tr>";
5586                         echo '<th colspan="2">' . _ADMIN_SYSTEMOVERVIEW_MODULES . "</th>\n";
5587                         echo "</tr>\n";
5588                         echo "<tbody>\n";
5589                         echo "<tr>\n";
5590                         echo '<td>mod_rewrite' . "</td>\n";
5591                         $modrewrite = (strstr($im, 'mod_rewrite') != '') ?
5592                                                 _ADMIN_SYSTEMOVERVIEW_ENABLE :
5593                                                 _ADMIN_SYSTEMOVERVIEW_DISABLE;
5594                         echo '<td>' . $modrewrite . "</td>\n";
5595                         echo "</tr>\n";
5596                         echo "</tbody>\n";
5597                         echo "</table>\n\n";
5598
5599                         // Information about the used Nucleus CMS
5600                         echo '<h3>' . _ADMIN_SYSTEMOVERVIEW_NUCLEUSSYSTEM . "</h3>\n";
5601                         global $nucleus;
5602                         $nv = getNucleusVersion() / 100 . '(' . $nucleus['version'] . ')';
5603                         $np = getNucleusPatchLevel();
5604                         echo "<table frame=\"box\" rules=\"all\" summary=\"Nucleus CMS\" class=\"systemoverview\" class=\"systemoverview\">\n";
5605                         echo "<thead>\n";
5606                         echo "<tr>\n";
5607                         echo '<th colspan="2">Nucleus CMS' . "</th>\n";
5608                         echo "</tr>\n";
5609                         echo "</thead>\n";
5610                         echo "<tbody>\n";
5611                         echo "<tr>\n";
5612                         echo '<td>' . _ADMIN_SYSTEMOVERVIEW_NUCLEUSVERSION . "</td>\n";
5613                         echo '<td>' . $nv . "</td>\n";
5614                         echo "</tr>\n";
5615                         echo "<tr>\n";
5616                         echo '<td>' . _ADMIN_SYSTEMOVERVIEW_NUCLEUSPATCHLEVEL . "</td>\n";
5617                         echo '<td>' . $np . "</td>\n";
5618                         echo "</tr>\n";
5619                         echo "</tbody>\n";
5620                         echo "</table>\n\n";
5621
5622                         // Important settings of the installation
5623                         echo '<table frame="box" rules="all" summary="' . _ADMIN_SYSTEMOVERVIEW_NUCLEUSSETTINGS . "\" class=\"systemoverview\">\n";
5624                         echo "<thead>\n";
5625                         echo "<tr>\n";
5626                         echo '<th colspan="2">' . _ADMIN_SYSTEMOVERVIEW_NUCLEUSSETTINGS . "</th>\n";
5627                         echo "</tr>\n";
5628                         echo "</thead>\n";
5629                         echo "<tbody>\n";
5630                         echo "<tr>\n";
5631                         echo '<td>' . '$CONF[' . "'Self']</td>\n";
5632                         echo '<td>' . $CONF['Self'] . "</td>\n";
5633                         echo "</tr>\n";
5634                         echo "<tr>\n";
5635                         echo '<td>' . '$CONF[' . "'ItemURL']</td>\n";
5636                         echo '<td>' . $CONF['ItemURL'] . "</td>\n";
5637                         echo "</tr>\n";
5638                         echo "<tr>\n";
5639                         echo '<td>' . '$CONF[' . "'alertOnHeadersSent']</td>\n";
5640                         $ohs = $CONF['alertOnHeadersSent'] ?
5641                                                 _ADMIN_SYSTEMOVERVIEW_ENABLE :
5642                                                 _ADMIN_SYSTEMOVERVIEW_DISABLE;
5643                         echo '<td>' . $ohs . "</td>\n";
5644                         echo "</tr>\n";
5645                         echo "<tr>\n";
5646                         echo "<td>i18n::get_current_charset()</td>\n";
5647                         echo '<td>' . i18n::get_current_charset() . "</td>\n";
5648                         echo "</tr>\n";
5649                         echo "</tbody>\n";
5650                         echo "</table>\n\n";
5651
5652                         // Link to the online version test at the Nucleus CMS website
5653                         echo '<h3>' . _ADMIN_SYSTEMOVERVIEW_VERSIONCHECK . "</h3>\n";
5654                         if ( $nucleus['codename'] != '')
5655                         {
5656                                 $codenamestring = ' &quot;' . $nucleus['codename'] . '&quot;';
5657                         }
5658                         else
5659                         {
5660                                 $codenamestring = '';
5661                         }
5662                         echo _ADMIN_SYSTEMOVERVIEW_VERSIONCHECK_TXT;
5663                         $checkURL = sprintf(_ADMIN_SYSTEMOVERVIEW_VERSIONCHECK_URL, getNucleusVersion(), getNucleusPatchLevel());
5664                         echo '<a href="' . $checkURL . '" title="' . _ADMIN_SYSTEMOVERVIEW_VERSIONCHECK_TITLE . '">';
5665                         echo 'Nucleus CMS ' . $nv . $codenamestring;
5666                         echo '</a>';
5667                 }
5668                 else
5669                 {
5670                         echo _ADMIN_SYSTEMOVERVIEW_NOT_ADMIN;
5671                 }
5672                 $this->pagefoot();
5673         }
5674
5675         /**
5676          * Admin::updateConfig()
5677          * 
5678          * @param       string  $name   
5679          * @param       string  $val    
5680          * @return      integer return the ID in which the latest query posted
5681          */
5682         function updateConfig($name, $val)
5683         {
5684                 $name = DB::quoteValue($name);
5685                 $val = DB::quoteValue(trim($val));
5686                 
5687                 $query = "UPDATE %s SET value=%s WHERE name=%s";
5688                 $query = sprintf($query, sql_table('config'), $val, $name);
5689                 if ( DB::execute($query) === FALSE )
5690                 {
5691                         $err = DB::getError();
5692                         die("Query error: " . $err[2]);
5693                 }
5694                 return DB::getInsertId();
5695         }
5696         
5697         /**
5698          * Error message
5699          * @param string $msg message that will be shown
5700          */
5701         function error($msg)
5702         {
5703                 $this->pagehead();
5704                 
5705                 echo "<h2>Error!</h2>\n";
5706                 echo $msg;
5707                 echo "<br />\n";
5708                 echo '<a href="index.php" onclick="history.back()">' . _BACK . "</a>\n";
5709                 $this->pagefoot();
5710                 exit;
5711         }
5712         
5713         /**
5714          * Admin::disallow()
5715          * add error log and show error page 
5716          * 
5717          * @param       void
5718          * @return      void
5719          */
5720         function disallow()
5721         {
5722                 ActionLog::add(WARNING, _ACTIONLOG_DISALLOWED . serverVar('REQUEST_URI'));
5723                 $this->error(_ERROR_DISALLOWED);
5724         }
5725         
5726         /**
5727          * Admin::pagehead()
5728          * Output admin page head
5729          * 
5730          * @param       void
5731          * @return      void
5732          */
5733         function pagehead($extrahead = '')
5734         {
5735                 global $member, $nucleus, $CONF, $manager;
5736                 
5737                 $manager->notify(
5738                         'AdminPrePageHead',
5739                         array(
5740                                 'extrahead' => &$extrahead,
5741                                 'action' => $this->action));
5742                 
5743                 $baseUrl = Entity::hsc($CONF['AdminURL']);
5744                 if ( !array_key_exists('AdminCSS',$CONF) )
5745                 {
5746                         DB::execute("INSERT INTO ".sql_table('config')." VALUES ('AdminCSS', 'original')");
5747                         $CONF['AdminCSS'] = 'original';
5748                 }
5749                 
5750                 /* HTTP 1.1 application for no caching */
5751                 header("Cache-Control: no-cache, must-revalidate");
5752                 header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
5753                 
5754                 $root_element = 'html';
5755                 $charset = i18n::get_current_charset();
5756                 $locale = preg_replace('#_#', '-', i18n::get_current_locale());
5757                 
5758                 echo "<?xml version=\"{$this->xml_version_info}\" encoding=\"{$charset}\" ?>\n";
5759                 echo "<!DOCTYPE {$root_element} PUBLIC \"{$this->formal_public_identifier}\" \"{$this->system_identifier}\">\n";
5760                 echo "<{$root_element} xmlns=\"{$this->xhtml_namespace}\" xml:lang=\"{$locale}\" lang=\"{$locale}\">\n";
5761                 echo "<head>\n";
5762                 echo '<title>' . Entity::hsc($CONF['SiteName']) . " - Admin</title>\n";
5763                 echo "<link rel=\"stylesheet\" title=\"Nucleus Admin Default\" type=\"text/css\" href=\"{$baseUrl}styles/admin_{$CONF["AdminCSS"]}.css\" />\n";
5764                 echo "<link rel=\"stylesheet\" title=\"Nucleus Admin Default\" type=\"text/css\" href=\"{$baseUrl}styles/addedit.css\" />\n";
5765                 echo "<script type=\"text/javascript\" src=\"{$baseUrl}javascript/edit.js\"></script>\n";
5766                 echo "<script type=\"text/javascript\" src=\"{$baseUrl}javascript/admin.js\"></script>\n";
5767                 echo "<script type=\"text/javascript\" src=\"{$baseUrl}javascript/compatibility.js\"></script>\n";
5768                 echo "{$extrahead}\n";
5769                 echo "</head>\n\n";
5770                 echo "<body>\n";
5771                 echo "<div id=\"adminwrapper\">\n";
5772                 echo "<div class=\"header\">\n";
5773                 echo '<h1>' . Entity::hsc($CONF['SiteName']) . "</h1>\n";
5774                 echo "</div>\n";
5775                 echo "<div id=\"container\">\n";
5776                 echo "<div id=\"content\">\n";
5777                 echo "<div class=\"loginname\">\n";
5778                 if ( $member->isLoggedIn() )
5779                 {
5780                         echo _LOGGEDINAS . ' ' . $member->getDisplayName() ." - <a href='index.php?action=logout'>" . _LOGOUT. "</a><br />\n";
5781                         echo "<a href='index.php?action=overview'>" . _ADMINHOME . "</a> - ";
5782                 }
5783                 else
5784                 {
5785                         echo '<a href="index.php?action=showlogin" title="Log in">' . _NOTLOGGEDIN . "</a><br />\n";
5786                 }
5787                 echo "<a href='".$CONF['IndexURL']."'>"._YOURSITE."</a><br />\n";
5788                 echo '(';
5789                 
5790                 if (array_key_exists('codename', $nucleus) && $nucleus['codename'] != '' )
5791                 {
5792                         $codenamestring = ' &quot;' . $nucleus['codename'].'&quot;';
5793                 }
5794                 else
5795                 {
5796                         $codenamestring = '';
5797                 }
5798                 
5799                 if ( $member->isLoggedIn() && $member->isAdmin() )
5800                 {
5801                         $checkURL = sprintf(_ADMIN_SYSTEMOVERVIEW_VERSIONCHECK_URL, getNucleusVersion(), getNucleusPatchLevel());
5802                         echo '<a href="' . $checkURL . '" title="' . _ADMIN_SYSTEMOVERVIEW_VERSIONCHECK_TITLE . '">Nucleus CMS ' . $nucleus['version'] . $codenamestring . '</a>';
5803                         
5804                         $newestVersion = getLatestVersion();
5805                         $newestCompare = str_replace('/','.',$newestVersion);
5806                         $currentVersion = str_replace(array('/','v'),array('.',''),$nucleus['version']);
5807                         if ( $newestVersion && version_compare($newestCompare, $currentVersion) > 0 )
5808                         {
5809                                 echo "<br />\n";
5810                                 echo '<a style="color:red" href="http://nucleuscms.org/upgrade.php" title="' . _ADMIN_SYSTEMOVERVIEW_LATESTVERSION_TITLE . '">';
5811                                 echo _ADMIN_SYSTEMOVERVIEW_LATESTVERSION_TEXT . $newestVersion;
5812                                 echo "</a>";
5813                         }
5814                 }
5815                 else
5816                 {
5817                         echo 'Nucleus CMS ' . $nucleus['version'] . $codenamestring;
5818                 }
5819                 echo ')';
5820                 echo '</div>';
5821                 return;
5822         }
5823         
5824         /**
5825          * Admin::pagefoot()
5826          * Output admin page foot include quickmenu
5827          * 
5828          * @param       void
5829          * @return      void
5830          */
5831         function pagefoot()
5832         {
5833                 global $action, $member, $manager;
5834                 
5835                 $manager->notify(
5836                         'AdminPrePageFoot',
5837                         array('action' => $this->action)
5838                 );
5839                 
5840                 if ( $member->isLoggedIn() && ($action != 'showlogin') )
5841                 {
5842                         echo '<h2>' . _LOGOUT . "</h2>\n";
5843                         echo "<ul>\n";
5844                         echo '<li><a href="index.php?action=overview">' . _BACKHOME . "</a></li>\n";
5845                         echo '<li><a href="index.php?action=logout">' .  _LOGOUT . "</a></li>\n";
5846                         echo "</ul>\n";
5847                 }
5848                 
5849                 echo "<div class=\"foot\">\n";
5850                 echo '<a href="' . _ADMINPAGEFOOT_OFFICIALURL . '">Nucleus CMS</a> &copy; 2002-' . date('Y') . ' ' . _ADMINPAGEFOOT_COPYRIGHT;
5851                 echo '-';
5852                 echo '<a href="' . _ADMINPAGEFOOT_DONATEURL . '">' . _ADMINPAGEFOOT_DONATE . "</a>\n";
5853                 echo "</div>\n";
5854                 
5855                 echo "<!-- content -->\n";
5856                 echo "<div id=\"quickmenu\">\n";
5857                 
5858                 if ( ($action != 'showlogin') && ($member->isLoggedIn()) )
5859                 {
5860                         echo "<ul>\n";
5861                         echo '<li><a href="index.php?action=overview">' . _QMENU_HOME . "</a></li>\n";
5862                         echo "</ul>\n";
5863                         
5864                         echo '<h2>' . _QMENU_ADD . "</h2>\n";
5865                         echo "<form method=\"get\" action=\"index.php\">\n";
5866                         echo "<p>\n";
5867                         echo "<input type=\"hidden\" name=\"action\" value=\"createitem\" />\n";
5868                         
5869                         $showAll = requestVar('showall');
5870                         
5871                         if ( ($member->isAdmin()) && ($showAll == 'yes') )
5872                         {
5873                                 // Super-Admins have access to all blogs! (no add item support though)
5874                                 $query =  'SELECT bnumber as value, bname as text'
5875                                                 . ' FROM ' . sql_table('blog')
5876                                                 . ' ORDER BY bname';
5877                         }
5878                         else
5879                         {
5880                                 $query =  'SELECT bnumber as value, bname as text'
5881                                                 . ' FROM ' . sql_table('blog') . ', ' . sql_table('team')
5882                                                 . ' WHERE tblog=bnumber and tmember=' . $member->getID()
5883                                                 . ' ORDER BY bname';
5884                         }
5885                         $template['name'] = 'blogid';
5886                         $template['tabindex'] = 15000;
5887                         $template['extra'] = _QMENU_ADD_SELECT;
5888                         $template['selected'] = -1;
5889                         $template['shorten'] = 10;
5890                         $template['shortenel'] = '';
5891                         $template['javascript'] = 'onchange="return form.submit()"';
5892                         showlist($query,'select',$template);
5893                         
5894                         echo "</p>\n";
5895                         echo "</form>\n";
5896                         
5897                         echo "<h2>{$member->getDisplayName()}</h2>\n";
5898                         echo "<ul>\n";
5899                         echo '<li><a href="index.php?action=editmembersettings">' . _QMENU_USER_SETTINGS . "</a></li>\n";
5900                         echo '<li><a href="index.php?action=browseownitems">' . _QMENU_USER_ITEMS . "</a></li>\n";
5901                         echo '<li><a href="index.php?action=browseowncomments">' . _QMENU_USER_COMMENTS . "</a></li>\n";
5902                         echo "</ul>\n";
5903                         
5904                         // ---- general settings ----
5905                         if ( $member->isAdmin() )
5906                         {
5907                                 echo '<h2>' . _QMENU_MANAGE . "</h2>\n";
5908                                 echo "<ul>\n";
5909                                 echo '<li><a href="index.php?action=actionlog">' . _QMENU_MANAGE_LOG . "</a></li>\n";
5910                                 echo '<li><a href="index.php?action=settingsedit">' . _QMENU_MANAGE_SETTINGS . "</a></li>\n";
5911                                 echo '<li><a href="index.php?action=systemoverview">' . _QMENU_MANAGE_SYSTEM . "</a></li>\n";
5912                                 echo '<li><a href="index.php?action=usermanagement">' . _QMENU_MANAGE_MEMBERS . "</a></li>\n";
5913                                 echo '<li><a href="index.php?action=createnewlog">' . _QMENU_MANAGE_NEWBLOG . "</a></li>\n";
5914                                 echo '<li><a href="index.php?action=backupoverview">' . _QMENU_MANAGE_BACKUPS . "</a></li>\n";
5915                                 echo '<li><a href="index.php?action=pluginlist">' . _QMENU_MANAGE_PLUGINS . "</a></li>\n";
5916                                 echo "</ul>\n";
5917                                 
5918                                 echo "<h2>" . _QMENU_LAYOUT . "</h2>\n";
5919                                 echo "<ul>\n";
5920                                 echo '<li><a href="index.php?action=skinoverview">' . _QMENU_LAYOUT_SKINS . "</a></li>\n";
5921                                 echo '<li><a href="index.php?action=templateoverview">' . _QMENU_LAYOUT_TEMPL . "</a></li>\n";
5922                                 echo '<li><a href="index.php?action=skinieoverview">' . _QMENU_LAYOUT_IEXPORT . "</a></li>\n";
5923                                 echo "</ul>\n";
5924                         }
5925                         
5926                         $aPluginExtras = array();
5927                         $manager->notify(
5928                                 'QuickMenu',
5929                                 array(
5930                                         'options' => &$aPluginExtras));
5931                         
5932                         if ( count($aPluginExtras) > 0 )
5933                         {
5934                                 echo "<h2>" . _QMENU_PLUGINS . "</h2>\n";
5935                                 echo "<ul>\n";
5936                                 foreach ( $aPluginExtras as $aInfo )
5937                                 {
5938                                         echo '<li><a href="' . Entity::hsc($aInfo['url']) . '" title="' . Entity::hsc($aInfo['tooltip']) . '">' . Entity::hsc($aInfo['title']) . "</a></li>\n";
5939                                 }
5940                                 echo "</ul>\n";
5941                         }
5942                 }
5943                 else if ( ($action == 'activate') || ($action == 'activatesetpwd') )
5944                 {
5945                 
5946                         echo '<h2>' . _QMENU_ACTIVATE . '</h2>' . _QMENU_ACTIVATE_TEXT;
5947                 }
5948                 else
5949                 {
5950                         // introduction text on login screen
5951                         echo '<h2>' . _QMENU_INTRO . '</h2>' . _QMENU_INTRO_TEXT;
5952                 }
5953                 
5954                 echo "<!-- quickmenu -->\n";
5955                 echo "</div>\n";
5956                 
5957                 echo "<!-- content -->\n";
5958                 echo "</div>\n";
5959                 
5960                 echo "<!-- container -->\n";
5961                 echo "</div>\n";
5962                 
5963                 echo "<!-- adminwrapper -->\n";
5964                 echo "</div>\n";
5965                 
5966                 echo "</body>\n";
5967                 echo "</html>\n";
5968                 return;
5969         }
5970         
5971     /**
5972      * @todo document this
5973      */
5974     function action_regfile() {
5975         global $member, $CONF;
5976
5977         $blogid = intRequestVar('blogid');
5978
5979         $member->teamRights($blogid) or $this->disallow();
5980
5981         // header-code stolen from phpMyAdmin
5982         // REGEDIT and bookmarklet code stolen from GreyMatter
5983
5984         $sjisBlogName = sprintf(_WINREGFILE_TEXT, getBlogNameFromID($blogid));
5985
5986
5987         header('Content-Type: application/octetstream');
5988         header('Content-Disposition: filename="nucleus.reg"');
5989         header('Pragma: no-cache');
5990         header('Expires: 0');
5991
5992         echo "REGEDIT4\n";
5993         echo "[HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\MenuExt\\" . $sjisBlogName . "]\n";
5994         echo '@="' . $CONF['AdminURL'] . "bookmarklet.php?action=contextmenucode&blogid=".intval($blogid)."\"\n";
5995         echo '"contexts"=hex:31';
5996     }
5997
5998     /**
5999      * @todo document this
6000      */
6001     function action_bookmarklet() {
6002         global $member, $manager;
6003
6004         $blogid = intRequestVar('blogid');
6005
6006         $member->teamRights($blogid) or $this->disallow();
6007
6008         $blog =& $manager->getBlog($blogid);
6009         $bm = getBookmarklet($blogid);
6010
6011         $this->pagehead();
6012
6013         echo '<p><a href="index.php?action=overview">(',_BACKHOME,')</a></p>';
6014
6015         ?>
6016
6017         <h2><?php echo _BOOKMARKLET_TITLE ?></h2>
6018
6019         <p>
6020         <?php echo _BOOKMARKLET_DESC1 . _BOOKMARKLET_DESC2 . _BOOKMARKLET_DESC3 . _BOOKMARKLET_DESC4 . _BOOKMARKLET_DESC5 ?>
6021         </p>
6022
6023         <h3><?php echo _BOOKMARKLET_BOOKARKLET ?></h3>
6024         <p>
6025             <?php echo _BOOKMARKLET_BMARKTEXT ?><small><?php echo _BOOKMARKLET_BMARKTEST ?></small>
6026             <br />
6027             <br />
6028             <?php echo '<a href="' . Entity::hsc($bm) . '">' . sprintf(_BOOKMARKLET_ANCHOR, Entity::hsc($blog->getName())) . '</a>' . _BOOKMARKLET_BMARKFOLLOW; ?>
6029         </p>
6030
6031         <h3><?php echo _BOOKMARKLET_RIGHTCLICK ?></h3>
6032         <p>
6033             <?php
6034                 $url = 'index.php?action=regfile&blogid=' . intval($blogid);
6035                 $url = $manager->addTicketToUrl($url);
6036             ?>
6037             <?php echo _BOOKMARKLET_RIGHTTEXT1 . '<a href="' . Entity::hsc($url, ENT_QUOTES, "SJIS") . '">' . _BOOKMARKLET_RIGHTLABEL . '</a>' . _BOOKMARKLET_RIGHTTEXT2; ?>
6038         </p>
6039
6040         <p>
6041             <?php echo _BOOKMARKLET_RIGHTTEXT3 ?>
6042         </p>
6043
6044         <h3><?php echo _BOOKMARKLET_UNINSTALLTT ?></h3>
6045         <p>
6046             <?php echo _BOOKMARKLET_DELETEBAR ?>
6047         </p>
6048
6049         <p>
6050             <?php echo _BOOKMARKLET_DELETERIGHTT ?>
6051         </p>
6052
6053         <ol>
6054             <li><?php echo _BOOKMARKLET_DELETERIGHT1 ?></li>
6055             <li><?php echo _BOOKMARKLET_DELETERIGHT2 ?></li>
6056             <li><?php echo _BOOKMARKLET_DELETERIGHT3 ?></li>
6057             <li><?php echo _BOOKMARKLET_DELETERIGHT4 ?></li>
6058             <li><?php echo _BOOKMARKLET_DELETERIGHT5 ?></li>
6059         </ol>
6060
6061         <?php
6062         $this->pagefoot();
6063
6064     }
6065
6066     /**
6067      * @todo document this
6068      */
6069     function action_actionlog() {
6070         global $member, $manager;
6071
6072         $member->isAdmin() or $this->disallow();
6073
6074         $this->pagehead();
6075
6076         echo '<p><a href="index.php?action=manage">(',_BACKTOMANAGE,')</a></p>';
6077
6078         $url = $manager->addTicketToUrl('index.php?action=clearactionlog');
6079
6080         ?>
6081             <h2><?php echo _ACTIONLOG_CLEAR_TITLE ?></h2>
6082             <p><a href="<?php echo Entity::hsc($url) ?>"><?php echo _ACTIONLOG_CLEAR_TEXT ?></a></p>
6083         <?php
6084         echo '<h2>' . _ACTIONLOG_TITLE . '</h2>';
6085
6086         $query =  'SELECT * FROM '.sql_table('actionlog').' ORDER BY timestamp DESC';
6087         $template['content'] = 'actionlist';
6088         $amount = showlist($query,'table',$template);
6089
6090         $this->pagefoot();
6091
6092     }
6093
6094     /**
6095      * @todo document this
6096      */
6097     function action_banlist() {
6098         global $member, $manager;
6099
6100         $blogid = intRequestVar('blogid');
6101
6102         $member->blogAdminRights($blogid) or $this->disallow();
6103
6104         $blog =& $manager->getBlog($blogid);
6105
6106         $this->pagehead();
6107
6108         echo '<p><a href="index.php?action=overview">(',_BACKHOME,')</a></p>';
6109
6110         echo '<h2>' . _BAN_TITLE . " '". $this->bloglink($blog) ."'</h2>";
6111
6112         $query =  'SELECT * FROM '.sql_table('ban').' WHERE blogid='.$blogid.' ORDER BY iprange';
6113         $template['content'] = 'banlist';
6114         $amount = showlist($query,'table',$template);
6115
6116         if ($amount == 0)
6117             echo _BAN_NONE;
6118
6119         echo '<h2>'._BAN_NEW_TITLE.'</h2>';
6120         echo "<p><a href='index.php?action=banlistnew&amp;blogid=$blogid'>"._BAN_NEW_TEXT."</a></p>";
6121
6122
6123         $this->pagefoot();
6124
6125     }
6126
6127     /**
6128      * @todo document this
6129      */
6130     function action_banlistdelete() {
6131         global $member, $manager;
6132
6133         $blogid = intRequestVar('blogid');
6134         $iprange = requestVar('iprange');
6135
6136         $member->blogAdminRights($blogid) or $this->disallow();
6137
6138         $blog =& $manager->getBlog($blogid);
6139         $banBlogName =  Entity::hsc($blog->getName());
6140
6141         $this->pagehead();
6142         ?>
6143             <h2><?php echo _BAN_REMOVE_TITLE ?></h2>
6144
6145             <form method="post" action="index.php">
6146
6147             <h3><?php echo _BAN_IPRANGE ?></h3>
6148
6149             <p>
6150                 <?php echo _CONFIRMTXT_BAN ?> <?php echo Entity::hsc($iprange) ?>
6151                 <input name="iprange" type="hidden" value="<?php echo Entity::hsc($iprange) ?>" />
6152             </p>
6153
6154             <h3><?php echo _BAN_BLOGS ?></h3>
6155
6156             <div>
6157                 <input type="hidden" name="blogid" value="<?php echo $blogid ?>" />
6158                 <input name="allblogs" type="radio" value="0" id="allblogs_one" />
6159                 <label for="allblogs_one"><?php echo sprintf(_BAN_BANBLOGNAME, $banBlogName) ?></label>
6160                 <br />
6161                 <input name="allblogs" type="radio" value="1" checked="checked" id="allblogs_all" /><label for="allblogs_all"><?php echo _BAN_ALLBLOGS ?></label>
6162             </div>
6163
6164             <h3><?php echo _BAN_DELETE_TITLE ?></h3>
6165
6166             <div>
6167                 <?php $manager->addTicketHidden() ?>
6168                 <input type="hidden" name="action" value="banlistdeleteconfirm" />
6169                 <input type="submit" value="<?php echo _DELETE_CONFIRM_BTN ?>" />
6170             </div>
6171
6172             </form>
6173         <?php
6174         $this->pagefoot();
6175     }
6176
6177     /**
6178      * @todo document this
6179      */
6180     function action_banlistdeleteconfirm() {
6181         global $member, $manager;
6182
6183         $blogid = intPostVar('blogid');
6184         $allblogs = postVar('allblogs');
6185         $iprange = postVar('iprange');
6186
6187         $member->blogAdminRights($blogid) or $this->disallow();
6188
6189         $deleted = array();
6190
6191         if (!$allblogs) {
6192             if (Ban::removeBan($blogid, $iprange))
6193                 array_push($deleted, $blogid);
6194         } else {
6195             // get blogs fot which member has admin rights
6196             $adminblogs = $member->getAdminBlogs();
6197             foreach ($adminblogs as $blogje) {
6198                 if (Ban::removeBan($blogje, $iprange))
6199                     array_push($deleted, $blogje);
6200             }
6201         }
6202
6203         if (sizeof($deleted) == 0)
6204             $this->error(_ERROR_DELETEBAN);
6205
6206         $this->pagehead();
6207
6208         echo '<a href="index.php?action=banlist&amp;blogid=',$blogid,'">(',_BACK,')</a>';
6209         echo '<h2>'._BAN_REMOVED_TITLE.'</h2>';
6210         echo "<p>"._BAN_REMOVED_TEXT."</p>";
6211
6212         echo "<ul>";
6213         foreach ($deleted as $delblog) {
6214             $b =& $manager->getBlog($delblog);
6215             echo "<li>" . Entity::hsc($b->getName()). "</li>";
6216         }
6217         echo "</ul>";
6218
6219         $this->pagefoot();
6220
6221     }
6222
6223     /**
6224      * @todo document this
6225      */
6226     function action_banlistnewfromitem() {
6227         $this->action_banlistnew(getBlogIDFromItemID(intRequestVar('itemid')));
6228     }
6229
6230     /**
6231      * @todo document this
6232      */
6233     function action_banlistnew($blogid = '') {
6234         global $member, $manager;
6235
6236         if ($blogid == '')
6237             $blogid = intRequestVar('blogid');
6238
6239         $ip = requestVar('ip');
6240
6241         $member->blogAdminRights($blogid) or $this->disallow();
6242
6243         $blog =& $manager->getBlog($blogid);
6244
6245         $this->pagehead();
6246         ?>
6247         <h2><?php echo _BAN_ADD_TITLE ?></h2>
6248
6249
6250         <form method="post" action="index.php">
6251
6252         <h3><?php echo _BAN_IPRANGE ?></h3>
6253
6254         <p><?php echo _BAN_IPRANGE_TEXT ?></p>
6255
6256         <div class="note">
6257             <strong><?php echo _BAN_EXAMPLE_TITLE ?></strong>
6258             <?php echo _BAN_EXAMPLE_TEXT ?>
6259         </div>
6260
6261         <div>
6262         <?php
6263         if ($ip) {
6264             $iprangeVal = Entity::hsc($ip);
6265         ?>
6266             <input name="iprange" type="radio" value="<?php echo $iprangeVal ?>" checked="checked" id="ip_fixed" />
6267             <label for="ip_fixed"><?php echo $iprangeVal ?></label>
6268             <br />
6269             <input name="iprange" type="radio" value="custom" id="ip_custom" />
6270             <label for="ip_custom"><?php echo _BAN_IP_CUSTOM ?></label>
6271             <input name='customiprange' value='<?php echo $iprangeVal ?>' maxlength='15' size='15' />
6272         <?php
6273         } else {
6274             echo "<input name='iprange' value='custom' type='hidden' />";
6275             echo "<input name='customiprange' value='' maxlength='15' size='15' />";
6276         }
6277         ?>
6278         </div>
6279
6280         <h3><?php echo _BAN_BLOGS ?></h3>
6281
6282         <p><?php echo _BAN_BLOGS_TEXT ?></p>
6283
6284         <div>
6285             <input type="hidden" name="blogid" value="<?php echo $blogid ?>" />
6286             <input name="allblogs" type="radio" value="0" id="allblogs_one" /><label for="allblogs_one">'<?php echo Entity::hsc($blog->getName()) ?>'</label>
6287             <br />
6288             <input name="allblogs" type="radio" value="1" checked="checked" id="allblogs_all" /><label for="allblogs_all"><?php echo _BAN_ALLBLOGS ?></label>
6289         </div>
6290
6291         <h3><?php echo _BAN_REASON_TITLE ?></h3>
6292
6293         <p><?php echo _BAN_REASON_TEXT ?></p>
6294
6295         <div><textarea name="reason" cols="40" rows="5"></textarea></div>
6296
6297         <h3><?php echo _BAN_ADD_TITLE ?></h3>
6298
6299         <div>
6300             <input name="action" type="hidden" value="banlistadd" />
6301             <?php $manager->addTicketHidden() ?>
6302             <input type="submit" value="<?php echo _BAN_ADD_BTN ?>" />
6303         </div>
6304
6305         </form>
6306
6307         <?php       $this->pagefoot();
6308     }
6309
6310     /**
6311      * @todo document this
6312      */
6313     function action_banlistadd() {
6314         global $member;
6315
6316         $blogid =       intPostVar('blogid');
6317         $allblogs =     postVar('allblogs');
6318         $iprange =      postVar('iprange');
6319         if ($iprange == "custom")
6320             $iprange = postVar('customiprange');
6321         $reason =       postVar('reason');
6322
6323         $member->blogAdminRights($blogid) or $this->disallow();
6324
6325         // TODO: check IP range validity
6326
6327         if (!$allblogs) {
6328             if (!Ban::addBan($blogid, $iprange, $reason))
6329                 $this->error(_ERROR_ADDBAN);
6330         } else {
6331             // get blogs fot which member has admin rights
6332             $adminblogs = $member->getAdminBlogs();
6333             $failed = 0;
6334             foreach ($adminblogs as $blogje) {
6335                 if (!Ban::addBan($blogje, $iprange, $reason))
6336                     $failed = 1;
6337             }
6338             if ($failed)
6339                 $this->error(_ERROR_ADDBAN);
6340         }
6341
6342         $this->action_banlist();
6343
6344     }
6345
6346     /**
6347      * @todo document this
6348      */
6349     function action_clearactionlog() {
6350         global $member;
6351
6352         $member->isAdmin() or $this->disallow();
6353
6354         ActionLog::clear();
6355
6356         $this->action_manage(_MSG_ACTIONLOGCLEARED);
6357     }
6358
6359     /**
6360      * @todo document this
6361      */
6362     function action_backupoverview() {
6363         global $member, $manager;
6364
6365         $member->isAdmin() or $this->disallow();
6366
6367         $this->pagehead();
6368
6369         echo '<p><a href="index.php?action=manage">(',_BACKTOMANAGE,')</a></p>';
6370         ?>
6371         <h2><?php echo _BACKUPS_TITLE ?></h2>
6372
6373         <h3><?php echo _BACKUP_TITLE ?></h3>
6374
6375         <p><?php echo _BACKUP_INTRO ?></p>
6376
6377         <form method="post" action="index.php"><p>
6378         <input type="hidden" name="action" value="backupcreate" />
6379         <?php $manager->addTicketHidden() ?>
6380
6381         <input type="radio" name="gzip" value="1" checked="checked" id="gzip_yes" tabindex="10" /><label for="gzip_yes"><?php echo _BACKUP_ZIP_YES ?></label>
6382         <br />
6383         <input type="radio" name="gzip" value="0" id="gzip_no" tabindex="10" /><label for="gzip_no" ><?php echo _BACKUP_ZIP_NO ?></label>
6384         <br /><br />
6385         <input type="submit" value="<?php echo _BACKUP_BTN ?>" tabindex="20" />
6386
6387         </p></form>
6388
6389         <div class="note"><?php echo _BACKUP_NOTE ?></div>
6390
6391
6392         <h3><?php echo _RESTORE_TITLE ?></h3>
6393
6394         <div class="note"><?php echo _RESTORE_NOTE ?></div>
6395
6396         <p><?php echo _RESTORE_INTRO ?></p>
6397
6398         <form method="post" action="index.php" enctype="multipart/form-data"><p>
6399             <input type="hidden" name="action" value="backuprestore" />
6400             <?php $manager->addTicketHidden() ?>
6401             <input name="backup_file" type="file" tabindex="30" />
6402             <br /><br />
6403             <input type="submit" value="<?php echo _RESTORE_BTN ?>" tabindex="40" />
6404             <br /><input type="checkbox" name="letsgo" value="1" id="letsgo" tabindex="50" /><label for="letsgo"><?php echo _RESTORE_IMSURE ?></label>
6405             <br /><?php echo _RESTORE_WARNING ?>
6406         </p></form>
6407
6408         <?php       $this->pagefoot();
6409     }
6410
6411         /**
6412          * Admin::action_backupcreate()
6413          * create file for backup
6414          * 
6415          * @param               void
6416          * @return      void
6417          * 
6418          */
6419         function action_backupcreate()
6420         {
6421                 global $member, $DIR_LIBS;
6422                 
6423                 $member->isAdmin() or $this->disallow();
6424                 
6425                 // use compression ?
6426                 $useGzip = (integer) postVar('gzip');
6427                 
6428                 include($DIR_LIBS . 'backup.php');
6429                 
6430                 // try to extend time limit
6431                 // (creating/restoring dumps might take a while)
6432                 @set_time_limit(1200);
6433                 
6434                 Backup::do_backup($useGzip);
6435                 exit;
6436         }
6437         
6438         /**
6439          * Admin::action_backuprestore()
6440          * restoring from uploaded file
6441          * 
6442          * @param               void
6443          * @return      void
6444          */
6445         function action_backuprestore()
6446         {
6447                 global $member, $DIR_LIBS;
6448                 
6449                 $member->isAdmin() or $this->disallow();
6450                 
6451                 if ( intPostVar('letsgo') != 1 )
6452                 {
6453                         $this->error(_ERROR_BACKUP_NOTSURE);
6454                 }
6455                 
6456                 include($DIR_LIBS . 'backup.php');
6457                 
6458                 // try to extend time limit
6459                 // (creating/restoring dumps might take a while)
6460                 @set_time_limit(1200);
6461                 
6462                 $message = Backup::do_restore();
6463                 if ( $message != '' )
6464                 {
6465                         $this->error($message);
6466                 }
6467                 $this->pagehead();
6468                 echo '<h2>' . _RESTORE_COMPLETE . "</h2>\n";
6469                 $this->pagefoot();
6470                 return;
6471         }
6472         
6473         /**
6474          * Admin::action_pluginlist()
6475          * output the list of installed plugins
6476          * 
6477          * @param       void
6478          * @return      void
6479          * 
6480          */
6481         function action_pluginlist()
6482         {
6483                 global $DIR_PLUGINS, $member, $manager;
6484                 
6485                 // check if allowed
6486                 $member->isAdmin() or $this->disallow();
6487                 
6488                 $this->pagehead();
6489                 
6490                 echo '<p><a href="index.php?action=manage">(',_BACKTOMANAGE,')</a></p>';
6491                 
6492                 echo '<h2>' , _PLUGS_TITLE_MANAGE , ' ', help('plugins'), '</h2>';
6493                 
6494                 echo '<h3>' , _PLUGS_TITLE_INSTALLED , ' &nbsp;&nbsp;<span style="font-size:smaller">', helplink('getplugins'), _PLUGS_TITLE_GETPLUGINS, '</a></span></h3>';
6495                 
6496                 $query =  'SELECT * FROM '.sql_table('plugin').' ORDER BY porder ASC';
6497                 
6498                 $template['content'] = 'pluginlist';
6499                 $template['tabindex'] = 10;
6500                 showlist($query, 'table', $template);
6501                 
6502                 echo '<h3>' . _PLUGS_TITLE_UPDATE . "</h3>\n";
6503                 echo '<p>' . _PLUGS_TEXT_UPDATE . "</p>\n";
6504                 echo '<form method="post" action="index.php">' . "\n";
6505                 echo "<div>\n";
6506                 echo '<input type="hidden" name="action" value="pluginupdate" />' . "\n";
6507                 $manager->addTicketHidden();
6508                 echo '<input type="submit" value="' . _PLUGS_BTN_UPDATE . '" tabindex="20" />' . "\n";
6509                 echo "</div>\n";
6510                 echo "</form>\n";
6511                 
6512                 echo '<h3>' . _PLUGS_TITLE_NEW . "</h3>\n";
6513                 
6514                 // find a list of possibly non-installed plugins
6515                 $candidates = array();
6516                 $dirhandle = opendir($DIR_PLUGINS);
6517                 
6518                 while ( $filename = readdir($dirhandle) )
6519                 {
6520                         if ( preg_match('#^NP_(.*)\.php$#', $filename, $matches) )
6521                         {
6522                                 $name = $matches[1];
6523                                 
6524                                 // only show in list when not yet installed
6525                                 $query = 'SELECT * FROM %s WHERE pfile = %s';
6526                                 $query = sprintf($query, sql_table('plugin'), DB::quoteValue('NP_'.$name));
6527                                 $res = DB::getResult($query);
6528                                 
6529                                 if ( $res->rowCount() == 0 )
6530                                 {
6531                                         array_push($candidates, $name);
6532                                 }
6533                         }
6534                 }
6535                 
6536                 closedir($dirhandle);
6537                 
6538                 if ( sizeof($candidates) > 0 )
6539                 {
6540                         echo '<p>' . _PLUGS_ADD_TEXT . "</p>\n";
6541                         
6542                         echo '<form method="post" action="index.php">' . "\n";
6543                         echo "<div>\n";
6544                         echo '<input type="hidden" name="action" value="pluginadd" />' . "\n";
6545                         $manager->addTicketHidden();
6546                         echo '<select name="filename" tabindex="30">' . "\n";
6547                         
6548                         foreach ( $candidates as $name )
6549                         {
6550                                 echo '<option value="NP_',$name,'">',Entity::hsc($name),'</option>';
6551                         }
6552                         
6553                         echo "</select>\n";
6554                         echo '<input type="submit" tabindex="40" value="' . _PLUGS_BTN_INSTALL ."\" />\n";
6555                         echo "</div>\n";
6556                         echo "</form>\n";
6557                 }
6558                 else
6559                 {
6560                         echo '<p>', _PLUGS_NOCANDIDATES, '</p>';
6561                 }
6562                 
6563                 $this->pagefoot();
6564                 return;
6565         }
6566         
6567     /**
6568      * @todo document this
6569      */
6570     function action_pluginhelp() {
6571         global $member, $manager, $DIR_PLUGINS, $CONF;
6572
6573         // check if allowed
6574         $member->isAdmin() or $this->disallow();
6575
6576         $plugid = intGetVar('plugid');
6577
6578         if (!$manager->pidInstalled($plugid))
6579             $this->error(_ERROR_NOSUCHPLUGIN);
6580
6581         $plugName = getPluginNameFromPid($plugid);
6582
6583         $this->pagehead();
6584
6585         echo '<p><a href="index.php?action=pluginlist">(',_PLUGS_BACK,')</a></p>';
6586
6587         echo '<h2>',_PLUGS_HELP_TITLE,': ',Entity::hsc($plugName),'</h2>';
6588
6589         $plug =& $manager->getPlugin($plugName);
6590         $helpFile = $DIR_PLUGINS.$plug->getShortName().'/help.html';
6591
6592         if (($plug->supportsFeature('HelpPage') > 0) && (@file_exists($helpFile))) {
6593             @readfile($helpFile);
6594         } else {
6595             echo '<p>Error: ', _ERROR_PLUGNOHELPFILE,'</p>';
6596             echo '<p><a href="index.php?action=pluginlist">(',_BACK,')</a></p>';
6597         }
6598
6599
6600         $this->pagefoot();
6601     }
6602
6603         /**
6604          * Admin::action_pluginadd()
6605          * 
6606          * @param       Void
6607          * @return      Void
6608          * 
6609          */
6610         function action_pluginadd()
6611         {
6612                 global $member, $manager, $DIR_PLUGINS;
6613                 
6614                 // check if allowed
6615                 $member->isAdmin() or $this->disallow();
6616                 
6617                 $name = postVar('filename');
6618                 
6619                 if ( $manager->pluginInstalled($name) )
6620                 {
6621                         $this->error(_ERROR_DUPPLUGIN);
6622                 }
6623                 
6624                 if ( !checkPlugin($name) )
6625                 {
6626                         $this->error(_ERROR_PLUGFILEERROR . ' (' . Entity::hsc($name) . ')');
6627                 }
6628                 
6629                 // get number of currently installed plugins
6630                 $res = DB::getResult('SELECT * FROM '.sql_table('plugin'));
6631                 $numCurrent = $res->rowCount();
6632                 
6633                 // plugin will be added as last one in the list
6634                 $newOrder = $numCurrent + 1;
6635                 
6636                 $manager->notify(
6637                         'PreAddPlugin',
6638                         array(
6639                                 'file' => &$name
6640                         )
6641                 );
6642                 
6643                 // do this before calling getPlugin (in case the plugin id is used there)
6644                 $query = 'INSERT INTO '.sql_table('plugin').' (porder, pfile) VALUES ('.$newOrder.','.DB::quoteValue($name).')';
6645                 DB::execute($query);
6646                 $iPid = DB::getInsertId();
6647                 
6648                 $manager->clearCachedInfo('installedPlugins');
6649                 
6650                 // Load the plugin for condition checking and instalation
6651                 $plugin =& $manager->getPlugin($name);
6652                 
6653                 // check if it got loaded (could have failed)
6654                 if ( !$plugin )
6655                 {
6656                         DB::execute('DELETE FROM ' . sql_table('plugin') . ' WHERE pid='. intval($iPid));
6657                         $manager->clearCachedInfo('installedPlugins');
6658                         $this->error(_ERROR_PLUGIN_LOAD);
6659                 }
6660                 
6661                 // check if plugin needs a newer Nucleus version
6662                 if ( getNucleusVersion() < $plugin->getMinNucleusVersion() )
6663                 {
6664                         // uninstall plugin again...
6665                         $this->deleteOnePlugin($plugin->getID());
6666                         
6667                         // ...and show error
6668                         $this->error(_ERROR_NUCLEUSVERSIONREQ . Entity::hsc($plugin->getMinNucleusVersion()));
6669                 }
6670                 
6671                 // check if plugin needs a newer Nucleus version
6672                 if ( (getNucleusVersion() == $plugin->getMinNucleusVersion()) && (getNucleusPatchLevel() < $plugin->getMinNucleusPatchLevel()) )
6673                 {
6674                         // uninstall plugin again...
6675                         $this->deleteOnePlugin($plugin->getID());
6676                         
6677                         // ...and show error
6678                         $this->error(_ERROR_NUCLEUSVERSIONREQ . Entity::hsc( $plugin->getMinNucleusVersion() . ' patch ' . $plugin->getMinNucleusPatchLevel() ) );
6679                 }
6680                 
6681                 $pluginList = $plugin->getPluginDep();
6682                 foreach ( $pluginList as $pluginName )
6683                 {
6684                         $res = DB::getResult('SELECT * FROM '.sql_table('plugin') . ' WHERE pfile=' . DB::quoteValue($pluginName));
6685                         if ($res->rowCount() == 0)
6686                         {
6687                                 // uninstall plugin again...
6688                                 $this->deleteOnePlugin($plugin->getID());
6689                                 $this->error(sprintf(_ERROR_INSREQPLUGIN, Entity::hsc($pluginName)));
6690                         }
6691                 }
6692                 
6693                 // call the install method of the plugin
6694                 $plugin->install();
6695                 
6696                 $manager->notify(
6697                         'PostAddPlugin',
6698                         array(
6699                                 'plugin' => &$plugin
6700                         )
6701                 );
6702                 
6703                 // update all events
6704                 $this->action_pluginupdate();
6705                 return;
6706         }
6707         
6708         /**
6709          * ADMIN:action_pluginupdate():
6710          * 
6711          * @param       Void
6712          * @return      Void
6713          * 
6714          */
6715         function action_pluginupdate()
6716         {
6717                 global $member, $manager, $CONF;
6718                 
6719                 // check if allowed
6720                 $member->isAdmin() or $this->disallow();
6721                 
6722                 // delete everything from plugin_events
6723                 DB::execute('DELETE FROM '.sql_table('plugin_event'));
6724                 
6725                 // loop over all installed plugins
6726                 $res = DB::getResult('SELECT pid, pfile FROM '.sql_table('plugin'));
6727                 foreach ( $res as $row )
6728                 {
6729                         $pid = $row['pid'];
6730                         $plug =& $manager->getPlugin($row['pfile']);
6731                         if ( $plug )
6732                         {
6733                                 $eventList = $plug->getEventList();
6734                                 foreach ( $eventList as $eventName )
6735                                 {
6736                                         $query = "INSERT INTO %s (pid, event) VALUES (%d, %s)";
6737                                         $query = sprintf($query, sql_table('plugin_event'), (integer) $pid, DB::quoteValue($eventName));
6738                                         DB::execute($query);
6739                                 }
6740                         }
6741                 }
6742                 redirect($CONF['AdminURL'] . '?action=pluginlist');
6743                 return;
6744         }
6745         
6746     /**
6747      * @todo document this
6748      */
6749     function action_plugindelete() {
6750         global $member, $manager;
6751
6752         // check if allowed
6753         $member->isAdmin() or $this->disallow();
6754
6755         $pid = intGetVar('plugid');
6756
6757         if (!$manager->pidInstalled($pid))
6758             $this->error(_ERROR_NOSUCHPLUGIN);
6759
6760         $this->pagehead();
6761         ?>
6762             <h2><?php echo _DELETE_CONFIRM ?></h2>
6763
6764             <p><?php echo _CONFIRMTXT_PLUGIN ?> <strong><?php echo getPluginNameFromPid($pid) ?></strong>?</p>
6765
6766             <form method="post" action="index.php"><div>
6767             <?php $manager->addTicketHidden() ?>
6768             <input type="hidden" name="action" value="plugindeleteconfirm" />
6769             <input type="hidden" name="plugid" value="<?php echo $pid; ?>" />
6770             <input type="submit" tabindex="10" value="<?php echo _DELETE_CONFIRM_BTN ?>" />
6771             </div></form>
6772         <?php
6773         $this->pagefoot();
6774     }
6775
6776     /**
6777      * @todo document this
6778      */
6779     function action_plugindeleteconfirm() {
6780         global $member, $manager, $CONF;
6781
6782         // check if allowed
6783         $member->isAdmin() or $this->disallow();
6784
6785         $pid = intPostVar('plugid');
6786
6787         $error = $this->deleteOnePlugin($pid, 1);
6788         if ($error) {
6789             $this->error($error);
6790         }
6791
6792         redirect($CONF['AdminURL'] . '?action=pluginlist');
6793 //              $this->action_pluginlist();
6794     }
6795
6796     /**
6797      * @todo document this
6798      */
6799     function deleteOnePlugin($pid, $callUninstall = 0) {
6800         global $manager;
6801
6802         $pid = intval($pid);
6803
6804         if (!$manager->pidInstalled($pid))
6805             return _ERROR_NOSUCHPLUGIN;
6806
6807         $name = DB::getValue('SELECT pfile as result FROM '.sql_table('plugin').' WHERE pid='.$pid);
6808
6809 /*              // call the unInstall method of the plugin
6810         if ($callUninstall) {
6811             $plugin =& $manager->getPlugin($name);
6812             if ($plugin) $plugin->unInstall();
6813         }*/
6814
6815         // check dependency before delete
6816         $res = DB::getResult('SELECT pfile FROM '.sql_table('plugin'));
6817         foreach ( $res as $row ) {
6818             $plug =& $manager->getPlugin($row['pfile']);
6819             if ($plug)
6820             {
6821                 $depList = $plug->getPluginDep();
6822                 foreach ($depList as $depName)
6823                 {
6824                     if ($name == $depName)
6825                     {
6826                         return sprintf(_ERROR_DELREQPLUGIN, $row['pfile']);
6827                     }
6828                 }
6829             }
6830         }
6831
6832         $manager->notify('PreDeletePlugin', array('plugid' => $pid));
6833
6834         // call the unInstall method of the plugin
6835         if ($callUninstall) {
6836             $plugin =& $manager->getPlugin($name);
6837             if ($plugin) $plugin->unInstall();
6838         }
6839
6840         // delete all subscriptions
6841         DB::execute('DELETE FROM '.sql_table('plugin_event').' WHERE pid=' . $pid);
6842
6843         // delete all options
6844         // get OIDs from plugin_option_desc
6845         $res = DB::getResult('SELECT oid FROM ' . sql_table('plugin_option_desc') . ' WHERE opid=' . $pid);
6846         $aOIDs = array();
6847         foreach ( $res as $row ) {
6848             array_push($aOIDs, $row['oid']);
6849         }
6850
6851         // delete from plugin_option and plugin_option_desc
6852         DB::execute('DELETE FROM '.sql_table('plugin_option_desc').' WHERE opid=' . $pid);
6853         if (count($aOIDs) > 0)
6854             DB::execute('DELETE FROM '.sql_table('plugin_option').' WHERE oid in ('.implode(',',$aOIDs).')');
6855
6856         // update order numbers
6857         $res = DB::getValue('SELECT porder FROM '.sql_table('plugin').' WHERE pid=' . $pid);
6858         DB::execute('UPDATE '.sql_table('plugin').' SET porder=(porder - 1) WHERE porder>'.$res);
6859
6860         // delete row
6861         DB::execute('DELETE FROM '.sql_table('plugin').' WHERE pid='.$pid);
6862
6863         $manager->clearCachedInfo('installedPlugins');
6864         $manager->notify('PostDeletePlugin', array('plugid' => $pid));
6865
6866         return '';
6867     }
6868
6869     /**
6870      * @todo document this
6871      */
6872     function action_pluginup() {
6873         global $member, $manager, $CONF;
6874
6875         // check if allowed
6876         $member->isAdmin() or $this->disallow();
6877
6878         $plugid = intGetVar('plugid');
6879
6880         if (!$manager->pidInstalled($plugid))
6881             $this->error(_ERROR_NOSUCHPLUGIN);
6882
6883         // 1. get old order number
6884         $oldOrder = DB::getValue('SELECT porder FROM '.sql_table('plugin').' WHERE pid='.$plugid);
6885
6886         // 2. calculate new order number
6887         $newOrder = ($oldOrder > 1) ? ($oldOrder - 1) : 1;
6888
6889         // 3. update plug numbers
6890         DB::execute('UPDATE '.sql_table('plugin').' SET porder='.$oldOrder.' WHERE porder='.$newOrder);
6891         DB::execute('UPDATE '.sql_table('plugin').' SET porder='.$newOrder.' WHERE pid='.$plugid);
6892
6893         //$this->action_pluginlist();
6894         // To avoid showing ticket in the URL, redirect to pluginlist, instead.
6895         redirect($CONF['AdminURL'] . '?action=pluginlist');
6896     }
6897
6898     /**
6899      * @todo document this
6900      */
6901     function action_plugindown() {
6902         global $member, $manager, $CONF;
6903
6904         // check if allowed
6905         $member->isAdmin() or $this->disallow();
6906
6907         $plugid = intGetVar('plugid');
6908         if (!$manager->pidInstalled($plugid))
6909             $this->error(_ERROR_NOSUCHPLUGIN);
6910
6911         // 1. get old order number
6912         $oldOrder = DB::getValue('SELECT porder FROM '.sql_table('plugin').' WHERE pid='.$plugid);
6913
6914         $res = DB::getResult('SELECT * FROM '.sql_table('plugin'));
6915         $maxOrder = $res->rowCount();
6916
6917         // 2. calculate new order number
6918         $newOrder = ($oldOrder < $maxOrder) ? ($oldOrder + 1) : $maxOrder;
6919
6920         // 3. update plug numbers
6921         DB::execute('UPDATE '.sql_table('plugin').' SET porder='.$oldOrder.' WHERE porder='.$newOrder);
6922         DB::execute('UPDATE '.sql_table('plugin').' SET porder='.$newOrder.' WHERE pid='.$plugid);
6923
6924         //$this->action_pluginlist();
6925         // To avoid showing ticket in the URL, redirect to pluginlist, instead.
6926         redirect($CONF['AdminURL'] . '?action=pluginlist');
6927     }
6928         
6929         /**
6930          * Admin::action_pluginoptions()
6931          * 
6932          * Output Plugin option page
6933          * 
6934          * @access      public
6935          * @param       string $message message when fallbacked
6936          * @return      void
6937          * 
6938          */
6939         public function action_pluginoptions($message = '')
6940         {
6941                 global $member, $manager;
6942                 
6943                 // check if allowed
6944                 $member->isAdmin() or $this->disallow();
6945                 
6946                 $pid = (integer) requestVar('plugid');
6947                 if ( !$manager->pidInstalled($pid) )
6948                 {
6949                         $this->error(_ERROR_NOSUCHPLUGIN);
6950                 }
6951                 
6952                 $pname = getPluginNameFromPid($pid);
6953                 
6954                 /* just for including translation */
6955                 $manager->getPlugin($pname);
6956                 
6957                 $extrahead = "<script type=\"text/javascript\" src=\"javascript/numbercheck.js\"></script>\n";
6958                 $this->pagehead($extrahead);
6959                 echo '<p><a href="index.php?action=pluginlist">(' . _PLUGS_BACK . ")</a></p>\n";
6960                 echo '<h2>' . sprintf(_PLUGIN_OPTIONS_TITLE, Entity::hsc($pname)) . "</h2>\n";
6961                 
6962                 if ( isset($message) )
6963                 {
6964                         echo $message;
6965                 }
6966                 
6967                 echo "<form action=\"index.php\" method=\"post\">\n";
6968                 echo "<div>\n";
6969                 echo "<input type=\"hidden\" name=\"action\" value=\"pluginoptionsupdate\" />\n";
6970                 echo "<input type=\"hidden\" name=\"plugid\" value=\"{$pid}\" />\n";
6971                 $manager->addTicketHidden();
6972                 
6973                 $aOptions = array();
6974                 $aOIDs = array();
6975                 $query = "SELECT * FROM %s WHERE ocontext='global' and opid=%d ORDER BY oid ASC";
6976                 $query = sprintf($query, sql_table('plugin_option_desc'), $pid);
6977                 $result = DB::getResult($query);
6978                 foreach ( $result as $row )
6979                 {
6980                         array_push($aOIDs, $row['oid']);
6981                         $aOptions[$row['oid']] = array(
6982                                                 'oid' => $row['oid'],
6983                                                 'value' => $row['odef'],
6984                                                 'name' => $row['oname'],
6985                                                 'description' => $row['odesc'],
6986                                                 'type' => $row['otype'],
6987                                                 'typeinfo' => $row['oextra'],
6988                                                 'contextid' => 0
6989                         );
6990                 }
6991                 // fill out actual values
6992                 if ( count($aOIDs) > 0 )
6993                 {
6994                         $query = "SELECT oid, ovalue FROM %s WHERE oid in (%s)";
6995                         $query = sprintf($query, sql_table('plugin_option'), implode(',',$aOIDs));
6996                         $result = DB::getResult($query);
6997                         foreach ( $result as $row )
6998                         {
6999                                 $aOptions[$row['oid']]['value'] = $row['ovalue'];
7000                         }
7001                 }
7002                 
7003                 // call plugins
7004                 $data = array('context' => 'global', 'plugid' => $pid, 'options'=>&$aOptions);
7005                 $manager->notify('PrePluginOptionsEdit',$data);
7006                 
7007                 $template['content'] = 'plugoptionlist';
7008                 $amount = showlist($aOptions,'table',$template);
7009                 if ( $amount == 0 )
7010                 {
7011                         echo '<p>',_ERROR_NOPLUGOPTIONS,'</p>';
7012                 }
7013                 echo "</div>\n";
7014                 echo "</form>\n";
7015                 $this->pagefoot();
7016                 
7017                 return;
7018         }
7019         
7020         /**
7021          * Admin::action_pluginoptionsupdate()
7022          * 
7023          * Update plugin options and fallback to plugin option page
7024          * 
7025          * @access      public
7026          * @param       void
7027          * @return      void
7028          */
7029         public function action_pluginoptionsupdate()
7030         {
7031                 global $member, $manager;
7032                 
7033                 // check if allowed
7034                 $member->isAdmin() or $this->disallow();
7035                 
7036                 $pid = (integer) requestVar('plugid');
7037                 if ( !$manager->pidInstalled($pid) )
7038                 {
7039                         $this->error(_ERROR_NOSUCHPLUGIN);
7040                 }
7041                 
7042                 $aOptions = requestArray('plugoption');
7043                 NucleusPlugin::apply_plugin_options($aOptions);
7044                 
7045                 $manager->notify('PostPluginOptionsUpdate',array('context' => 'global', 'plugid' => $pid));
7046                 
7047                 $this->action_pluginoptions(_PLUGS_OPTIONS_UPDATED);
7048                 return;
7049         }
7050         
7051         /**
7052          * Admin::_insertPluginOptions()
7053          * 
7054          * Output plugin option field
7055          * 
7056          * @access      public
7057          * @param string        $context        plugin option context
7058          * @param integer       $contextid      plugin option context id
7059          * @return      void
7060          */
7061         public function _insertPluginOptions($context, $contextid = 0)
7062         {
7063                 // get all current values for this contextid
7064                 // (note: this might contain doubles for overlapping contextids)
7065                 $aIdToValue = array();
7066                 $res = DB::getResult('SELECT oid, ovalue FROM ' . sql_table('plugin_option') . ' WHERE ocontextid=' . intval($contextid));
7067                 foreach ( $res as $row )
7068                 {
7069                         $aIdToValue[$row['oid']] = $row['ovalue'];
7070                 }
7071                 
7072                 // get list of oids per pid
7073                 $query = 'SELECT * FROM ' . sql_table('plugin_option_desc') . ',' . sql_table('plugin')
7074                            . ' WHERE opid=pid and ocontext='.DB::quoteValue($context).' ORDER BY porder, oid ASC';
7075                 $res = DB::getResult($query);
7076                 $aOptions = array();
7077                 foreach ( $res as $row )
7078                 {
7079                         if (in_array($row['oid'], array_keys($aIdToValue)))
7080                         {
7081                                 $value = $aIdToValue[$row['oid']];
7082                         }
7083                         else
7084                         {
7085                                 $value = $row['odef'];
7086                         }
7087                         
7088                         array_push($aOptions, array(
7089                                 'pid' => $row['pid'],
7090                                 'pfile' => $row['pfile'],
7091                                 'oid' => $row['oid'],
7092                                 'value' => $value,
7093                                 'name' => $row['oname'],
7094                                 'description' => $row['odesc'],
7095                                 'type' => $row['otype'],
7096                                 'typeinfo' => $row['oextra'],
7097                                 'contextid' => $contextid,
7098                                 'extra' => ''));
7099                 }
7100                 
7101                 global $manager;
7102                 $manager->notify('PrePluginOptionsEdit',array('context' => $context, 'contextid' => $contextid, 'options'=>&$aOptions));
7103                 
7104                 $iPrevPid = -1;
7105                 foreach ($aOptions as $aOption)
7106                 {
7107                         // new plugin?
7108                         if ( $iPrevPid != $aOption['pid'] )
7109                         {
7110                                 $iPrevPid = $aOption['pid'];
7111                                 if ( !defined('_PLUGIN_OPTIONS_TITLE') )
7112                                 {
7113                                         define('_PLUGIN_OPTIONS_TITLE', 'Options for %s');
7114                                 }
7115                                 echo '<tr><th colspan="2">'.sprintf(_PLUGIN_OPTIONS_TITLE, Entity::hsc($aOption['pfile'])).'</th></tr>';
7116                         }
7117                         
7118                         $meta = NucleusPlugin::getOptionMeta($aOption['typeinfo']);
7119                         if ( @$meta['access'] != 'hidden' )
7120                         {
7121                                 echo '<tr>';
7122                                 listplug_plugOptionRow($aOption);
7123                                 echo '</tr>';
7124                         }
7125                 }
7126                 return;
7127         }
7128         
7129         /**
7130          * Admin::input_yesno()
7131          * Output input elements with radio attribute for yes/no options
7132          * 
7133          * @param       string  $name   name attribute
7134          * @param       string  $value_current  current value attribute
7135          * @param       integer $tabindex       tab index
7136          * @param       string  $value_yes      value attribute for yes option
7137          * @param       string  $value_no       value attribute for no option
7138          * @param       string  $text_yes       child text element for yes option
7139          * @param       string  $text_no        child text element for no option
7140          * @param       boolean $isAdmin        have admin right or not
7141          * @return      void
7142          */
7143         function input_yesno($name, $value_current, $tabindex = 0, $value_yes = 1, $value_no = 0, $text_yes = _YES, $text_no = _NO, $isAdmin = 0)
7144         {
7145                 $id = preg_replace('#\[|\]#', '-', $name);
7146                 $id_yes = $id . $value_yes;
7147                 $id_no  = $id . $value_no;
7148                 
7149                 /* yes option */
7150                 echo '<input type="radio" id="' . Entity::hsc($id_yes) . '" name="' . Entity::hsc($name) . '" value="' . Entity::hsc($value_yes) . '"';
7151                 if ( $name=="admin" )
7152                 {
7153                         echo ' onclick="selectCanLogin(true);"';
7154                 }
7155                 if ( $value_current == $value_yes )
7156                 {
7157                         echo " tabindex='$tabindex' checked='checked'";
7158                 }
7159                 echo " />\n";
7160                 echo '<label for="' . Entity::hsc($id_yes) . '">' . Entity::hsc($text_yes) . "</label>\n";
7161                 
7162                 /* no option */
7163                 echo '<input type="radio" id="' . Entity::hsc($id_no) . '" name="' . Entity::hsc($name) . '" value="' . Entity::hsc($value_no) . '"';
7164                 if ( $name=="admin" )
7165                 {
7166                         echo ' onclick="selectCanLogin(false);"';
7167                 }
7168                 if ( $value_current != $value_yes )
7169                 {
7170                         echo " tabindex='$tabindex' checked='checked'";
7171                 }
7172                 if ($isAdmin && $name=="canlogin")
7173                 {
7174                         echo ' disabled="disabled"';
7175                 }
7176                 echo " />\n";
7177                 echo '<label for="' . Entity::hsc($id_no) . '">' . Entity::hsc($text_no) . "</label>\n";
7178                 
7179                 return;
7180         }
7181 }