]> git.mxchange.org Git - friendica.git/blob - mod/admin.php
More "relocate":
[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         
332         $no_multi_reg           =       ((x($_POST,'no_multi_reg'))             ? True                                          : False);
333         $no_openid              =       !((x($_POST,'no_openid'))               ? True                                          : False);
334         $no_regfullname         =       !((x($_POST,'no_regfullname'))          ? True                                          : False);
335         $no_utf                 =       !((x($_POST,'no_utf'))                  ? True                                          : False);
336         $no_community_page      =       !((x($_POST,'no_community_page'))       ? True                                          : False);
337
338         $verifyssl              =       ((x($_POST,'verifyssl'))                ? True                                          : False);
339         $proxyuser              =       ((x($_POST,'proxyuser'))                ? notags(trim($_POST['proxyuser']))             : '');
340         $proxy                  =       ((x($_POST,'proxy'))                    ? notags(trim($_POST['proxy']))                 : '');
341         $timeout                =       ((x($_POST,'timeout'))                  ? intval(trim($_POST['timeout']))               : 60);
342         $delivery_interval      =       ((x($_POST,'delivery_interval'))        ? intval(trim($_POST['delivery_interval']))     : 0);
343         $poll_interval          =       ((x($_POST,'poll_interval'))            ? intval(trim($_POST['poll_interval']))         : 0);
344         $maxloadavg             =       ((x($_POST,'maxloadavg'))               ? intval(trim($_POST['maxloadavg']))            : 50);
345         $dfrn_only              =       ((x($_POST,'dfrn_only'))                ? True                                          : False);
346         $ostatus_disabled       =       !((x($_POST,'ostatus_disabled'))        ? True                                          : False);
347         $ostatus_poll_interval  =       ((x($_POST,'ostatus_poll_interval'))    ? intval(trim($_POST['ostatus_poll_interval']))         :  0);
348         $diaspora_enabled       =       ((x($_POST,'diaspora_enabled'))         ? True                                          : False);
349         $ssl_policy             =       ((x($_POST,'ssl_policy'))               ? intval($_POST['ssl_policy'])                  : 0);
350         $old_share              =       ((x($_POST,'old_share'))                ? True                                          : False);
351         $hide_help              =       ((x($_POST,'hide_help'))                ? True                                          : False);
352         $suppress_language      =       ((x($_POST,'suppress_language'))        ? True                                          : False);
353         $use_fulltext_engine    =       ((x($_POST,'use_fulltext_engine'))      ? True                                          : False);
354         $itemcache              =       ((x($_POST,'itemcache'))                ? notags(trim($_POST['itemcache']))             : '');
355         $itemcache_duration     =       ((x($_POST,'itemcache_duration'))       ? intval($_POST['itemcache_duration'])          : 0);
356         $lockpath               =       ((x($_POST,'lockpath'))                 ? notags(trim($_POST['lockpath']))              : '');
357         $temppath               =       ((x($_POST,'temppath'))                 ? notags(trim($_POST['temppath']))              : '');
358         $basepath               =       ((x($_POST,'basepath'))                 ? notags(trim($_POST['basepath']))              : '');
359         $singleuser             =       ((x($_POST,'singleuser'))               ? notags(trim($_POST['singleuser']))            : '');
360         if($ssl_policy != intval(get_config('system','ssl_policy'))) {
361                 if($ssl_policy == SSL_POLICY_FULL) {
362                         q("update `contact` set 
363                                 `url`     = replace(`url`    , 'http:' , 'https:'),
364                                 `photo`   = replace(`photo`  , 'http:' , 'https:'),
365                                 `thumb`   = replace(`thumb`  , 'http:' , 'https:'),
366                                 `micro`   = replace(`micro`  , 'http:' , 'https:'),
367                                 `request` = replace(`request`, 'http:' , 'https:'),
368                                 `notify`  = replace(`notify` , 'http:' , 'https:'),
369                                 `poll`    = replace(`poll`   , 'http:' , 'https:'),
370                                 `confirm` = replace(`confirm`, 'http:' , 'https:'),
371                                 `poco`    = replace(`poco`   , 'http:' , 'https:')
372                                 where `self` = 1"
373                         );
374                         q("update `profile` set 
375                                 `photo`   = replace(`photo`  , 'http:' , 'https:'),
376                                 `thumb`   = replace(`thumb`  , 'http:' , 'https:')
377                                 where 1 "
378                         );
379                 }
380                 elseif($ssl_policy == SSL_POLICY_SELFSIGN) {
381                         q("update `contact` set 
382                                 `url`     = replace(`url`    , 'https:' , 'http:'),
383                                 `photo`   = replace(`photo`  , 'https:' , 'http:'),
384                                 `thumb`   = replace(`thumb`  , 'https:' , 'http:'),
385                                 `micro`   = replace(`micro`  , 'https:' , 'http:'),
386                                 `request` = replace(`request`, 'https:' , 'http:'),
387                                 `notify`  = replace(`notify` , 'https:' , 'http:'),
388                                 `poll`    = replace(`poll`   , 'https:' , 'http:'),
389                                 `confirm` = replace(`confirm`, 'https:' , 'http:'),
390                                 `poco`    = replace(`poco`   , 'https:' , 'http:')
391                                 where `self` = 1"
392                         );
393                         q("update `profile` set 
394                                 `photo`   = replace(`photo`  , 'https:' , 'http:'),
395                                 `thumb`   = replace(`thumb`  , 'https:' , 'http:')
396                                 where 1 "
397                         );
398                 }
399         }
400         set_config('system','ssl_policy',$ssl_policy);
401         set_config('system','delivery_interval',$delivery_interval);
402         set_config('system','poll_interval',$poll_interval);
403         set_config('system','maxloadavg',$maxloadavg);
404         set_config('config','sitename',$sitename);
405         if ($banner==""){
406                 // don't know why, but del_config doesn't work...
407                 q("DELETE FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
408                         dbesc("system"),
409                         dbesc("banner")
410                 );
411         } else {
412                 set_config('system','banner', $banner);
413         }
414         if ($info=="") {
415             del_config('config','info');
416         } else {
417             set_config('config','info',$info);
418         }
419         set_config('system','language', $language);
420         set_config('system','theme', $theme);
421         if ( $theme_mobile === '---' ) {
422                 del_config('system','mobile-theme');
423         } else {
424                 set_config('system','mobile-theme', $theme_mobile);
425         }
426         if ( $singleuser === '---' ) {
427             del_config('system','singleuser');
428         } else {
429             set_config('system','singleuser', $singleuser);
430         }
431         set_config('system','maximagesize', $maximagesize);
432         set_config('system','max_image_length', $maximagelength);
433         set_config('system','jpeg_quality', $jpegimagequality);
434         
435         set_config('config','register_policy', $register_policy);
436         set_config('system','max_daily_registrations', $daily_registrations);
437         set_config('system','account_abandon_days', $abandon_days);
438         set_config('config','register_text', $register_text);
439         set_config('system','allowed_sites', $allowed_sites);
440         set_config('system','allowed_email', $allowed_email);
441         set_config('system','block_public', $block_public);
442         set_config('system','publish_all', $force_publish);
443         if ($global_directory==""){
444                 // don't know why, but del_config doesn't work...
445                 q("DELETE FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
446                         dbesc("system"),
447                         dbesc("directory_submit_url")
448                 );
449         } else {
450                 set_config('system','directory_submit_url', $global_directory);
451         }
452         set_config('system','thread_allow', $thread_allow);
453         set_config('system','newuser_private', $newuser_private);
454         set_config('system','enotify_no_content', $enotify_no_content);
455         set_config('system','disable_embedded', $disable_embedded);
456
457         set_config('system','block_extended_register', $no_multi_reg);
458         set_config('system','no_openid', $no_openid);
459         set_config('system','no_regfullname', $no_regfullname);
460         set_config('system','no_community_page', $no_community_page);
461         set_config('system','no_utf', $no_utf);
462         set_config('system','verifyssl', $verifyssl);
463         set_config('system','proxyuser', $proxyuser);
464         set_config('system','proxy', $proxy);
465         set_config('system','curl_timeout', $timeout);
466         set_config('system','dfrn_only', $dfrn_only);
467         set_config('system','ostatus_disabled', $ostatus_disabled);
468         set_config('system','ostatus_poll_interval', $ostatus_poll_interval);
469         set_config('system','diaspora_enabled', $diaspora_enabled);
470         set_config('config','private_addons', $private_addons);
471         
472         set_config('system','old_share', $old_share);
473         set_config('system','hide_help', $hide_help);
474         set_config('system','use_fulltext_engine', $use_fulltext_engine);
475         set_config('system','itemcache', $itemcache);
476         set_config('system','itemcache_duration', $itemcache_duration);
477         set_config('system','lockpath', $lockpath);
478         set_config('system','temppath', $temppath);
479         set_config('system','basepath', $basepath);
480         
481         info( t('Site settings updated.') . EOL);
482         goaway($a->get_baseurl(true) . '/admin/site' );
483         return; // NOTREACHED
484
485 }
486
487 /**
488  * @param  App $a
489  * @return string
490  */
491 function admin_page_site(&$a) {
492         
493         /* Installed langs */
494         $lang_choices = array();
495         $langs = glob('view/*/strings.php');
496         
497         if(is_array($langs) && count($langs)) {
498                 if(! in_array('view/en/strings.php',$langs))
499                         $langs[] = 'view/en/';
500                 asort($langs);
501                 foreach($langs as $l) {
502                         $t = explode("/",$l);
503                         $lang_choices[$t[1]] = $t[1];
504                 }
505         }
506         
507         /* Installed themes */
508         $theme_choices = array();
509         $theme_choices_mobile = array();
510         $theme_choices_mobile["---"] = t("No special theme for mobile devices");
511         $files = glob('view/theme/*');
512         if($files) {
513                 foreach($files as $file) {
514                         $f = basename($file);
515                         $theme_name = ((file_exists($file . '/experimental')) ?  sprintf("%s - \x28Experimental\x29", $f) : $f);
516             if (file_exists($file . '/mobile')) {
517                 $theme_choices_mobile[$f] = $theme_name;
518             }
519                 else {
520                 $theme_choices[$f] = $theme_name;
521                         }
522                 }
523         }
524
525         /* OStatus conversation poll choices */
526         $ostatus_poll_choices = array(
527                 "-1" => t("Never"),
528                 "0" => t("Frequently"),
529                 "60" => t("Hourly"),
530                 "720" => t("Twice daily"),
531                 "1440" => t("Daily")
532             );
533
534         /* get user names to make the install a personal install of X */
535         $user_names = array();
536         $user_names['---'] = t('Multi user instance');
537         $users = q("SELECT username, nickname FROM `user`");
538         foreach ($users as $user) {
539             $user_names[$user['nickname']] = $user['username'];
540         }
541
542         /* Banner */
543         $banner = get_config('system','banner');
544         if($banner == false) 
545                 $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>';
546         $banner = htmlspecialchars($banner);
547         $info = get_config('config','info');
548         $info = htmlspecialchars($info);
549
550         //echo "<pre>"; var_dump($lang_choices); die("</pre>");
551
552         /* Register policy */
553         $register_choices = Array(
554                 REGISTER_CLOSED => t("Closed"),
555                 REGISTER_APPROVE => t("Requires approval"),
556                 REGISTER_OPEN => t("Open")
557         ); 
558
559         $ssl_choices = array(
560                 SSL_POLICY_NONE => t("No SSL policy, links will track page SSL state"),
561                 SSL_POLICY_FULL => t("Force all links to use SSL"),
562                 SSL_POLICY_SELFSIGN => t("Self-signed certificate, use SSL for local links only (discouraged)")
563         );
564
565         $t = get_markup_template("admin_site.tpl");
566         return replace_macros($t, array(
567                 '$title' => t('Administration'),
568                 '$page' => t('Site'),
569                 '$submit' => t('Submit'),
570                 '$registration' => t('Registration'),
571                 '$upload' => t('File upload'),
572                 '$corporate' => t('Policies'),
573                 '$advanced' => t('Advanced'),
574                 '$performance' => t('Performance'),
575                 '$relocate'=> t('Relocate - WARNING: advanced function. Could make this server unreachable.'),
576                 
577                 '$baseurl' => $a->get_baseurl(true),
578                 // name, label, value, help string, extra data...
579                 '$sitename'             => array('sitename', t("Site name"), htmlentities($a->config['sitename'], ENT_QUOTES), 'UTF-8'),
580                 '$banner'               => array('banner', t("Banner/Logo"), $banner, ""),
581                 '$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.')),
582                 '$language'             => array('language', t("System language"), get_config('system','language'), "", $lang_choices),
583                 '$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),
584                 '$theme_mobile'         => array('theme_mobile', t("Mobile system theme"), get_config('system','mobile-theme'), t("Theme for mobile devices"), $theme_choices_mobile),
585                 '$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),
586                 '$old_share'            => array('old_share', t("Old style 'Share'"), get_config('system','old_share'), t("Deactivates the bbcode element 'share' for repeating items.")),
587                 '$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.")),
588                 '$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),
589                 '$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.")),
590                 '$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.")),
591                 '$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.")),
592
593                 '$register_policy'      => array('register_policy', t("Register policy"), $a->config['register_policy'], "", $register_choices),
594                 '$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.")),
595                 '$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.")),
596                 '$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.')),
597                 '$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")),
598                 '$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")),
599                 '$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.")),
600                 '$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.")),
601                 '$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.")),
602                 '$thread_allow'         => array('thread_allow', t("Allow threaded items"), get_config('system','thread_allow'), t("Allow infinite level threading for items on this site.")),
603                 '$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.")),
604                 '$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.")),
605                 '$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.")),
606                 '$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.")),
607                 
608                 '$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.")),
609                 '$no_openid'            => array('no_openid', t("OpenID support"), !get_config('system','no_openid'), t("OpenID support for registration and logins.")),
610                 '$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")),
611                 '$no_utf'               => array('no_utf', t("UTF-8 Regular expressions"), !get_config('system','no_utf'), t("Use PHP UTF8 regular expressions")),
612                 '$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.")),
613                 '$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.")),    
614                 '$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),
615                 '$diaspora_enabled'     => array('diaspora_enabled', t("Enable Diaspora support"), get_config('system','diaspora_enabled'), t("Provide built-in Diaspora network compatibility.")),     
616                 '$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.")),
617                 '$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.")),
618                 '$proxyuser'            => array('proxyuser', t("Proxy user"), get_config('system','proxyuser'), ""),
619                 '$proxy'                => array('proxy', t("Proxy URL"), get_config('system','proxy'), ""),
620                 '$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).")),
621                 '$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.")),
622                 '$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.")),
623                 '$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.")),
624
625                 '$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.")),
626                 '$suppress_language'    => array('suppress_language', t("Suppress Language"), get_config('system','suppress_language'), t("Suppress language information in meta information about a posting.")),
627                 '$itemcache'            => array('itemcache', t("Path to item cache"), get_config('system','itemcache'), "The item caches buffers generated bbcode and external images."),
628                 '$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).")),
629                 '$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."),
630                 '$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."),
631                 '$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."),
632                 
633                 '$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."),
634                 
635         '$form_security_token' => get_form_security_token("admin_site"),
636
637         ));
638
639 }
640
641
642 function admin_page_dbsync(&$a) {
643
644         $o = '';
645
646         if($a->argc > 3 && intval($a->argv[3]) && $a->argv[2] === 'mark') {
647                 set_config('database', 'update_' . intval($a->argv[3]), 'success');
648                 $curr = get_config('system','build');
649                 if(intval($curr) == intval($a->argv[3]))
650                         set_config('system','build',intval($curr) + 1);
651                 info( t('Update has been marked successful') . EOL);
652                 goaway($a->get_baseurl(true) . '/admin/dbsync');
653         }
654
655         if($a->argc > 2 && intval($a->argv[2])) {
656                 require_once('update.php');
657                 $func = 'update_' . intval($a->argv[2]);
658                 if(function_exists($func)) {
659                         $retval = $func();
660                         if($retval === UPDATE_FAILED) {
661                                 $o .= sprintf( t('Executing %s failed. Check system logs.'), $func); 
662                         }
663                         elseif($retval === UPDATE_SUCCESS) {
664                                 $o .= sprintf( t('Update %s was successfully applied.', $func));
665                                 set_config('database',$func, 'success');
666                         }
667                         else
668                                 $o .= sprintf( t('Update %s did not return a status. Unknown if it succeeded.'), $func);
669                 }
670                 else
671                         $o .= sprintf( t('Update function %s could not be found.'), $func);
672                 return $o;
673         }
674
675         $failed = array();
676         $r = q("select k, v from config where `cat` = 'database' ");
677         if(count($r)) {
678                 foreach($r as $rr) {
679                         $upd = intval(substr($rr['k'],7));
680                         if($upd < 1139 || $rr['v'] === 'success')
681                                 continue;
682                         $failed[] = $upd;
683                 }
684         }
685         if(! count($failed))
686                 return '<h3>' . t('No failed updates.') . '</h3>';
687
688         $o = replace_macros(get_markup_template('failed_updates.tpl'),array(
689                 '$base' => $a->get_baseurl(true),
690                 '$banner' => t('Failed Updates'),
691                 '$desc' => t('This does not include updates prior to 1139, which did not return a status.'),
692                 '$mark' => t('Mark success (if update was manually applied)'),
693                 '$apply' => t('Attempt to execute this update step automatically'),
694                 '$failed' => $failed
695         ));     
696
697         return $o;
698
699 }
700
701 /**
702  * Users admin page
703  *
704  * @param App $a
705  */
706 function admin_page_users_post(&$a){
707         $pending = ( x($_POST, 'pending') ? $_POST['pending'] : Array() );
708         $users = ( x($_POST, 'user') ? $_POST['user'] : Array() );
709         $nu_name = ( x($_POST, 'new_user_name') ? $_POST['new_user_name'] : ''); 
710   $nu_nickname = ( x($_POST, 'new_user_nickname') ? $_POST['new_user_nickname'] : ''); 
711   $nu_email = ( x($_POST, 'new_user_email') ? $_POST['new_user_email'] : '');
712
713   check_form_security_token_redirectOnErr('/admin/users', 'admin_users');
714     
715   if (!($nu_name==="") && !($nu_email==="") && !($nu_nickname==="")) { 
716       require_once('include/user.php'); 
717       require_once('include/email.php'); 
718       $result = create_user( array('username'=>$nu_name, 'email'=>$nu_email, 'nickname'=>$nu_nickname, 'verified'=>1)  ); 
719       if(! $result['success']) { 
720                     notice($result['message']); 
721                     return; 
722       } 
723       $nu = $result['user']; 
724       $email_tpl = get_intltext_template("register_adminadd_eml.tpl"); 
725       $email_tpl = replace_macros($email_tpl, array( 
726                     '$sitename' => $a->config['sitename'], 
727                     '$siteurl' =>  $a->get_baseurl(), 
728                     '$username' => $nu['username'], 
729                     '$email' => $nu['email'], 
730                     '$password' => $result['password'], 
731                     '$uid' => $nu['uid'] )); 
732  
733       $res = mail($nu['email'], email_header_encode( sprintf( t('Registration details for %s'), $a->config['sitename']),'UTF-8'), 
734                     $email_tpl,  
735                     'From: ' . 'Administrator' . '@' . $_SERVER['SERVER_NAME'] . "\n" 
736                     . 'Content-type: text/plain; charset=UTF-8' . "\n" 
737                     . 'Content-transfer-encoding: 8bit' ); 
738       if ($res) { 
739                     info( t('Registration successful. Email send to user').EOL ); 
740       } 
741   }
742         
743         if (x($_POST,'page_users_block')){
744                 foreach($users as $uid){
745                         q("UPDATE `user` SET `blocked`=1-`blocked` WHERE `uid`=%s",
746                                 intval( $uid )
747                         );
748                 }
749                 notice( sprintf( tt("%s user blocked/unblocked", "%s users blocked/unblocked", count($users)), count($users)) );
750         }
751         if (x($_POST,'page_users_delete')){
752                 require_once("include/Contact.php");
753                 foreach($users as $uid){
754                         user_remove($uid);
755                 }
756                 notice( sprintf( tt("%s user deleted", "%s users deleted", count($users)), count($users)) );
757         }
758         
759         if (x($_POST,'page_users_approve')){
760                 require_once("mod/regmod.php");
761                 foreach($pending as $hash){
762                         user_allow($hash);
763                 }
764         }
765         if (x($_POST,'page_users_deny')){
766                 require_once("mod/regmod.php");
767                 foreach($pending as $hash){
768                         user_deny($hash);
769                 }
770         }
771         goaway($a->get_baseurl(true) . '/admin/users' );
772         return; // NOTREACHED   
773 }
774
775 /**
776  * @param App $a
777  * @return string
778  */
779 function admin_page_users(&$a){
780         if ($a->argc>2) {
781                 $uid = $a->argv[3];
782                 $user = q("SELECT username, blocked FROM `user` WHERE `uid`=%d", intval($uid));
783                 if (count($user)==0){
784                         notice( 'User not found' . EOL);
785                         goaway($a->get_baseurl(true) . '/admin/users' );
786                         return ''; // NOTREACHED
787                 }               
788                 switch($a->argv[2]){
789                         case "delete":{
790                 check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't');
791                                 // delete user
792                                 require_once("include/Contact.php");
793                                 user_remove($uid);
794                                 
795                                 notice( sprintf(t("User '%s' deleted"), $user[0]['username']) . EOL);
796                         }; break;
797                         case "block":{
798                 check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't');
799                                 q("UPDATE `user` SET `blocked`=%d WHERE `uid`=%s",
800                                         intval( 1-$user[0]['blocked'] ),
801                                         intval( $uid )
802                                 );
803                                 notice( sprintf( ($user[0]['blocked']?t("User '%s' unblocked"):t("User '%s' blocked")) , $user[0]['username']) . EOL);
804                         }; break;
805                 }
806                 goaway($a->get_baseurl(true) . '/admin/users' );
807                 return ''; // NOTREACHED
808                 
809         }
810         
811         /* get pending */
812         $pending = q("SELECT `register`.*, `contact`.`name`, `user`.`email`
813                                  FROM `register`
814                                  LEFT JOIN `contact` ON `register`.`uid` = `contact`.`uid`
815                                  LEFT JOIN `user` ON `register`.`uid` = `user`.`uid`;");
816         
817         
818         /* get users */
819
820         $total = q("SELECT count(*) as total FROM `user` where 1");
821         if(count($total)) {
822                 $a->set_pager_total($total[0]['total']);
823                 $a->set_pager_itemspage(100);
824         }
825         
826         
827         $users = q("SELECT `user` . * , `contact`.`name` , `contact`.`url` , `contact`.`micro`, `lastitem`.`lastitem_date`, `user`.`account_expired`
828                                 FROM
829                                         (SELECT MAX(`item`.`changed`) as `lastitem_date`, `item`.`uid`
830                                         FROM `item`
831                                         WHERE `item`.`type` = 'wall'
832                                         GROUP BY `item`.`uid`) AS `lastitem`
833                                                  RIGHT OUTER JOIN `user` ON `user`.`uid` = `lastitem`.`uid`,
834                                            `contact`
835                                 WHERE
836                                            `user`.`uid` = `contact`.`uid`
837                                                 AND `user`.`verified` =1
838                                         AND `contact`.`self` =1
839                                 ORDER BY `contact`.`name` LIMIT %d, %d
840                                 ",
841                                 intval($a->pager['start']),
842                                 intval($a->pager['itemspage'])
843                                 );
844                                         
845         function _setup_users($e){
846         $a = get_app();
847                 $accounts = Array(
848                         t('Normal Account'), 
849                         t('Soapbox Account'),
850                         t('Community/Celebrity Account'),
851                         t('Automatic Friend Account')
852                 );
853                 $e['page-flags'] = $accounts[$e['page-flags']];
854                 $e['register_date'] = relative_date($e['register_date']);
855                 $e['login_date'] = relative_date($e['login_date']);
856                 $e['lastitem_date'] = relative_date($e['lastitem_date']);
857         $e['is_admin'] = ($e['email'] === $a->config['admin_email']);
858         $e['deleted'] = ($e['account_removed']?relative_date($e['account_expires_on']):False);
859                 return $e;
860         }
861         $users = array_map("_setup_users", $users);
862         
863         
864         // Get rid of dashes in key names, Smarty3 can't handle them
865         // and extracting deleted users
866         
867         $tmp_users = Array();
868         $deleted = Array();
869         
870         while(count($users)) {
871                 $new_user = Array();
872                 foreach( array_pop($users) as $k => $v) {
873                         $k = str_replace('-','_',$k);
874                         $new_user[$k] = $v;
875                 }
876                 if($new_user['deleted']) {
877                         array_push($deleted, $new_user);
878                 }
879                 else {
880                         array_push($tmp_users, $new_user);
881                 }
882         }
883         //Reversing the two array, and moving $tmp_users to $users
884         array_reverse($deleted);
885         while(count($tmp_users)) {
886                 array_push($users, array_pop($tmp_users));
887         }
888
889         $t = get_markup_template("admin_users.tpl");
890         $o = replace_macros($t, array(
891                 // strings //
892                 '$title' => t('Administration'),
893                 '$page' => t('Users'),
894                 '$submit' => t('Submit'),
895                 '$select_all' => t('select all'),
896                 '$h_pending' => t('User registrations waiting for confirm'),
897                 '$h_deleted' => t('User waiting for permanent deletion'),
898                 '$th_pending' => array( t('Request date'), t('Name'), t('Email') ),
899                 '$no_pending' =>  t('No registrations.'),
900                 '$approve' => t('Approve'),
901                 '$deny' => t('Deny'),
902                 '$delete' => t('Delete'),
903                 '$block' => t('Block'),
904                 '$unblock' => t('Unblock'),
905         '$siteadmin' => t('Site admin'),
906         '$accountexpired' => t('Account expired'),
907                 
908                 '$h_users' => t('Users'),
909                 '$h_newuser' => t('New User'),
910                 '$th_deleted' => array( t('Name'), t('Email'), t('Register date'), t('Last login'), t('Last item'), t('Deleted since') ),
911                 '$th_users' => array( t('Name'), t('Email'), t('Register date'), t('Last login'), t('Last item'),  t('Account') ),
912
913                 '$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?'),
914                 '$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?'),
915
916         '$form_security_token' => get_form_security_token("admin_users"),
917
918                 // values //
919                 '$baseurl' => $a->get_baseurl(true),
920
921                 '$pending' => $pending,
922                 'deleted' => $deleted,
923                 '$users' => $users,
924                 '$newusername'  => array('new_user_name', t("Name"), '', t("Name of the new user.")), 
925     '$newusernickname'  => array('new_user_nickname', t("Nickname"), '', t("Nickname of the new user.")), 
926     '$newuseremail'  => array('new_user_email', t("Email"), '', t("Email address of the new user.")),
927         ));
928         $o .= paginate($a);
929         return $o;
930 }
931
932
933 /**
934  * Plugins admin page
935  *
936  * @param App $a
937  * @return string
938  */
939 function admin_page_plugins(&$a){
940
941         /**
942          * Single plugin
943          */
944         if ($a->argc == 3){
945                 $plugin = $a->argv[2];
946                 if (!is_file("addon/$plugin/$plugin.php")){
947                         notice( t("Item not found.") );
948                         return '';
949                 }
950
951                 if (x($_GET,"a") && $_GET['a']=="t"){
952                         check_form_security_token_redirectOnErr('/admin/plugins', 'admin_themes', 't');
953
954                         // Toggle plugin status
955                         $idx = array_search($plugin, $a->plugins);
956                         if ($idx !== false){
957                                 unset($a->plugins[$idx]);
958                                 uninstall_plugin($plugin);
959                                 info( sprintf( t("Plugin %s disabled."), $plugin ) );
960                         } else {
961                                 $a->plugins[] = $plugin;
962                                 install_plugin($plugin);
963                                 info( sprintf( t("Plugin %s enabled."), $plugin ) );
964                         }
965                         set_config("system","addon", implode(", ",$a->plugins));
966                         goaway($a->get_baseurl(true) . '/admin/plugins' );
967                         return ''; // NOTREACHED
968                 }
969                 // display plugin details
970                 require_once('library/markdown.php');
971
972                 if (in_array($plugin, $a->plugins)){
973                         $status="on"; $action= t("Disable");
974                 } else {
975                         $status="off"; $action= t("Enable");
976                 }
977
978                 $readme=Null;
979                 if (is_file("addon/$plugin/README.md")){
980                         $readme = file_get_contents("addon/$plugin/README.md");
981                         $readme = Markdown($readme);
982                 } else if (is_file("addon/$plugin/README")){
983                         $readme = "<pre>". file_get_contents("addon/$plugin/README") ."</pre>";
984                 }
985
986                 $admin_form="";
987                 if (is_array($a->plugins_admin) && in_array($plugin, $a->plugins_admin)){
988                         @require_once("addon/$plugin/$plugin.php");
989                         $func = $plugin.'_plugin_admin';
990                         $func($a, $admin_form);
991                 }
992
993                 $t = get_markup_template("admin_plugins_details.tpl");
994
995                 return replace_macros($t, array(
996                         '$title' => t('Administration'),
997                         '$page' => t('Plugins'),
998                         '$toggle' => t('Toggle'),
999                         '$settings' => t('Settings'),
1000                         '$baseurl' => $a->get_baseurl(true),
1001
1002                         '$plugin' => $plugin,
1003                         '$status' => $status,
1004                         '$action' => $action,
1005                         '$info' => get_plugin_info($plugin),
1006                         '$str_author' => t('Author: '),
1007                         '$str_maintainer' => t('Maintainer: '),
1008
1009                         '$admin_form' => $admin_form,
1010                         '$function' => 'plugins',
1011                         '$screenshot' => '',
1012                         '$readme' => $readme,
1013
1014                         '$form_security_token' => get_form_security_token("admin_themes"),
1015                 ));
1016         }
1017
1018
1019
1020         /**
1021          * List plugins
1022          */
1023
1024         $plugins = array();
1025         $files = glob("addon/*/");
1026         if($files) {
1027                 foreach($files as $file) {      
1028                         if (is_dir($file)){
1029                                 list($tmp, $id)=array_map("trim", explode("/",$file));
1030                                 $info = get_plugin_info($id);
1031                                 $plugins[] = array( $id, (in_array($id,  $a->plugins)?"on":"off") , $info);
1032                         }
1033                 }
1034         }
1035
1036         $t = get_markup_template("admin_plugins.tpl");
1037         return replace_macros($t, array(
1038                 '$title' => t('Administration'),
1039                 '$page' => t('Plugins'),
1040                 '$submit' => t('Submit'),
1041                 '$baseurl' => $a->get_baseurl(true),
1042                 '$function' => 'plugins',       
1043                 '$plugins' => $plugins,
1044         '$form_security_token' => get_form_security_token("admin_themes"),
1045         ));
1046 }
1047
1048 /**
1049  * @param array $themes
1050  * @param string $th
1051  * @param int $result
1052  */
1053 function toggle_theme(&$themes,$th,&$result) {
1054         for($x = 0; $x < count($themes); $x ++) {
1055                 if($themes[$x]['name'] === $th) {
1056                         if($themes[$x]['allowed']) {
1057                                 $themes[$x]['allowed'] = 0;
1058                                 $result = 0;
1059                         }
1060                         else {
1061                                 $themes[$x]['allowed'] = 1;
1062                                 $result = 1;
1063                         }
1064                 }
1065         }
1066 }
1067
1068 /**
1069  * @param array $themes
1070  * @param string $th
1071  * @return int
1072  */
1073 function theme_status($themes,$th) {
1074         for($x = 0; $x < count($themes); $x ++) {
1075                 if($themes[$x]['name'] === $th) {
1076                         if($themes[$x]['allowed']) {
1077                                 return 1;
1078                         }
1079                         else {
1080                                 return 0;
1081                         }
1082                 }
1083         }
1084         return 0;
1085 }
1086
1087
1088 /**
1089  * @param array $themes
1090  * @return string
1091  */
1092 function rebuild_theme_table($themes) {
1093         $o = '';
1094         if(count($themes)) {
1095                 foreach($themes as $th) {
1096                         if($th['allowed']) {
1097                                 if(strlen($o))
1098                                         $o .= ',';
1099                                 $o .= $th['name'];
1100                         }
1101                 }
1102         }
1103         return $o;
1104 }
1105
1106
1107 /**
1108  * Themes admin page
1109  *
1110  * @param App $a
1111  * @return string
1112  */
1113 function admin_page_themes(&$a){
1114
1115         $allowed_themes_str = get_config('system','allowed_themes');
1116         $allowed_themes_raw = explode(',',$allowed_themes_str);
1117         $allowed_themes = array();
1118         if(count($allowed_themes_raw))
1119                 foreach($allowed_themes_raw as $x)
1120                         if(strlen(trim($x)))
1121                                 $allowed_themes[] = trim($x);
1122
1123         $themes = array();
1124     $files = glob('view/theme/*');
1125     if($files) {
1126         foreach($files as $file) {
1127             $f = basename($file);
1128             $is_experimental = intval(file_exists($file . '/experimental'));
1129                         $is_supported = 1-(intval(file_exists($file . '/unsupported'))); // Is not used yet
1130                         $is_allowed = intval(in_array($f,$allowed_themes));
1131                         $themes[] = array('name' => $f, 'experimental' => $is_experimental, 'supported' => $is_supported, 'allowed' => $is_allowed);
1132         }
1133     }
1134
1135         if(! count($themes)) {
1136                 notice( t('No themes found.'));
1137                 return '';
1138         }
1139
1140         /**
1141          * Single theme
1142          */
1143
1144         if ($a->argc == 3){
1145                 $theme = $a->argv[2];
1146                 if(! is_dir("view/theme/$theme")){
1147                         notice( t("Item not found.") );
1148                         return '';
1149                 }
1150
1151                 if (x($_GET,"a") && $_GET['a']=="t"){
1152                         check_form_security_token_redirectOnErr('/admin/themes', 'admin_themes', 't');
1153
1154                         // Toggle theme status
1155
1156                         toggle_theme($themes,$theme,$result);
1157                         $s = rebuild_theme_table($themes);
1158                         if($result) {
1159                                 install_theme($theme);
1160                                 info( sprintf('Theme %s enabled.',$theme));
1161                         }
1162                         else {
1163                                 uninstall_theme($theme);
1164                                 info( sprintf('Theme %s disabled.',$theme));
1165                         }
1166
1167                         set_config('system','allowed_themes',$s);
1168                         goaway($a->get_baseurl(true) . '/admin/themes' );
1169                         return ''; // NOTREACHED
1170                 }
1171
1172                 // display theme details
1173                 require_once('library/markdown.php');
1174
1175                 if (theme_status($themes,$theme)) {
1176                         $status="on"; $action= t("Disable");
1177                 } else {
1178                         $status="off"; $action= t("Enable");
1179                 }
1180
1181                 $readme=Null;
1182                 if (is_file("view/theme/$theme/README.md")){
1183                         $readme = file_get_contents("view/theme/$theme/README.md");
1184                         $readme = Markdown($readme);
1185                 } else if (is_file("view/theme/$theme/README")){
1186                         $readme = "<pre>". file_get_contents("view/theme/$theme/README") ."</pre>";
1187                 }
1188
1189                 $admin_form="";
1190                 if (is_file("view/theme/$theme/config.php")){
1191                         require_once("view/theme/$theme/config.php");
1192                         if(function_exists("theme_admin")){
1193                                 $admin_form = theme_admin($a);
1194                         }
1195
1196                 }
1197
1198                 $screenshot = array( get_theme_screenshot($theme), t('Screenshot'));
1199                 if(! stristr($screenshot[0],$theme))
1200                         $screenshot = null;
1201
1202                 $t = get_markup_template("admin_plugins_details.tpl");
1203                 return replace_macros($t, array(
1204                         '$title' => t('Administration'),
1205                         '$page' => t('Themes'),
1206                         '$toggle' => t('Toggle'),
1207                         '$settings' => t('Settings'),
1208                         '$baseurl' => $a->get_baseurl(true),
1209
1210                         '$plugin' => $theme,
1211                         '$status' => $status,
1212                         '$action' => $action,
1213                         '$info' => get_theme_info($theme),
1214                         '$function' => 'themes',
1215                         '$admin_form' => $admin_form,
1216                         '$str_author' => t('Author: '),
1217                         '$str_maintainer' => t('Maintainer: '),
1218                         '$screenshot' => $screenshot,
1219                         '$readme' => $readme,
1220
1221                         '$form_security_token' => get_form_security_token("admin_themes"),
1222                 ));
1223         }
1224
1225         /**
1226          * List themes
1227          */
1228
1229         $xthemes = array();
1230         if($themes) {
1231                 foreach($themes as $th) {
1232                         $xthemes[] = array($th['name'],(($th['allowed']) ? "on" : "off"), get_theme_info($th['name']));
1233                 }
1234         }
1235
1236         $t = get_markup_template("admin_plugins.tpl");
1237         return replace_macros($t, array(
1238                 '$title' => t('Administration'),
1239                 '$page' => t('Themes'),
1240                 '$submit' => t('Submit'),
1241                 '$baseurl' => $a->get_baseurl(true),
1242                 '$function' => 'themes',
1243                 '$plugins' => $xthemes,
1244                 '$experimental' => t('[Experimental]'),
1245                 '$unsupported' => t('[Unsupported]'),
1246         '$form_security_token' => get_form_security_token("admin_themes"),
1247         ));
1248 }
1249
1250
1251 /**
1252  * Logs admin page
1253  *
1254  * @param App $a
1255  */
1256  
1257 function admin_page_logs_post(&$a) {
1258         if (x($_POST,"page_logs")) {
1259         check_form_security_token_redirectOnErr('/admin/logs', 'admin_logs');
1260
1261                 $logfile                =       ((x($_POST,'logfile'))          ? notags(trim($_POST['logfile']))       : '');
1262                 $debugging              =       ((x($_POST,'debugging'))        ? true                                                          : false);
1263                 $loglevel               =       ((x($_POST,'loglevel'))         ? intval(trim($_POST['loglevel']))      : 0);
1264
1265                 set_config('system','logfile', $logfile);
1266                 set_config('system','debugging',  $debugging);
1267                 set_config('system','loglevel', $loglevel);
1268
1269                 
1270         }
1271
1272         info( t("Log settings updated.") );
1273         goaway($a->get_baseurl(true) . '/admin/logs' );
1274         return; // NOTREACHED   
1275 }
1276
1277 /**
1278  * @param App $a
1279  * @return string
1280  */
1281 function admin_page_logs(&$a){
1282         
1283         $log_choices = Array(
1284                 LOGGER_NORMAL => 'Normal',
1285                 LOGGER_TRACE => 'Trace',
1286                 LOGGER_DEBUG => 'Debug',
1287                 LOGGER_DATA => 'Data',
1288                 LOGGER_ALL => 'All'
1289         );
1290         
1291         $t = get_markup_template("admin_logs.tpl");
1292
1293         $f = get_config('system','logfile');
1294
1295         $data = '';
1296
1297         if(!file_exists($f)) {
1298                 $data = t("Error trying to open <strong>$f</strong> log file.\r\n<br/>Check to see if file $f exist and is 
1299 readable.");
1300         }
1301         else {
1302                 $fp = fopen($f, 'r');
1303                 if(!$fp) {
1304                         $data = t("Couldn't open <strong>$f</strong> log file.\r\n<br/>Check to see if file $f is readable.");
1305                 }
1306                 else {
1307                         $fstat = fstat($fp);
1308                         $size = $fstat['size'];
1309                         if($size != 0)
1310                         {
1311                                 if($size > 5000000 || $size < 0)
1312                                         $size = 5000000;
1313                                 $seek = fseek($fp,0-$size,SEEK_END);
1314                                 if($seek === 0) {
1315                                         $data = escape_tags(fread($fp,$size));
1316                                         while(! feof($fp))
1317                                                 $data .= escape_tags(fread($fp,4096));
1318                                 }
1319                         }
1320                         fclose($fp);
1321                 }
1322         }                       
1323
1324         return replace_macros($t, array(
1325                 '$title' => t('Administration'),
1326                 '$page' => t('Logs'),
1327                 '$submit' => t('Submit'),
1328                 '$clear' => t('Clear'),
1329                 '$data' => $data,
1330                 '$baseurl' => $a->get_baseurl(true),
1331                 '$logname' =>  get_config('system','logfile'),
1332                 
1333                                                                         // name, label, value, help string, extra data...
1334                 '$debugging'            => array('debugging', t("Enable Debugging"),get_config('system','debugging'), ""),
1335                 '$logfile'                      => array('logfile', t("Log file"), get_config('system','logfile'), t("Must be writable by web server. Relative to your Friendica top-level directory.")),
1336                 '$loglevel'             => array('loglevel', t("Log level"), get_config('system','loglevel'), "", $log_choices),
1337
1338         '$form_security_token' => get_form_security_token("admin_logs"),
1339         ));
1340 }
1341
1342 /**
1343  * @param App $a
1344  */
1345 function admin_page_remoteupdate_post(&$a) {
1346         // this function should be called via ajax post
1347         if(!is_site_admin()) {
1348                 return;
1349         }
1350
1351         
1352         if (x($_POST,'remotefile') && $_POST['remotefile']!=""){
1353                 $remotefile = $_POST['remotefile'];
1354                 $ftpdata = (x($_POST['ftphost'])?$_POST:false);
1355                 doUpdate($remotefile, $ftpdata);
1356         } else {
1357                 echo "No remote file to download. Abort!";
1358         }
1359
1360         killme();
1361 }
1362
1363 /**
1364  * @param App $a
1365  * @return string
1366  */
1367 function admin_page_remoteupdate(&$a) {
1368         if(!is_site_admin()) {
1369                 return login(false);
1370         }
1371
1372         $canwrite = canWeWrite();
1373         $canftp = function_exists('ftp_connect');
1374         
1375         $needupdate = true;
1376         $u = checkUpdate();
1377         if (!is_array($u)){
1378                 $needupdate = false;
1379                 $u = array('','','');
1380         }
1381         
1382         $tpl = get_markup_template("admin_remoteupdate.tpl");
1383         return replace_macros($tpl, array(
1384                 '$baseurl' => $a->get_baseurl(true),
1385                 '$submit' => t("Update now"),
1386                 '$close' => t("Close"),
1387                 '$localversion' => FRIENDICA_VERSION,
1388                 '$remoteversion' => $u[1],
1389                 '$needupdate' => $needupdate,
1390                 '$canwrite' => $canwrite,
1391                 '$canftp'       => $canftp,
1392                 '$ftphost'      => array('ftphost', t("FTP Host"), '',''),
1393                 '$ftppath'      => array('ftppath', t("FTP Path"), '/',''),
1394                 '$ftpuser'      => array('ftpuser', t("FTP User"), '',''),
1395                 '$ftppwd'       => array('ftppwd', t("FTP Password"), '',''),
1396                 '$remotefile'=>array('remotefile','', $u['2'],''),
1397         ));
1398         
1399 }