]> git.mxchange.org Git - friendica.git/blob - mod/admin.php
Merge pull request #927 from annando/master
[friendica.git] / mod / admin.php
1 <?php
2
3  /**
4   * Friendica admin
5   */
6 require_once("include/remoteupdate.php");
7
8
9 /**
10  * @param App $a
11  */
12 function admin_post(&$a){
13
14
15         if(!is_site_admin()) {
16                 return;
17         }
18
19         // do not allow a page manager to access the admin panel at all.
20
21         if(x($_SESSION,'submanage') && intval($_SESSION['submanage']))
22                 return;
23
24
25
26         // urls
27         if ($a->argc > 1){
28                 switch ($a->argv[1]){
29                         case 'site':
30                                 admin_page_site_post($a);
31                                 break;
32                         case 'users':
33                                 admin_page_users_post($a);
34                                 break;
35                         case 'plugins':
36                                 if ($a->argc > 2 && 
37                                         is_file("addon/".$a->argv[2]."/".$a->argv[2].".php")){
38                                                 @include_once("addon/".$a->argv[2]."/".$a->argv[2].".php");
39                                                 if(function_exists($a->argv[2].'_plugin_admin_post')) {
40                                                         $func = $a->argv[2].'_plugin_admin_post';
41                                                         $func($a);
42                                                 }
43                                 }
44                                 goaway($a->get_baseurl(true) . '/admin/plugins/' . $a->argv[2] );
45                                 return; // NOTREACHED
46                                 break;
47                         case 'themes':
48                                 $theme = $a->argv[2];
49                                 if (is_file("view/theme/$theme/config.php")){
50                                         require_once("view/theme/$theme/config.php");
51                                         if (function_exists("theme_admin_post")){
52                                                 theme_admin_post($a);
53                                         }
54                                 }
55                                 info(t('Theme settings updated.'));
56                                 if(is_ajax()) return;
57
58                                 goaway($a->get_baseurl(true) . '/admin/themes/' . $theme );
59                                 return;
60                                 break;
61                         case 'logs':
62                                 admin_page_logs_post($a);
63                                 break;
64                         case 'dbsync':
65                                 admin_page_dbsync_post($a);
66                                 break;
67                         case 'update':
68                                 admin_page_remoteupdate_post($a);
69                                 break;
70                 }
71         }
72
73         goaway($a->get_baseurl(true) . '/admin' );
74         return; // NOTREACHED
75 }
76
77 /**
78  * @param App $a
79  * @return string
80  */
81 function admin_content(&$a) {
82
83         if(!is_site_admin()) {
84                 return login(false);
85         }
86
87         if(x($_SESSION,'submanage') && intval($_SESSION['submanage']))
88                 return "";
89
90         if (function_exists("apc_delete")) {
91                 $toDelete = new APCIterator('user', APC_ITER_VALUE);
92                 apc_delete($toDelete);
93         }
94
95         /**
96          * Side bar links
97          */
98
99         // array( url, name, extra css classes )
100         $aside = Array(
101                 'site'   =>     Array($a->get_baseurl(true)."/admin/site/", t("Site") , "site"),
102                 'users'  =>     Array($a->get_baseurl(true)."/admin/users/", t("Users") , "users"),
103                 'plugins'=>     Array($a->get_baseurl(true)."/admin/plugins/", t("Plugins") , "plugins"),
104                 'themes' =>     Array($a->get_baseurl(true)."/admin/themes/", t("Themes") , "themes"),
105                 'dbsync' => Array($a->get_baseurl(true)."/admin/dbsync/", t('DB updates'), "dbsync"),
106                 //'update' =>   Array($a->get_baseurl(true)."/admin/update/", t("Software Update") , "update")
107         );
108
109         /* get plugins admin page */
110
111         $r = q("SELECT name FROM `addon` WHERE `plugin_admin`=1");
112         $aside['plugins_admin']=Array();
113         foreach ($r as $h){
114                 $plugin =$h['name'];
115                 $aside['plugins_admin'][] = Array($a->get_baseurl(true)."/admin/plugins/".$plugin, $plugin, "plugin");
116                 // temp plugins with admin
117                 $a->plugins_admin[] = $plugin;
118         }
119
120         $aside['logs'] = Array($a->get_baseurl(true)."/admin/logs/", t("Logs"), "logs");
121
122         $t = get_markup_template("admin_aside.tpl");
123         $a->page['aside'] .= replace_macros( $t, array(
124                         '$admin' => $aside, 
125                         '$admtxt' => t('Admin'),
126                         '$plugadmtxt' => t('Plugin Features'),
127                         '$logtxt' => t('Logs'),
128                         '$h_pending' => t('User registrations waiting for confirmation'),
129                         '$admurl'=> $a->get_baseurl(true)."/admin/"
130         ));
131
132
133
134         /**
135          * Page content
136          */
137         $o = '';
138         // urls
139         if ($a->argc > 1){
140                 switch ($a->argv[1]){
141                         case 'site':
142                                 $o = admin_page_site($a);
143                                 break;
144                         case 'users':
145                                 $o = admin_page_users($a);
146                                 break;
147                         case 'plugins':
148                                 $o = admin_page_plugins($a);
149                                 break;
150                         case 'themes':
151                                 $o = admin_page_themes($a);
152                                 break;
153                         case 'logs':
154                                 $o = admin_page_logs($a);
155                                 break;
156                         case 'dbsync':
157                                 $o = admin_page_dbsync($a);
158                                 break;
159                         case 'update':
160                                 $o = admin_page_remoteupdate($a);
161                                 break;
162                         default:
163                                 notice( t("Item not found.") );
164                 }
165         } else {
166                 $o = admin_page_summary($a);
167         }
168
169         if(is_ajax()) {
170                 echo $o; 
171                 killme();
172                 return '';
173         } else {
174                 return $o;
175         }
176
177
178
179 /**
180  * Admin Summary Page
181  * @param App $a
182  * @return string
183  */
184 function admin_page_summary(&$a) {
185         $r = q("SELECT `page-flags`, COUNT(uid) as `count` FROM `user` GROUP BY `page-flags`");
186         $accounts = Array(
187                 Array( t('Normal Account'), 0),
188                 Array( t('Soapbox Account'), 0),
189                 Array( t('Community/Celebrity Account'), 0),
190                 Array( t('Automatic Friend Account'), 0),
191                 Array( t('Blog Account'), 0),
192                 Array( t('Private Forum'), 0)
193         );
194
195         $users=0;
196         foreach ($r as $u){ $accounts[$u['page-flags']][1] = $u['count']; $users+= $u['count']; }
197
198         logger('accounts: ' . print_r($accounts,true),LOGGER_DATA);
199
200         $r = q("SELECT COUNT(id) as `count` FROM `register`");
201         $pending = $r[0]['count'];
202
203         $r = q("select count(*) as total from deliverq where 1");
204         $deliverq = (($r) ? $r[0]['total'] : 0);
205
206         $r = q("select count(*) as total from queue where 1");
207         $queue = (($r) ? $r[0]['total'] : 0);
208
209         // We can do better, but this is a quick queue status
210
211         $queues = array( 'label' => t('Message queues'), 'deliverq' => $deliverq, 'queue' => $queue );
212
213
214         $t = get_markup_template("admin_summary.tpl");
215         return replace_macros($t, array(
216                 '$title' => t('Administration'),
217                 '$page' => t('Summary'),
218                 '$queues' => $queues,
219                 '$users' => Array( t('Registered users'), $users),
220                 '$accounts' => $accounts,
221                 '$pending' => Array( t('Pending registrations'), $pending),
222                 '$version' => Array( t('Version'), FRIENDICA_VERSION),
223                 '$build' =>  get_config('system','build'),
224                 '$plugins' => Array( t('Active plugins'), $a->plugins )
225         ));
226 }
227
228
229 /**
230  * Admin Site Page
231  *  @param App $a
232  */
233 function admin_page_site_post(&$a){
234         if (!x($_POST,"page_site")){
235                 return;
236         }
237
238         check_form_security_token_redirectOnErr('/admin/site', 'admin_site');
239
240         // relocate
241         if (x($_POST,'relocate') && x($_POST,'relocate_url') && $_POST['relocate_url']!=""){
242                 $new_url = $_POST['relocate_url'];
243                 $new_url = rtrim($new_url,"/");
244                 
245                 $parsed = @parse_url($new_url);
246                 if (!$parsed || (!x($parsed,'host') || !x($parsed,'scheme'))) {
247                         notice(t("Can not parse base url. Must have at least <scheme>://<domain>"));
248                         goaway($a->get_baseurl(true) . '/admin/site' );
249                 }
250                 
251                 /* steps:
252                  * replace all "baseurl" to "new_url" in config, profile, term, items and contacts
253                  * send relocate for every local user
254                  * */
255                 
256                 $old_url = $a->get_baseurl(true);
257                 
258                 function update_table($table_name, $fields, $old_url, $new_url) {
259                         global $db, $a;
260                         
261                         $dbold = dbesc($old_url);
262                         $dbnew = dbesc($new_url);
263                         
264                         $upd = array();
265                         foreach ($fields as $f) {
266                                 $upd[] = "`$f` = REPLACE(`$f`, '$dbold', '$dbnew')";
267                         }
268                         
269                         $upds = implode(", ", $upd);
270                         
271                         
272                         
273                         $q = sprintf("UPDATE %s SET %s;", $table_name, $upds);
274                         $r = q($q);
275                         if (!$r) {
276                                 notice( "Falied updating '$table_name': " . $db->error );
277                                 goaway($a->get_baseurl(true) . '/admin/site' );
278                         }
279                 }
280                 
281                 // update tables
282                 update_table("profile", array('photo', 'thumb'), $old_url, $new_url);
283                 update_table("term", array('url'), $old_url, $new_url);
284                 update_table("contact", array('photo','thumb','micro','url','nurl','request','notify','poll','confirm','poco'), $old_url, $new_url);
285                 update_table("item", array('owner-link','owner-avatar','author-name','author-link','author-avatar','body','plink','tag'), $old_url, $new_url);
286
287                 // update config
288                 $a->set_baseurl($new_url);
289                 set_config('system','url',$new_url);
290                 
291                 // send relocate
292                 $users = q("SELECT uid FROM user WHERE account_removed = 0 AND account_expired = 0");
293                 
294                 foreach ($users as $user) {
295                         proc_run('php', 'include/notifier.php', 'relocate', $user['uid']);
296                 }
297
298                 info("Relocation started. Could take a while to complete.");
299                 
300                 goaway($a->get_baseurl(true) . '/admin/site' );
301         }
302         // end relocate
303         
304         $sitename               =       ((x($_POST,'sitename'))                 ? notags(trim($_POST['sitename']))              : '');
305         $banner                 =       ((x($_POST,'banner'))                   ? trim($_POST['banner'])                        : false);
306         $info                   =       ((x($_POST,'info'))                     ? trim($_POST['info'])                  : false);
307         $language               =       ((x($_POST,'language'))                 ? notags(trim($_POST['language']))              : '');
308         $theme                  =       ((x($_POST,'theme'))                    ? notags(trim($_POST['theme']))                 : '');
309         $theme_mobile           =       ((x($_POST,'theme_mobile'))             ? notags(trim($_POST['theme_mobile']))          : '');
310         $maximagesize           =       ((x($_POST,'maximagesize'))             ? intval(trim($_POST['maximagesize']))          :  0);
311         $maximagelength         =       ((x($_POST,'maximagelength'))           ? intval(trim($_POST['maximagelength']))        :  MAX_IMAGE_LENGTH);
312         $jpegimagequality       =       ((x($_POST,'jpegimagequality'))         ? intval(trim($_POST['jpegimagequality']))      :  JPEG_QUALITY);
313
314
315         $register_policy        =       ((x($_POST,'register_policy'))          ? intval(trim($_POST['register_policy']))       :  0);
316         $daily_registrations    =       ((x($_POST,'max_daily_registrations'))  ? intval(trim($_POST['max_daily_registrations']))       :0);
317         $abandon_days           =       ((x($_POST,'abandon_days'))             ? intval(trim($_POST['abandon_days']))          :  0);
318
319         $register_text          =       ((x($_POST,'register_text'))            ? notags(trim($_POST['register_text']))         : '');
320
321         $allowed_sites          =       ((x($_POST,'allowed_sites'))            ? notags(trim($_POST['allowed_sites']))         : '');
322         $allowed_email          =       ((x($_POST,'allowed_email'))            ? notags(trim($_POST['allowed_email']))         : '');
323         $block_public           =       ((x($_POST,'block_public'))             ? True                                          : False);
324         $force_publish          =       ((x($_POST,'publish_all'))              ? True                                          : False);
325         $global_directory       =       ((x($_POST,'directory_submit_url'))     ? notags(trim($_POST['directory_submit_url']))  : '');
326         $thread_allow           =       ((x($_POST,'thread_allow'))             ? True                                          : False);
327         $newuser_private                =       ((x($_POST,'newuser_private'))          ? True                                          : False);
328         $enotify_no_content             =       ((x($_POST,'enotify_no_content'))       ? True                                          : False);
329         $private_addons                 =       ((x($_POST,'private_addons'))           ? True                                          : False);
330         $disable_embedded               =       ((x($_POST,'disable_embedded'))         ? True                                          : False);
331         $allow_users_remote_self        =       ((x($_POST,'allow_users_remote_self'))          ? True                                          : False);
332         
333         $no_multi_reg           =       ((x($_POST,'no_multi_reg'))             ? True                                          : False);
334         $no_openid              =       !((x($_POST,'no_openid'))               ? True                                          : False);
335         $no_regfullname         =       !((x($_POST,'no_regfullname'))          ? True                                          : False);
336         $no_utf                 =       !((x($_POST,'no_utf'))                  ? True                                          : False);
337         $no_community_page      =       !((x($_POST,'no_community_page'))       ? True                                          : False);
338
339         $verifyssl              =       ((x($_POST,'verifyssl'))                ? True                                          : False);
340         $proxyuser              =       ((x($_POST,'proxyuser'))                ? notags(trim($_POST['proxyuser']))             : '');
341         $proxy                  =       ((x($_POST,'proxy'))                    ? notags(trim($_POST['proxy']))                 : '');
342         $timeout                =       ((x($_POST,'timeout'))                  ? intval(trim($_POST['timeout']))               : 60);
343         $delivery_interval      =       ((x($_POST,'delivery_interval'))        ? intval(trim($_POST['delivery_interval']))     : 0);
344         $poll_interval          =       ((x($_POST,'poll_interval'))            ? intval(trim($_POST['poll_interval']))         : 0);
345         $maxloadavg             =       ((x($_POST,'maxloadavg'))               ? intval(trim($_POST['maxloadavg']))            : 50);
346         $dfrn_only              =       ((x($_POST,'dfrn_only'))                ? True                                          : False);
347         $ostatus_disabled       =       !((x($_POST,'ostatus_disabled'))        ? True                                          : False);
348         $ostatus_poll_interval  =       ((x($_POST,'ostatus_poll_interval'))    ? intval(trim($_POST['ostatus_poll_interval']))         :  0);
349         $diaspora_enabled       =       ((x($_POST,'diaspora_enabled'))         ? True                                          : False);
350         $ssl_policy             =       ((x($_POST,'ssl_policy'))               ? intval($_POST['ssl_policy'])                  : 0);
351         $old_share              =       ((x($_POST,'old_share'))                ? True                                          : False);
352         $hide_help              =       ((x($_POST,'hide_help'))                ? True                                          : False);
353         $suppress_language      =       ((x($_POST,'suppress_language'))        ? True                                          : False);
354         $use_fulltext_engine    =       ((x($_POST,'use_fulltext_engine'))      ? True                                          : False);
355         $itemcache              =       ((x($_POST,'itemcache'))                ? notags(trim($_POST['itemcache']))             : '');
356         $itemcache_duration     =       ((x($_POST,'itemcache_duration'))       ? intval($_POST['itemcache_duration'])          : 0);
357         $lockpath               =       ((x($_POST,'lockpath'))                 ? notags(trim($_POST['lockpath']))              : '');
358         $temppath               =       ((x($_POST,'temppath'))                 ? notags(trim($_POST['temppath']))              : '');
359         $basepath               =       ((x($_POST,'basepath'))                 ? notags(trim($_POST['basepath']))              : '');
360         $singleuser             =       ((x($_POST,'singleuser'))               ? notags(trim($_POST['singleuser']))            : '');
361         if($ssl_policy != intval(get_config('system','ssl_policy'))) {
362                 if($ssl_policy == SSL_POLICY_FULL) {
363                         q("update `contact` set 
364                                 `url`     = replace(`url`    , 'http:' , 'https:'),
365                                 `photo`   = replace(`photo`  , 'http:' , 'https:'),
366                                 `thumb`   = replace(`thumb`  , 'http:' , 'https:'),
367                                 `micro`   = replace(`micro`  , 'http:' , 'https:'),
368                                 `request` = replace(`request`, 'http:' , 'https:'),
369                                 `notify`  = replace(`notify` , 'http:' , 'https:'),
370                                 `poll`    = replace(`poll`   , 'http:' , 'https:'),
371                                 `confirm` = replace(`confirm`, 'http:' , 'https:'),
372                                 `poco`    = replace(`poco`   , 'http:' , 'https:')
373                                 where `self` = 1"
374                         );
375                         q("update `profile` set 
376                                 `photo`   = replace(`photo`  , 'http:' , 'https:'),
377                                 `thumb`   = replace(`thumb`  , 'http:' , 'https:')
378                                 where 1 "
379                         );
380                 }
381                 elseif($ssl_policy == SSL_POLICY_SELFSIGN) {
382                         q("update `contact` set 
383                                 `url`     = replace(`url`    , 'https:' , 'http:'),
384                                 `photo`   = replace(`photo`  , 'https:' , 'http:'),
385                                 `thumb`   = replace(`thumb`  , 'https:' , 'http:'),
386                                 `micro`   = replace(`micro`  , 'https:' , 'http:'),
387                                 `request` = replace(`request`, 'https:' , 'http:'),
388                                 `notify`  = replace(`notify` , 'https:' , 'http:'),
389                                 `poll`    = replace(`poll`   , 'https:' , 'http:'),
390                                 `confirm` = replace(`confirm`, 'https:' , 'http:'),
391                                 `poco`    = replace(`poco`   , 'https:' , 'http:')
392                                 where `self` = 1"
393                         );
394                         q("update `profile` set 
395                                 `photo`   = replace(`photo`  , 'https:' , 'http:'),
396                                 `thumb`   = replace(`thumb`  , 'https:' , 'http:')
397                                 where 1 "
398                         );
399                 }
400         }
401         set_config('system','ssl_policy',$ssl_policy);
402         set_config('system','delivery_interval',$delivery_interval);
403         set_config('system','poll_interval',$poll_interval);
404         set_config('system','maxloadavg',$maxloadavg);
405         set_config('config','sitename',$sitename);
406         if ($banner==""){
407                 // don't know why, but del_config doesn't work...
408                 q("DELETE FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
409                         dbesc("system"),
410                         dbesc("banner")
411                 );
412         } else {
413                 set_config('system','banner', $banner);
414         }
415         if ($info=="") {
416             del_config('config','info');
417         } else {
418             set_config('config','info',$info);
419         }
420         set_config('system','language', $language);
421         set_config('system','theme', $theme);
422         if ( $theme_mobile === '---' ) {
423                 del_config('system','mobile-theme');
424         } else {
425                 set_config('system','mobile-theme', $theme_mobile);
426         }
427         if ( $singleuser === '---' ) {
428             del_config('system','singleuser');
429         } else {
430             set_config('system','singleuser', $singleuser);
431         }
432         set_config('system','maximagesize', $maximagesize);
433         set_config('system','max_image_length', $maximagelength);
434         set_config('system','jpeg_quality', $jpegimagequality);
435
436         set_config('config','register_policy', $register_policy);
437         set_config('system','max_daily_registrations', $daily_registrations);
438         set_config('system','account_abandon_days', $abandon_days);
439         set_config('config','register_text', $register_text);
440         set_config('system','allowed_sites', $allowed_sites);
441         set_config('system','allowed_email', $allowed_email);
442         set_config('system','block_public', $block_public);
443         set_config('system','publish_all', $force_publish);
444         if ($global_directory==""){
445                 // don't know why, but del_config doesn't work...
446                 q("DELETE FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
447                         dbesc("system"),
448                         dbesc("directory_submit_url")
449                 );
450         } else {
451                 set_config('system','directory_submit_url', $global_directory);
452         }
453         set_config('system','thread_allow', $thread_allow);
454         set_config('system','newuser_private', $newuser_private);
455         set_config('system','enotify_no_content', $enotify_no_content);
456         set_config('system','disable_embedded', $disable_embedded);
457         set_config('system','allow_users_remote_self', $allow_users_remote_self);
458
459         set_config('system','block_extended_register', $no_multi_reg);
460         set_config('system','no_openid', $no_openid);
461         set_config('system','no_regfullname', $no_regfullname);
462         set_config('system','no_community_page', $no_community_page);
463         set_config('system','no_utf', $no_utf);
464         set_config('system','verifyssl', $verifyssl);
465         set_config('system','proxyuser', $proxyuser);
466         set_config('system','proxy', $proxy);
467         set_config('system','curl_timeout', $timeout);
468         set_config('system','dfrn_only', $dfrn_only);
469         set_config('system','ostatus_disabled', $ostatus_disabled);
470         set_config('system','ostatus_poll_interval', $ostatus_poll_interval);
471         set_config('system','diaspora_enabled', $diaspora_enabled);
472         set_config('config','private_addons', $private_addons);
473
474         set_config('system','old_share', $old_share);
475         set_config('system','hide_help', $hide_help);
476         set_config('system','use_fulltext_engine', $use_fulltext_engine);
477         set_config('system','itemcache', $itemcache);
478         set_config('system','itemcache_duration', $itemcache_duration);
479         set_config('system','lockpath', $lockpath);
480         set_config('system','temppath', $temppath);
481         set_config('system','basepath', $basepath);
482
483         info( t('Site settings updated.') . EOL);
484         goaway($a->get_baseurl(true) . '/admin/site' );
485         return; // NOTREACHED
486
487 }
488
489 /**
490  * @param  App $a
491  * @return string
492  */
493 function admin_page_site(&$a) {
494
495         /* Installed langs */
496         $lang_choices = array();
497         $langs = glob('view/*/strings.php');
498
499         if(is_array($langs) && count($langs)) {
500                 if(! in_array('view/en/strings.php',$langs))
501                         $langs[] = 'view/en/';
502                 asort($langs);
503                 foreach($langs as $l) {
504                         $t = explode("/",$l);
505                         $lang_choices[$t[1]] = $t[1];
506                 }
507         }
508
509         /* Installed themes */
510         $theme_choices = array();
511         $theme_choices_mobile = array();
512         $theme_choices_mobile["---"] = t("No special theme for mobile devices");
513         $files = glob('view/theme/*');
514         if($files) {
515                 foreach($files as $file) {
516                         $f = basename($file);
517                         $theme_name = ((file_exists($file . '/experimental')) ?  sprintf("%s - \x28Experimental\x29", $f) : $f);
518             if (file_exists($file . '/mobile')) {
519                 $theme_choices_mobile[$f] = $theme_name;
520             }
521                 else {
522                 $theme_choices[$f] = $theme_name;
523                         }
524                 }
525         }
526
527         /* OStatus conversation poll choices */
528         $ostatus_poll_choices = array(
529                 "-2" => t("Never"),
530                 "-1" => t("At post arrival"),
531                 "0" => t("Frequently"),
532                 "60" => t("Hourly"),
533                 "720" => t("Twice daily"),
534                 "1440" => t("Daily")
535             );
536
537         /* get user names to make the install a personal install of X */
538         $user_names = array();
539         $user_names['---'] = t('Multi user instance');
540         $users = q("SELECT username, nickname FROM `user`");
541         foreach ($users as $user) {
542             $user_names[$user['nickname']] = $user['username'];
543         }
544
545         /* Banner */
546         $banner = get_config('system','banner');
547         if($banner == false) 
548                 $banner = '<a href="http://friendica.com"><img id="logo-img" src="images/friendica-32.png" alt="logo" /></a><span id="logo-text"><a href="http://friendica.com">Friendica</a></span>';
549         $banner = htmlspecialchars($banner);
550         $info = get_config('config','info');
551         $info = htmlspecialchars($info);
552
553         //echo "<pre>"; var_dump($lang_choices); die("</pre>");
554
555         /* Register policy */
556         $register_choices = Array(
557                 REGISTER_CLOSED => t("Closed"),
558                 REGISTER_APPROVE => t("Requires approval"),
559                 REGISTER_OPEN => t("Open")
560         ); 
561
562         $ssl_choices = array(
563                 SSL_POLICY_NONE => t("No SSL policy, links will track page SSL state"),
564                 SSL_POLICY_FULL => t("Force all links to use SSL"),
565                 SSL_POLICY_SELFSIGN => t("Self-signed certificate, use SSL for local links only (discouraged)")
566         );
567
568         $t = get_markup_template("admin_site.tpl");
569         return replace_macros($t, array(
570                 '$title' => t('Administration'),
571                 '$page' => t('Site'),
572                 '$submit' => t('Save Settings'),
573                 '$registration' => t('Registration'),
574                 '$upload' => t('File upload'),
575                 '$corporate' => t('Policies'),
576                 '$advanced' => t('Advanced'),
577                 '$performance' => t('Performance'),
578                 '$relocate'=> t('Relocate - WARNING: advanced function. Could make this server unreachable.'),
579                 '$baseurl' => $a->get_baseurl(true),
580                 // name, label, value, help string, extra data...
581                 '$sitename'             => array('sitename', t("Site name"), htmlentities($a->config['sitename'], ENT_QUOTES), 'UTF-8'),
582                 '$banner'               => array('banner', t("Banner/Logo"), $banner, ""),
583                 '$info' => array('info',t('Additional Info'), $info, t('For public servers: you can add additional information here that will be listed at dir.friendica.com/siteinfo.')),
584                 '$language'             => array('language', t("System language"), get_config('system','language'), "", $lang_choices),
585                 '$theme'                => array('theme', t("System theme"), get_config('system','theme'), t("Default system theme - may be over-ridden by user profiles - <a href='#' id='cnftheme'>change theme settings</a>"), $theme_choices),
586                 '$theme_mobile'         => array('theme_mobile', t("Mobile system theme"), get_config('system','mobile-theme'), t("Theme for mobile devices"), $theme_choices_mobile),
587                 '$ssl_policy'           => array('ssl_policy', t("SSL link policy"), (string) intval(get_config('system','ssl_policy')), t("Determines whether generated links should be forced to use SSL"), $ssl_choices),
588                 '$old_share'            => array('old_share', t("Old style 'Share'"), get_config('system','old_share'), t("Deactivates the bbcode element 'share' for repeating items.")),
589                 '$hide_help'            => array('hide_help', t("Hide help entry from navigation menu"), get_config('system','hide_help'), t("Hides the menu entry for the Help pages from the navigation menu. You can still access it calling /help directly.")),
590                 '$singleuser'           => array('singleuser', t("Single user instance"), get_config('system','singleuser'), t("Make this instance multi-user or single-user for the named user"), $user_names),
591                 '$maximagesize'         => array('maximagesize', t("Maximum image size"), get_config('system','maximagesize'), t("Maximum size in bytes of uploaded images. Default is 0, which means no limits.")),
592                 '$maximagelength'               => array('maximagelength', t("Maximum image length"), get_config('system','max_image_length'), t("Maximum length in pixels of the longest side of uploaded images. Default is -1, which means no limits.")),
593                 '$jpegimagequality'             => array('jpegimagequality', t("JPEG image quality"), get_config('system','jpeg_quality'), t("Uploaded JPEGS will be saved at this quality setting [0-100]. Default is 100, which is full quality.")),
594
595                 '$register_policy'      => array('register_policy', t("Register policy"), $a->config['register_policy'], "", $register_choices),
596                 '$daily_registrations'  => array('max_daily_registrations', t("Maximum Daily Registrations"), get_config('system', 'max_daily_registrations'), t("If registration is permitted above, this sets the maximum number of new user registrations to accept per day.  If register is set to closed, this setting has no effect.")),
597                 '$register_text'        => array('register_text', t("Register text"), htmlentities($a->config['register_text'], ENT_QUOTES, 'UTF-8'), t("Will be displayed prominently on the registration page.")),
598                 '$abandon_days'         => array('abandon_days', t('Accounts abandoned after x days'), get_config('system','account_abandon_days'), t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.')),
599                 '$allowed_sites'        => array('allowed_sites', t("Allowed friend domains"), get_config('system','allowed_sites'), t("Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains")),
600                 '$allowed_email'        => array('allowed_email', t("Allowed email domains"), get_config('system','allowed_email'), t("Comma separated list of domains which are allowed in email addresses for registrations to this site. Wildcards are accepted. Empty to allow any domains")),
601                 '$block_public'         => array('block_public', t("Block public"), get_config('system','block_public'), t("Check to block public access to all otherwise public personal pages on this site unless you are currently logged in.")),
602                 '$force_publish'        => array('publish_all', t("Force publish"), get_config('system','publish_all'), t("Check to force all profiles on this site to be listed in the site directory.")),
603                 '$global_directory'     => array('directory_submit_url', t("Global directory update URL"), get_config('system','directory_submit_url'), t("URL to update the global directory. If this is not set, the global directory is completely unavailable to the application.")),
604                 '$thread_allow'         => array('thread_allow', t("Allow threaded items"), get_config('system','thread_allow'), t("Allow infinite level threading for items on this site.")),
605                 '$newuser_private'      => array('newuser_private', t("Private posts by default for new users"), get_config('system','newuser_private'), t("Set default post permissions for all new members to the default privacy group rather than public.")),
606                 '$enotify_no_content'   => array('enotify_no_content', t("Don't include post content in email notifications"), get_config('system','enotify_no_content'), t("Don't include the content of a post/comment/private message/etc. in the email notifications that are sent out from this site, as a privacy measure.")),
607                 '$private_addons'       => array('private_addons', t("Disallow public access to addons listed in the apps menu."), get_config('config','private_addons'), t("Checking this box will restrict addons listed in the apps menu to members only.")),
608                 '$disable_embedded'     => array('disable_embedded', t("Don't embed private images in posts"), get_config('system','disable_embedded'), t("Don't replace locally-hosted private photos in posts with an embedded copy of the image. This means that contacts who receive posts containing private photos will have to authenticate and load each image, which may take a while.")),
609                 '$allow_users_remote_self'      => array('allow_users_remote_self', t('Allow Users to set remote_self'), get_config('system','allow_users_remote_self'), t('With checking this, every user is allowed to mark every contact as a remote_self in the repair contact dialog. Setting this flag on a contact causes mirroring every posting of that contact in the users stream.')),
610                 '$no_multi_reg'         => array('no_multi_reg', t("Block multiple registrations"),  get_config('system','block_extended_register'), t("Disallow users to register additional accounts for use as pages.")),
611                 '$no_openid'            => array('no_openid', t("OpenID support"), !get_config('system','no_openid'), t("OpenID support for registration and logins.")),
612                 '$no_regfullname'       => array('no_regfullname', t("Fullname check"), !get_config('system','no_regfullname'), t("Force users to register with a space between firstname and lastname in Full name, as an antispam measure")),
613                 '$no_utf'               => array('no_utf', t("UTF-8 Regular expressions"), !get_config('system','no_utf'), t("Use PHP UTF8 regular expressions")),
614                 '$no_community_page'    => array('no_community_page', t("Show Community Page"), !get_config('system','no_community_page'), t("Display a Community page showing all recent public postings on this site.")),
615                 '$ostatus_disabled'     => array('ostatus_disabled', t("Enable OStatus support"), !get_config('system','ostatus_disabled'), t("Provide built-in OStatus \x28identi.ca, status.net, etc.\x29 compatibility. All communications in OStatus are public, so privacy warnings will be occasionally displayed.")),    
616                 '$ostatus_poll_interval'        => array('ostatus_poll_interval', t("OStatus conversation completion interval"), (string) intval(get_config('system','ostatus_poll_interval')), t("How often shall the poller check for new entries in OStatus conversations? This can be a very ressource task."), $ostatus_poll_choices),
617                 '$diaspora_enabled'     => array('diaspora_enabled', t("Enable Diaspora support"), get_config('system','diaspora_enabled'), t("Provide built-in Diaspora network compatibility.")),     
618                 '$dfrn_only'            => array('dfrn_only', t('Only allow Friendica contacts'), get_config('system','dfrn_only'), t("All contacts must use Friendica protocols. All other built-in communication protocols disabled.")),
619                 '$verifyssl'            => array('verifyssl', t("Verify SSL"), get_config('system','verifyssl'), t("If you wish, you can turn on strict certificate checking. This will mean you cannot connect (at all) to self-signed SSL sites.")),
620                 '$proxyuser'            => array('proxyuser', t("Proxy user"), get_config('system','proxyuser'), ""),
621                 '$proxy'                => array('proxy', t("Proxy URL"), get_config('system','proxy'), ""),
622                 '$timeout'              => array('timeout', t("Network timeout"), (x(get_config('system','curl_timeout'))?get_config('system','curl_timeout'):60), t("Value is in seconds. Set to 0 for unlimited (not recommended).")),
623                 '$delivery_interval'    => array('delivery_interval', t("Delivery interval"), (x(get_config('system','delivery_interval'))?get_config('system','delivery_interval'):2), t("Delay background delivery processes by this many seconds to reduce system load. Recommend: 4-5 for shared hosts, 2-3 for virtual private servers. 0-1 for large dedicated servers.")),
624                 '$poll_interval'        => array('poll_interval', t("Poll interval"), (x(get_config('system','poll_interval'))?get_config('system','poll_interval'):2), t("Delay background polling processes by this many seconds to reduce system load. If 0, use delivery interval.")),
625                 '$maxloadavg'           => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")),
626
627                 '$use_fulltext_engine'  => array('use_fulltext_engine', t("Use MySQL full text engine"), get_config('system','use_fulltext_engine'), t("Activates the full text engine. Speeds up search - but can only search for four and more characters.")),
628                 '$suppress_language'    => array('suppress_language', t("Suppress Language"), get_config('system','suppress_language'), t("Suppress language information in meta information about a posting.")),
629                 '$itemcache'            => array('itemcache', t("Path to item cache"), get_config('system','itemcache'), "The item caches buffers generated bbcode and external images."),
630                 '$itemcache_duration'   => array('itemcache_duration', t("Cache duration in seconds"), get_config('system','itemcache_duration'), t("How long should the cache files be hold? Default value is 86400 seconds (One day).")),
631                 '$lockpath'             => array('lockpath', t("Path for lock file"), get_config('system','lockpath'), "The lock file is used to avoid multiple pollers at one time. Only define a folder here."),
632                 '$temppath'             => array('temppath', t("Temp path"), get_config('system','temppath'), "If you have a restricted system where the webserver can't access the system temp path, enter another path here."),
633                 '$basepath'             => array('basepath', t("Base path to installation"), get_config('system','basepath'), "If the system cannot detect the correct path to your installation, enter the correct path here. This setting should only be set if you are using a restricted system and symbolic links to your webroot."),
634                 
635                 '$relocate_url'     => array('relocate_url', t("New base url"), $a->get_baseurl(), "Change base url for this server. Sends relocate message to all DFRN contacts of all users."),
636                 
637         '$form_security_token' => get_form_security_token("admin_site"),
638
639         ));
640
641 }
642
643
644 function admin_page_dbsync(&$a) {
645
646         $o = '';
647
648         if($a->argc > 3 && intval($a->argv[3]) && $a->argv[2] === 'mark') {
649                 set_config('database', 'update_' . intval($a->argv[3]), 'success');
650                 $curr = get_config('system','build');
651                 if(intval($curr) == intval($a->argv[3]))
652                         set_config('system','build',intval($curr) + 1);
653                 info( t('Update has been marked successful') . EOL);
654                 goaway($a->get_baseurl(true) . '/admin/dbsync');
655         }
656
657         if($a->argc > 2 && intval($a->argv[2])) {
658                 require_once('update.php');
659                 $func = 'update_' . intval($a->argv[2]);
660                 if(function_exists($func)) {
661                         $retval = $func();
662                         if($retval === UPDATE_FAILED) {
663                                 $o .= sprintf( t('Executing %s failed. Check system logs.'), $func); 
664                         }
665                         elseif($retval === UPDATE_SUCCESS) {
666                                 $o .= sprintf( t('Update %s was successfully applied.', $func));
667                                 set_config('database',$func, 'success');
668                         }
669                         else
670                                 $o .= sprintf( t('Update %s did not return a status. Unknown if it succeeded.'), $func);
671                 }
672                 else
673                         $o .= sprintf( t('Update function %s could not be found.'), $func);
674                 return $o;
675         }
676
677         $failed = array();
678         $r = q("select k, v from config where `cat` = 'database' ");
679         if(count($r)) {
680                 foreach($r as $rr) {
681                         $upd = intval(substr($rr['k'],7));
682                         if($upd < 1139 || $rr['v'] === 'success')
683                                 continue;
684                         $failed[] = $upd;
685                 }
686         }
687         if(! count($failed))
688                 return '<h3>' . t('No failed updates.') . '</h3>';
689
690         $o = replace_macros(get_markup_template('failed_updates.tpl'),array(
691                 '$base' => $a->get_baseurl(true),
692                 '$banner' => t('Failed Updates'),
693                 '$desc' => t('This does not include updates prior to 1139, which did not return a status.'),
694                 '$mark' => t('Mark success (if update was manually applied)'),
695                 '$apply' => t('Attempt to execute this update step automatically'),
696                 '$failed' => $failed
697         ));
698
699         return $o;
700
701 }
702
703 /**
704  * Users admin page
705  *
706  * @param App $a
707  */
708 function admin_page_users_post(&$a){
709         $pending = ( x($_POST, 'pending') ? $_POST['pending'] : Array() );
710         $users = ( x($_POST, 'user') ? $_POST['user'] : Array() );
711         $nu_name = ( x($_POST, 'new_user_name') ? $_POST['new_user_name'] : ''); 
712   $nu_nickname = ( x($_POST, 'new_user_nickname') ? $_POST['new_user_nickname'] : ''); 
713   $nu_email = ( x($_POST, 'new_user_email') ? $_POST['new_user_email'] : '');
714
715   check_form_security_token_redirectOnErr('/admin/users', 'admin_users');
716
717   if (!($nu_name==="") && !($nu_email==="") && !($nu_nickname==="")) { 
718       require_once('include/user.php'); 
719       require_once('include/email.php'); 
720       $result = create_user( array('username'=>$nu_name, 'email'=>$nu_email, 'nickname'=>$nu_nickname, 'verified'=>1)  ); 
721       if(! $result['success']) { 
722                     notice($result['message']); 
723                     return; 
724       } 
725       $nu = $result['user']; 
726       $email_tpl = get_intltext_template("register_adminadd_eml.tpl"); 
727       $email_tpl = replace_macros($email_tpl, array( 
728                     '$sitename' => $a->config['sitename'], 
729                     '$siteurl' =>  $a->get_baseurl(), 
730                     '$username' => $nu['username'], 
731                     '$email' => $nu['email'], 
732                     '$password' => $result['password'], 
733                     '$uid' => $nu['uid'] )); 
734  
735       $res = mail($nu['email'], email_header_encode( sprintf( t('Registration details for %s'), $a->config['sitename']),'UTF-8'), 
736                     $email_tpl,  
737                     'From: ' . 'Administrator' . '@' . $_SERVER['SERVER_NAME'] . "\n" 
738                     . 'Content-type: text/plain; charset=UTF-8' . "\n" 
739                     . 'Content-transfer-encoding: 8bit' ); 
740       if ($res) { 
741                     info( t('Registration successful. Email send to user').EOL ); 
742       } 
743   }
744
745         if (x($_POST,'page_users_block')){
746                 foreach($users as $uid){
747                         q("UPDATE `user` SET `blocked`=1-`blocked` WHERE `uid`=%s",
748                                 intval( $uid )
749                         );
750                 }
751                 notice( sprintf( tt("%s user blocked/unblocked", "%s users blocked/unblocked", count($users)), count($users)) );
752         }
753         if (x($_POST,'page_users_delete')){
754                 require_once("include/Contact.php");
755                 foreach($users as $uid){
756                         user_remove($uid);
757                 }
758                 notice( sprintf( tt("%s user deleted", "%s users deleted", count($users)), count($users)) );
759         }
760
761         if (x($_POST,'page_users_approve')){
762                 require_once("mod/regmod.php");
763                 foreach($pending as $hash){
764                         user_allow($hash);
765                 }
766         }
767         if (x($_POST,'page_users_deny')){
768                 require_once("mod/regmod.php");
769                 foreach($pending as $hash){
770                         user_deny($hash);
771                 }
772         }
773         goaway($a->get_baseurl(true) . '/admin/users' );
774         return; // NOTREACHED
775 }
776
777 /**
778  * @param App $a
779  * @return string
780  */
781 function admin_page_users(&$a){
782         if ($a->argc>2) {
783                 $uid = $a->argv[3];
784                 $user = q("SELECT username, blocked FROM `user` WHERE `uid`=%d", intval($uid));
785                 if (count($user)==0){
786                         notice( 'User not found' . EOL);
787                         goaway($a->get_baseurl(true) . '/admin/users' );
788                         return ''; // NOTREACHED
789                 }
790                 switch($a->argv[2]){
791                         case "delete":{
792                 check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't');
793                                 // delete user
794                                 require_once("include/Contact.php");
795                                 user_remove($uid);
796
797                                 notice( sprintf(t("User '%s' deleted"), $user[0]['username']) . EOL);
798                         }; break;
799                         case "block":{
800                 check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't');
801                                 q("UPDATE `user` SET `blocked`=%d WHERE `uid`=%s",
802                                         intval( 1-$user[0]['blocked'] ),
803                                         intval( $uid )
804                                 );
805                                 notice( sprintf( ($user[0]['blocked']?t("User '%s' unblocked"):t("User '%s' blocked")) , $user[0]['username']) . EOL);
806                         }; break;
807                 }
808                 goaway($a->get_baseurl(true) . '/admin/users' );
809                 return ''; // NOTREACHED
810
811         }
812
813         /* get pending */
814         $pending = q("SELECT `register`.*, `contact`.`name`, `user`.`email`
815                                  FROM `register`
816                                  LEFT JOIN `contact` ON `register`.`uid` = `contact`.`uid`
817                                  LEFT JOIN `user` ON `register`.`uid` = `user`.`uid`;");
818
819
820         /* get users */
821
822         $total = q("SELECT count(*) as total FROM `user` where 1");
823         if(count($total)) {
824                 $a->set_pager_total($total[0]['total']);
825                 $a->set_pager_itemspage(100);
826         }
827
828
829         $users = q("SELECT `user` . * , `contact`.`name` , `contact`.`url` , `contact`.`micro`, `lastitem`.`lastitem_date`, `user`.`account_expired`
830                                 FROM
831                                         (SELECT MAX(`item`.`changed`) as `lastitem_date`, `item`.`uid`
832                                         FROM `item`
833                                         WHERE `item`.`type` = 'wall'
834                                         GROUP BY `item`.`uid`) AS `lastitem`
835                                                  RIGHT OUTER JOIN `user` ON `user`.`uid` = `lastitem`.`uid`,
836                                            `contact`
837                                 WHERE
838                                            `user`.`uid` = `contact`.`uid`
839                                                 AND `user`.`verified` =1
840                                         AND `contact`.`self` =1
841                                 ORDER BY `contact`.`name` LIMIT %d, %d
842                                 ",
843                                 intval($a->pager['start']),
844                                 intval($a->pager['itemspage'])
845                                 );
846
847         function _setup_users($e){
848                 $a = get_app();
849
850                 $adminlist = explode(",", str_replace(" ", "", $a->config['admin_email']));
851
852                 $accounts = Array(
853                         t('Normal Account'),
854                         t('Soapbox Account'),
855                         t('Community/Celebrity Account'),
856                         t('Automatic Friend Account')
857                 );
858                 $e['page-flags'] = $accounts[$e['page-flags']];
859                 $e['register_date'] = relative_date($e['register_date']);
860                 $e['login_date'] = relative_date($e['login_date']);
861                 $e['lastitem_date'] = relative_date($e['lastitem_date']);
862                 //$e['is_admin'] = ($e['email'] === $a->config['admin_email']);
863                 $e['is_admin'] = in_array($e['email'], $adminlist);
864                 $e['deleted'] = ($e['account_removed']?relative_date($e['account_expires_on']):False);
865                 return $e;
866         }
867         $users = array_map("_setup_users", $users);
868
869
870         // Get rid of dashes in key names, Smarty3 can't handle them
871         // and extracting deleted users
872
873         $tmp_users = Array();
874         $deleted = Array();
875
876         while(count($users)) {
877                 $new_user = Array();
878                 foreach( array_pop($users) as $k => $v) {
879                         $k = str_replace('-','_',$k);
880                         $new_user[$k] = $v;
881                 }
882                 if($new_user['deleted']) {
883                         array_push($deleted, $new_user);
884                 }
885                 else {
886                         array_push($tmp_users, $new_user);
887                 }
888         }
889         //Reversing the two array, and moving $tmp_users to $users
890         array_reverse($deleted);
891         while(count($tmp_users)) {
892                 array_push($users, array_pop($tmp_users));
893         }
894
895         $t = get_markup_template("admin_users.tpl");
896         $o = replace_macros($t, array(
897                 // strings //
898                 '$title' => t('Administration'),
899                 '$page' => t('Users'),
900                 '$submit' => t('Add User'),
901                 '$select_all' => t('select all'),
902                 '$h_pending' => t('User registrations waiting for confirm'),
903                 '$h_deleted' => t('User waiting for permanent deletion'),
904                 '$th_pending' => array( t('Request date'), t('Name'), t('Email') ),
905                 '$no_pending' =>  t('No registrations.'),
906                 '$approve' => t('Approve'),
907                 '$deny' => t('Deny'),
908                 '$delete' => t('Delete'),
909                 '$block' => t('Block'),
910                 '$unblock' => t('Unblock'),
911         '$siteadmin' => t('Site admin'),
912         '$accountexpired' => t('Account expired'),
913                 
914                 '$h_users' => t('Users'),
915                 '$h_newuser' => t('New User'),
916                 '$th_deleted' => array( t('Name'), t('Email'), t('Register date'), t('Last login'), t('Last item'), t('Deleted since') ),
917                 '$th_users' => array( t('Name'), t('Email'), t('Register date'), t('Last login'), t('Last item'),  t('Account') ),
918
919                 '$confirm_delete_multi' => t('Selected users will be deleted!\n\nEverything these users had posted on this site will be permanently deleted!\n\nAre you sure?'),
920                 '$confirm_delete' => t('The user {0} will be deleted!\n\nEverything this user has posted on this site will be permanently deleted!\n\nAre you sure?'),
921
922         '$form_security_token' => get_form_security_token("admin_users"),
923
924                 // values //
925                 '$baseurl' => $a->get_baseurl(true),
926
927                 '$pending' => $pending,
928                 'deleted' => $deleted,
929                 '$users' => $users,
930                 '$newusername'  => array('new_user_name', t("Name"), '', t("Name of the new user.")), 
931     '$newusernickname'  => array('new_user_nickname', t("Nickname"), '', t("Nickname of the new user.")), 
932     '$newuseremail'  => array('new_user_email', t("Email"), '', t("Email address of the new user.")),
933         ));
934         $o .= paginate($a);
935         return $o;
936 }
937
938
939 /**
940  * Plugins admin page
941  *
942  * @param App $a
943  * @return string
944  */
945 function admin_page_plugins(&$a){
946
947         /**
948          * Single plugin
949          */
950         if ($a->argc == 3){
951                 $plugin = $a->argv[2];
952                 if (!is_file("addon/$plugin/$plugin.php")){
953                         notice( t("Item not found.") );
954                         return '';
955                 }
956
957                 if (x($_GET,"a") && $_GET['a']=="t"){
958                         check_form_security_token_redirectOnErr('/admin/plugins', 'admin_themes', 't');
959
960                         // Toggle plugin status
961                         $idx = array_search($plugin, $a->plugins);
962                         if ($idx !== false){
963                                 unset($a->plugins[$idx]);
964                                 uninstall_plugin($plugin);
965                                 info( sprintf( t("Plugin %s disabled."), $plugin ) );
966                         } else {
967                                 $a->plugins[] = $plugin;
968                                 install_plugin($plugin);
969                                 info( sprintf( t("Plugin %s enabled."), $plugin ) );
970                         }
971                         set_config("system","addon", implode(", ",$a->plugins));
972                         goaway($a->get_baseurl(true) . '/admin/plugins' );
973                         return ''; // NOTREACHED
974                 }
975                 // display plugin details
976                 require_once('library/markdown.php');
977
978                 if (in_array($plugin, $a->plugins)){
979                         $status="on"; $action= t("Disable");
980                 } else {
981                         $status="off"; $action= t("Enable");
982                 }
983
984                 $readme=Null;
985                 if (is_file("addon/$plugin/README.md")){
986                         $readme = file_get_contents("addon/$plugin/README.md");
987                         $readme = Markdown($readme);
988                 } else if (is_file("addon/$plugin/README")){
989                         $readme = "<pre>". file_get_contents("addon/$plugin/README") ."</pre>";
990                 }
991
992                 $admin_form="";
993                 if (is_array($a->plugins_admin) && in_array($plugin, $a->plugins_admin)){
994                         @require_once("addon/$plugin/$plugin.php");
995                         $func = $plugin.'_plugin_admin';
996                         $func($a, $admin_form);
997                 }
998
999                 $t = get_markup_template("admin_plugins_details.tpl");
1000
1001                 return replace_macros($t, array(
1002                         '$title' => t('Administration'),
1003                         '$page' => t('Plugins'),
1004                         '$toggle' => t('Toggle'),
1005                         '$settings' => t('Settings'),
1006                         '$baseurl' => $a->get_baseurl(true),
1007
1008                         '$plugin' => $plugin,
1009                         '$status' => $status,
1010                         '$action' => $action,
1011                         '$info' => get_plugin_info($plugin),
1012                         '$str_author' => t('Author: '),
1013                         '$str_maintainer' => t('Maintainer: '),
1014
1015                         '$admin_form' => $admin_form,
1016                         '$function' => 'plugins',
1017                         '$screenshot' => '',
1018                         '$readme' => $readme,
1019
1020                         '$form_security_token' => get_form_security_token("admin_themes"),
1021                 ));
1022         }
1023
1024
1025
1026         /**
1027          * List plugins
1028          */
1029
1030         $plugins = array();
1031         $files = glob("addon/*/");
1032         if($files) {
1033                 foreach($files as $file) {      
1034                         if (is_dir($file)){
1035                                 list($tmp, $id)=array_map("trim", explode("/",$file));
1036                                 $info = get_plugin_info($id);
1037                                 $plugins[] = array( $id, (in_array($id,  $a->plugins)?"on":"off") , $info);
1038                         }
1039                 }
1040         }
1041
1042         $t = get_markup_template("admin_plugins.tpl");
1043         return replace_macros($t, array(
1044                 '$title' => t('Administration'),
1045                 '$page' => t('Plugins'),
1046                 '$submit' => t('Save Settings'),
1047                 '$baseurl' => $a->get_baseurl(true),
1048                 '$function' => 'plugins',       
1049                 '$plugins' => $plugins,
1050         '$form_security_token' => get_form_security_token("admin_themes"),
1051         ));
1052 }
1053
1054 /**
1055  * @param array $themes
1056  * @param string $th
1057  * @param int $result
1058  */
1059 function toggle_theme(&$themes,$th,&$result) {
1060         for($x = 0; $x < count($themes); $x ++) {
1061                 if($themes[$x]['name'] === $th) {
1062                         if($themes[$x]['allowed']) {
1063                                 $themes[$x]['allowed'] = 0;
1064                                 $result = 0;
1065                         }
1066                         else {
1067                                 $themes[$x]['allowed'] = 1;
1068                                 $result = 1;
1069                         }
1070                 }
1071         }
1072 }
1073
1074 /**
1075  * @param array $themes
1076  * @param string $th
1077  * @return int
1078  */
1079 function theme_status($themes,$th) {
1080         for($x = 0; $x < count($themes); $x ++) {
1081                 if($themes[$x]['name'] === $th) {
1082                         if($themes[$x]['allowed']) {
1083                                 return 1;
1084                         }
1085                         else {
1086                                 return 0;
1087                         }
1088                 }
1089         }
1090         return 0;
1091 }
1092
1093
1094 /**
1095  * @param array $themes
1096  * @return string
1097  */
1098 function rebuild_theme_table($themes) {
1099         $o = '';
1100         if(count($themes)) {
1101                 foreach($themes as $th) {
1102                         if($th['allowed']) {
1103                                 if(strlen($o))
1104                                         $o .= ',';
1105                                 $o .= $th['name'];
1106                         }
1107                 }
1108         }
1109         return $o;
1110 }
1111
1112
1113 /**
1114  * Themes admin page
1115  *
1116  * @param App $a
1117  * @return string
1118  */
1119 function admin_page_themes(&$a){
1120
1121         $allowed_themes_str = get_config('system','allowed_themes');
1122         $allowed_themes_raw = explode(',',$allowed_themes_str);
1123         $allowed_themes = array();
1124         if(count($allowed_themes_raw))
1125                 foreach($allowed_themes_raw as $x)
1126                         if(strlen(trim($x)))
1127                                 $allowed_themes[] = trim($x);
1128
1129         $themes = array();
1130     $files = glob('view/theme/*');
1131     if($files) {
1132         foreach($files as $file) {
1133             $f = basename($file);
1134             $is_experimental = intval(file_exists($file . '/experimental'));
1135                         $is_supported = 1-(intval(file_exists($file . '/unsupported'))); // Is not used yet
1136                         $is_allowed = intval(in_array($f,$allowed_themes));
1137                         $themes[] = array('name' => $f, 'experimental' => $is_experimental, 'supported' => $is_supported, 'allowed' => $is_allowed);
1138         }
1139     }
1140
1141         if(! count($themes)) {
1142                 notice( t('No themes found.'));
1143                 return '';
1144         }
1145
1146         /**
1147          * Single theme
1148          */
1149
1150         if ($a->argc == 3){
1151                 $theme = $a->argv[2];
1152                 if(! is_dir("view/theme/$theme")){
1153                         notice( t("Item not found.") );
1154                         return '';
1155                 }
1156
1157                 if (x($_GET,"a") && $_GET['a']=="t"){
1158                         check_form_security_token_redirectOnErr('/admin/themes', 'admin_themes', 't');
1159
1160                         // Toggle theme status
1161
1162                         toggle_theme($themes,$theme,$result);
1163                         $s = rebuild_theme_table($themes);
1164                         if($result) {
1165                                 install_theme($theme);
1166                                 info( sprintf('Theme %s enabled.',$theme));
1167                         }
1168                         else {
1169                                 uninstall_theme($theme);
1170                                 info( sprintf('Theme %s disabled.',$theme));
1171                         }
1172
1173                         set_config('system','allowed_themes',$s);
1174                         goaway($a->get_baseurl(true) . '/admin/themes' );
1175                         return ''; // NOTREACHED
1176                 }
1177
1178                 // display theme details
1179                 require_once('library/markdown.php');
1180
1181                 if (theme_status($themes,$theme)) {
1182                         $status="on"; $action= t("Disable");
1183                 } else {
1184                         $status="off"; $action= t("Enable");
1185                 }
1186
1187                 $readme=Null;
1188                 if (is_file("view/theme/$theme/README.md")){
1189                         $readme = file_get_contents("view/theme/$theme/README.md");
1190                         $readme = Markdown($readme);
1191                 } else if (is_file("view/theme/$theme/README")){
1192                         $readme = "<pre>". file_get_contents("view/theme/$theme/README") ."</pre>";
1193                 }
1194
1195                 $admin_form="";
1196                 if (is_file("view/theme/$theme/config.php")){
1197                         require_once("view/theme/$theme/config.php");
1198                         if(function_exists("theme_admin")){
1199                                 $admin_form = theme_admin($a);
1200                         }
1201
1202                 }
1203
1204                 $screenshot = array( get_theme_screenshot($theme), t('Screenshot'));
1205                 if(! stristr($screenshot[0],$theme))
1206                         $screenshot = null;
1207
1208                 $t = get_markup_template("admin_plugins_details.tpl");
1209                 return replace_macros($t, array(
1210                         '$title' => t('Administration'),
1211                         '$page' => t('Themes'),
1212                         '$toggle' => t('Toggle'),
1213                         '$settings' => t('Settings'),
1214                         '$baseurl' => $a->get_baseurl(true),
1215
1216                         '$plugin' => $theme,
1217                         '$status' => $status,
1218                         '$action' => $action,
1219                         '$info' => get_theme_info($theme),
1220                         '$function' => 'themes',
1221                         '$admin_form' => $admin_form,
1222                         '$str_author' => t('Author: '),
1223                         '$str_maintainer' => t('Maintainer: '),
1224                         '$screenshot' => $screenshot,
1225                         '$readme' => $readme,
1226
1227                         '$form_security_token' => get_form_security_token("admin_themes"),
1228                 ));
1229         }
1230
1231         /**
1232          * List themes
1233          */
1234
1235         $xthemes = array();
1236         if($themes) {
1237                 foreach($themes as $th) {
1238                         $xthemes[] = array($th['name'],(($th['allowed']) ? "on" : "off"), get_theme_info($th['name']));
1239                 }
1240         }
1241
1242         $t = get_markup_template("admin_plugins.tpl");
1243         return replace_macros($t, array(
1244                 '$title' => t('Administration'),
1245                 '$page' => t('Themes'),
1246                 '$submit' => t('Save Settings'),
1247                 '$baseurl' => $a->get_baseurl(true),
1248                 '$function' => 'themes',
1249                 '$plugins' => $xthemes,
1250                 '$experimental' => t('[Experimental]'),
1251                 '$unsupported' => t('[Unsupported]'),
1252         '$form_security_token' => get_form_security_token("admin_themes"),
1253         ));
1254 }
1255
1256
1257 /**
1258  * Logs admin page
1259  *
1260  * @param App $a
1261  */
1262  
1263 function admin_page_logs_post(&$a) {
1264         if (x($_POST,"page_logs")) {
1265         check_form_security_token_redirectOnErr('/admin/logs', 'admin_logs');
1266
1267                 $logfile                =       ((x($_POST,'logfile'))          ? notags(trim($_POST['logfile']))       : '');
1268                 $debugging              =       ((x($_POST,'debugging'))        ? true                                                          : false);
1269                 $loglevel               =       ((x($_POST,'loglevel'))         ? intval(trim($_POST['loglevel']))      : 0);
1270
1271                 set_config('system','logfile', $logfile);
1272                 set_config('system','debugging',  $debugging);
1273                 set_config('system','loglevel', $loglevel);
1274
1275                 
1276         }
1277
1278         info( t("Log settings updated.") );
1279         goaway($a->get_baseurl(true) . '/admin/logs' );
1280         return; // NOTREACHED   
1281 }
1282
1283 /**
1284  * @param App $a
1285  * @return string
1286  */
1287 function admin_page_logs(&$a){
1288         
1289         $log_choices = Array(
1290                 LOGGER_NORMAL => 'Normal',
1291                 LOGGER_TRACE => 'Trace',
1292                 LOGGER_DEBUG => 'Debug',
1293                 LOGGER_DATA => 'Data',
1294                 LOGGER_ALL => 'All'
1295         );
1296         
1297         $t = get_markup_template("admin_logs.tpl");
1298
1299         $f = get_config('system','logfile');
1300
1301         $data = '';
1302
1303         if(!file_exists($f)) {
1304                 $data = t("Error trying to open <strong>$f</strong> log file.\r\n<br/>Check to see if file $f exist and is 
1305 readable.");
1306         }
1307         else {
1308                 $fp = fopen($f, 'r');
1309                 if(!$fp) {
1310                         $data = t("Couldn't open <strong>$f</strong> log file.\r\n<br/>Check to see if file $f is readable.");
1311                 }
1312                 else {
1313                         $fstat = fstat($fp);
1314                         $size = $fstat['size'];
1315                         if($size != 0)
1316                         {
1317                                 if($size > 5000000 || $size < 0)
1318                                         $size = 5000000;
1319                                 $seek = fseek($fp,0-$size,SEEK_END);
1320                                 if($seek === 0) {
1321                                         $data = escape_tags(fread($fp,$size));
1322                                         while(! feof($fp))
1323                                                 $data .= escape_tags(fread($fp,4096));
1324                                 }
1325                         }
1326                         fclose($fp);
1327                 }
1328         }                       
1329
1330         return replace_macros($t, array(
1331                 '$title' => t('Administration'),
1332                 '$page' => t('Logs'),
1333                 '$submit' => t('Save Settings'),
1334                 '$clear' => t('Clear'),
1335                 '$data' => $data,
1336                 '$baseurl' => $a->get_baseurl(true),
1337                 '$logname' =>  get_config('system','logfile'),
1338                 
1339                                                                         // name, label, value, help string, extra data...
1340                 '$debugging'            => array('debugging', t("Enable Debugging"),get_config('system','debugging'), ""),
1341                 '$logfile'                      => array('logfile', t("Log file"), get_config('system','logfile'), t("Must be writable by web server. Relative to your Friendica top-level directory.")),
1342                 '$loglevel'             => array('loglevel', t("Log level"), get_config('system','loglevel'), "", $log_choices),
1343
1344         '$form_security_token' => get_form_security_token("admin_logs"),
1345         ));
1346 }
1347
1348 /**
1349  * @param App $a
1350  */
1351 function admin_page_remoteupdate_post(&$a) {
1352         // this function should be called via ajax post
1353         if(!is_site_admin()) {
1354                 return;
1355         }
1356
1357         
1358         if (x($_POST,'remotefile') && $_POST['remotefile']!=""){
1359                 $remotefile = $_POST['remotefile'];
1360                 $ftpdata = (x($_POST['ftphost'])?$_POST:false);
1361                 doUpdate($remotefile, $ftpdata);
1362         } else {
1363                 echo "No remote file to download. Abort!";
1364         }
1365
1366         killme();
1367 }
1368
1369 /**
1370  * @param App $a
1371  * @return string
1372  */
1373 function admin_page_remoteupdate(&$a) {
1374         if(!is_site_admin()) {
1375                 return login(false);
1376         }
1377
1378         $canwrite = canWeWrite();
1379         $canftp = function_exists('ftp_connect');
1380         
1381         $needupdate = true;
1382         $u = checkUpdate();
1383         if (!is_array($u)){
1384                 $needupdate = false;
1385                 $u = array('','','');
1386         }
1387         
1388         $tpl = get_markup_template("admin_remoteupdate.tpl");
1389         return replace_macros($tpl, array(
1390                 '$baseurl' => $a->get_baseurl(true),
1391                 '$submit' => t("Update now"),
1392                 '$close' => t("Close"),
1393                 '$localversion' => FRIENDICA_VERSION,
1394                 '$remoteversion' => $u[1],
1395                 '$needupdate' => $needupdate,
1396                 '$canwrite' => $canwrite,
1397                 '$canftp'       => $canftp,
1398                 '$ftphost'      => array('ftphost', t("FTP Host"), '',''),
1399                 '$ftppath'      => array('ftppath', t("FTP Path"), '/',''),
1400                 '$ftpuser'      => array('ftpuser', t("FTP User"), '',''),
1401                 '$ftppwd'       => array('ftppwd', t("FTP Password"), '',''),
1402                 '$remotefile'=>array('remotefile','', $u['2'],''),
1403         ));
1404         
1405 }