]> git.mxchange.org Git - friendica.git/blob - mod/admin.php
16c3a23d4d3955eb222c072a39e7d60efb3a962a
[friendica.git] / mod / admin.php
1 <?php
2
3  /**
4   * Friendica admin
5   */
6 require_once("include/remoteupdate.php");
7 require_once("include/enotify.php");
8 require_once("include/text.php");
9
10 /**
11  * @brief process send data from the admin panels subpages
12  *
13  * This function acts as relais for processing the data send from the subpages
14  * of the admin panel. Depending on the 1st parameter of the url (argv[1])
15  * specialized functions are called to process the data from the subpages.
16  *
17  * The function itself does not return anything, but the subsequencely function
18  * return the HTML for the pages of the admin panel.
19  *
20  * @param App $a
21  *
22  */
23 function admin_post(&$a){
24
25
26         if(!is_site_admin()) {
27                 return;
28         }
29
30         // do not allow a page manager to access the admin panel at all.
31
32         if(x($_SESSION,'submanage') && intval($_SESSION['submanage']))
33                 return;
34
35
36
37         // urls
38         if ($a->argc > 1){
39                 switch ($a->argv[1]){
40                         case 'site':
41                                 admin_page_site_post($a);
42                                 break;
43                         case 'users':
44                                 admin_page_users_post($a);
45                                 break;
46                         case 'plugins':
47                                 if ($a->argc > 2 &&
48                                         is_file("addon/".$a->argv[2]."/".$a->argv[2].".php")){
49                                                 @include_once("addon/".$a->argv[2]."/".$a->argv[2].".php");
50                                                 if(function_exists($a->argv[2].'_plugin_admin_post')) {
51                                                         $func = $a->argv[2].'_plugin_admin_post';
52                                                         $func($a);
53                                                 }
54                                 }
55                                 goaway($a->get_baseurl(true) . '/admin/plugins/' . $a->argv[2] );
56                                 return; // NOTREACHED
57                                 break;
58                         case 'themes':
59                                 if ($a->argc < 2) {
60                                         if(is_ajax()) return;
61                                         goaway($a->get_baseurl(true) . '/admin/' );
62                                         return;
63                                 }
64
65                                 $theme = $a->argv[2];
66                                 if (is_file("view/theme/$theme/config.php")){
67                                         function __call_theme_admin_post(&$a, $theme) {
68                                                 $orig_theme = $a->theme;
69                                                 $orig_page = $a->page;
70                                                 $orig_session_theme = $_SESSION['theme'];
71                                                 require_once("view/theme/$theme/theme.php");
72                                                 require_once("view/theme/$theme/config.php");
73                                                 $_SESSION['theme'] = $theme;
74
75
76                                                 $init = $theme."_init";
77                                                 if(function_exists($init)) $init($a);
78                                                 if(function_exists("theme_admin_post")){
79                                                         $admin_form = theme_admin_post($a);
80                                                 }
81
82                                                 $_SESSION['theme'] = $orig_session_theme;
83                                                 $a->theme = $orig_theme;
84                                                 $a->page = $orig_page;
85                                                 return $admin_form;
86                                         }
87                                         __call_theme_admin_post($a, $theme);
88                                 }
89                                 info(t('Theme settings updated.'));
90                                 if(is_ajax()) return;
91
92                                 goaway($a->get_baseurl(true) . '/admin/themes/' . $theme );
93                                 return;
94                                 break;
95                         case 'logs':
96                                 admin_page_logs_post($a);
97                                 break;
98                         case 'dbsync':
99                                 admin_page_dbsync_post($a);
100                                 break;
101                         case 'update':
102                                 admin_page_remoteupdate_post($a);
103                                 break;
104                 }
105         }
106
107         goaway($a->get_baseurl(true) . '/admin' );
108         return; // NOTREACHED
109 }
110
111 /**
112  * This function generates the content for the admin panel.
113  * @brief generates content of the admin panel pages
114  * @param App $a
115  * @return string
116  */
117 function admin_content(&$a) {
118
119         if(!is_site_admin()) {
120                 return login(false);
121         }
122
123         if(x($_SESSION,'submanage') && intval($_SESSION['submanage']))
124                 return "";
125
126         // APC deactivated, since there are problems with PHP 5.5
127         //if (function_exists("apc_delete")) {
128         //      $toDelete = new APCIterator('user', APC_ITER_VALUE);
129         //      apc_delete($toDelete);
130         //}
131
132         /**
133          * Side bar links
134          */
135         $aside_tools = Array();
136         // array( url, name, extra css classes )
137         // not part of $aside to make the template more adjustable
138         $aside_sub = Array(
139                 'site'   =>     Array($a->get_baseurl(true)."/admin/site/", t("Site") , "site"),
140                 'users'  =>     Array($a->get_baseurl(true)."/admin/users/", t("Users") , "users"),
141                 'plugins'=>     Array($a->get_baseurl(true)."/admin/plugins/", t("Plugins") , "plugins"),
142                 'themes' =>     Array($a->get_baseurl(true)."/admin/themes/", t("Themes") , "themes"),
143                 'dbsync' =>     Array($a->get_baseurl(true)."/admin/dbsync/", t('DB updates'), "dbsync"),
144                 'queue'  =>     Array($a->get_baseurl(true)."/admin/queue/", t('Inspect Queue'), "queue"),
145                 'federation' => Array($a->get_baseurl(true)."/admin/federation/", t('Federation Statistics'), "federation"),
146                 //'update' =>   Array($a->get_baseurl(true)."/admin/update/", t("Software Update") , "update")
147         );
148
149         /* get plugins admin page */
150
151         $r = q("SELECT `name` FROM `addon` WHERE `plugin_admin`=1 ORDER BY `name`");
152         $aside_tools['plugins_admin']=Array();
153         foreach ($r as $h){
154                 $plugin =$h['name'];
155                 $aside['plugins_admin'][] = Array($a->get_baseurl(true)."/admin/plugins/".$plugin, $plugin, "plugin");
156                 // temp plugins with admin
157                 $a->plugins_admin[] = $plugin;
158         }
159
160         $aside_tools['logs'] = Array($a->get_baseurl(true)."/admin/logs/", t("Logs"), "logs");
161         $aside_tools['viewlogs'] = Array($a->get_baseurl(true)."/admin/viewlogs/", t("View Logs"), 'viewlogs');
162         $aside_tools['diagnostics_probe'] = Array($a->get_baseurl(true).'/probe/', t('probe address'), 'probe');
163         $aside_tools['diagnostics_webfinger'] = Array($a->get_baseurl(true).'/webfinger/', t('check webfinger'), 'webfinger');
164
165         $t = get_markup_template("admin_aside.tpl");
166         $a->page['aside'] .= replace_macros( $t, array(
167             '$admin' => $aside_tools,
168             '$subpages' => $aside_sub,
169             '$admtxt' => t('Admin'),
170             '$plugadmtxt' => t('Plugin Features'),
171             '$logtxt' => t('Logs'),
172             '$diagnosticstxt' => t('diagnostics'),
173             '$h_pending' => t('User registrations waiting for confirmation'),
174             '$admurl'=> $a->get_baseurl(true)."/admin/"
175         ));
176
177
178
179         /**
180          * Page content
181          */
182         $o = '';
183         // urls
184         if ($a->argc > 1){
185                 switch ($a->argv[1]){
186                         case 'site':
187                                 $o = admin_page_site($a);
188                                 break;
189                         case 'users':
190                                 $o = admin_page_users($a);
191                                 break;
192                         case 'plugins':
193                                 $o = admin_page_plugins($a);
194                                 break;
195                         case 'themes':
196                                 $o = admin_page_themes($a);
197                                 break;
198                         case 'logs':
199                                 $o = admin_page_logs($a);
200                                 break;
201                         case 'viewlogs':
202                                 $o = admin_page_viewlogs($a);
203                                 break;
204                         case 'dbsync':
205                                 $o = admin_page_dbsync($a);
206                                 break;
207                         case 'update':
208                                 $o = admin_page_remoteupdate($a);
209                                 break;
210                         case 'queue':
211                                 $o = admin_page_queue($a);
212                                 break;
213                         case 'federation':
214                                 $o = admin_page_federation($a);
215                                 break;
216                         default:
217                                 notice( t("Item not found.") );
218                 }
219         } else {
220                 $o = admin_page_summary($a);
221         }
222
223         if(is_ajax()) {
224                 echo $o;
225                 killme();
226                 return '';
227         } else {
228                 return $o;
229         }
230 }
231
232 /**
233  * This function generates the "Federation Statistics" subpage for the admin
234  * panel. The page lists some numbers to the part of "The Federation" known to
235  * the node. This data includes the different connected networks (e.g.
236  * Diaspora, Hubzilla, GNU Social) and the used versions in the different
237  * networks.
238  *
239  * The returned string contains the HTML code of the subpage for display.
240  *
241  * @brief subpage with some stats about "the federation" network
242  * @param App $a
243  * @return string
244  */
245 function admin_page_federation(&$a) {
246     // get counts on active friendica, diaspora, redmatrix, hubzilla, gnu
247     // social and statusnet nodes this node is knowing
248     //
249     // We are looking for the following platforms in the DB, "Red" should find
250     // all variants of that platform ID string as the q() function is stripping
251     // off one % two of them are needed in the query
252     // Add more platforms if you like, when one returns 0 known nodes it is not
253     // displayed on the stats page.
254     $platforms = array('Friendica', 'Diaspora', '%%red%%', 'Hubzilla', 'GNU Social', 'StatusNet');
255     $counts = array();
256     foreach ($platforms as $p) {
257         // get a total count for the platform, the name and version of the
258         // highest version and the protocol tpe
259         $c = q('select count(*), platform, network, version from gserver
260             where platform like "'.$p.'" and last_contact > last_failure
261             order by version asc;');
262         // what versions for that platform do we know at all?
263         // again only the active nodes
264         $v = q('select count(*), version from gserver
265             where last_contact > last_failure and platform like "'.$p.'" 
266             group by version
267             order by version;');
268         //
269         // clean up version numbers
270         //
271         // in the DB the Diaspora versions have the format x.x.x.x-xx the last
272         // part (-xx) should be removed to clean up the versions from the "head
273         // commit" information and combined into a single entry for x.x.x.x
274         if ($p=='Diaspora') {
275             $newV = array();
276             $newVv = array();
277             foreach($v as $vv) {
278                 $newVC = $vv['count(*)'];
279                 $newVV = $vv['version'];
280                 $posDash = strpos($newVV, '-');
281                 if ($posDash) 
282                     $newVV = substr($newVV, 0, $posDash);
283                 if (isset($newV[$newVV]))
284                 { 
285                     $newV[$newVV] += $newVC; 
286                 } else { 
287                     $newV[$newVV] = $newVC; 
288                 }
289             }
290             foreach ($newV as $key => $value) {
291                 array_push($newVv, array('count(*)'=>$value, 'version'=>$key));
292             }
293             $v = $newVv;
294         }
295         // early friendica versions have the format x.x.xxxx where xxxx is the
296         // DB version stamp; those should be operated out and versions be
297         // conbined
298         if ($p=='Friendica') {
299             $newV = array();
300             $newVv = array();
301             foreach ($v as $vv) {
302                 $newVC = $vv['count(*)'];
303                 $newVV = $vv['version'];
304                 $lastDot = strrpos($newVV,'.');
305                 $len = strlen($newVV)-1;
306                 if (($lastDot == $len-4) && (!strrpos($newVV,'-rc')==$len-3))
307                     $newVV = substr($newVV, 0, $lastDot);
308                 if (isset($newV[$newVV])) 
309                 { 
310                     $newV[$newVV] += $newVC; 
311                 } else { 
312                     $newV[$newVV] = $newVC; 
313                 }
314             }
315             foreach ($newV as $key => $value) {
316                 array_push($newVv, array('count(*)'=>$value, 'version'=>$key));
317             }
318             $v = $newVv;
319         }
320         // the 3rd array item is needed for the JavaScript graphs as JS does
321         // not like some characters in the names of variables...
322         $counts[$p]=array($c[0], $v, str_replace(array(' ','%'),'',$p));
323     }
324     // some helpful text
325     $intro = t('This page offers you some numbers to the known part of the federated social network your Friendica node is part of. These numbers are not complete but only reflect the part of the network your node is aware of.');
326     $hint = t('The <em>Auto Discovered Contact Directory</em> feature is not enabled, it will improve the data displayed here.');
327     // load the template, replace the macros and return the page content
328     $t = get_markup_template("admin_federation.tpl");
329     return replace_macros($t, array(
330         '$title' => t('Administration'),
331         '$page' => t('Federation Statistics'),
332         '$intro' => $intro,
333         '$hint' => $hint,
334         '$autoactive' => get_config('system', 'poco_completion'),
335         '$counts' => $counts,
336         '$version' => FRIENDICA_VERSION,
337         '$legendtext' => t('Currently this node is aware of nodes from the following platforms:'),
338         '$baseurl' => $a->get_baseurl(),
339     ));
340 }
341 /**
342  * @brief Admin Inspect Queue Page
343  *
344  * Generates a page for the admin to have a look into the current queue of
345  * postings that are not deliverabke. Shown are the name and url of the
346  * recipient, the delivery network and the dates when the posting was generated
347  * and the last time tried to deliver the posting.
348  *
349  * The returned string holds the content of the page.
350  *
351  * @param App $a
352  * @return string
353  */
354 function admin_page_queue(&$a) {
355         // get content from the queue table
356         $r = q("SELECT c.name,c.nurl,q.id,q.network,q.created,q.last from queue as q, contact as c where c.id=q.cid order by q.cid, q.created;");
357
358         $t = get_markup_template("admin_queue.tpl");
359         return replace_macros($t, array(
360                 '$title' => t('Administration'),
361                 '$page' => t('Inspect Queue'),
362                 '$count' => sizeof($r),
363                 'id_header' => t('ID'),
364                 '$to_header' => t('Recipient Name'),
365                 '$url_header' => t('Recipient Profile'),
366                 '$network_header' => t('Network'),
367                 '$created_header' => t('Created'),
368                 '$last_header' => t('Last Tried'),
369                 '$info' => t('This page lists the content of the queue for outgoing postings. These are postings the initial delivery failed for. They will be resend later and eventually deleted if the delivery fails permanently.'),
370                 '$entries' => $r,
371         ));
372 }
373 /**
374  * @brief Admin Summary Page
375  *
376  * The summary page is the "start page" of the admin panel. It gives the admin
377  * a first overview of the open adminastrative tasks.
378  *
379  * The returned string contains the HTML content of the generated page.
380  *
381  * @param App $a
382  * @return string
383  */
384 function admin_page_summary(&$a) {
385         $r = q("SELECT `page-flags`, COUNT(uid) as `count` FROM `user` GROUP BY `page-flags`");
386         $accounts = Array(
387                 Array( t('Normal Account'), 0),
388                 Array( t('Soapbox Account'), 0),
389                 Array( t('Community/Celebrity Account'), 0),
390                 Array( t('Automatic Friend Account'), 0),
391                 Array( t('Blog Account'), 0),
392                 Array( t('Private Forum'), 0)
393         );
394
395         $users=0;
396         foreach ($r as $u){ $accounts[$u['page-flags']][1] = $u['count']; $users+= $u['count']; }
397
398         logger('accounts: ' . print_r($accounts,true),LOGGER_DATA);
399
400         $r = q("SELECT COUNT(id) as `count` FROM `register`");
401         $pending = $r[0]['count'];
402
403         $r = q("select count(*) as total from deliverq where 1");
404         $deliverq = (($r) ? $r[0]['total'] : 0);
405
406         $r = q("select count(*) as total from queue where 1");
407         $queue = (($r) ? $r[0]['total'] : 0);
408
409         // We can do better, but this is a quick queue status
410
411         $queues = array( 'label' => t('Message queues'), 'deliverq' => $deliverq, 'queue' => $queue );
412
413
414         $t = get_markup_template("admin_summary.tpl");
415         return replace_macros($t, array(
416                 '$title' => t('Administration'),
417                 '$page' => t('Summary'),
418                 '$queues' => $queues,
419                 '$users' => Array( t('Registered users'), $users),
420                 '$accounts' => $accounts,
421                 '$pending' => Array( t('Pending registrations'), $pending),
422                 '$version' => Array( t('Version'), FRIENDICA_VERSION),
423                 '$baseurl' => $a->get_baseurl(),
424                 '$platform' => FRIENDICA_PLATFORM,
425                 '$codename' => FRIENDICA_CODENAME,
426                 '$build' =>  get_config('system','build'),
427                 '$plugins' => Array( t('Active plugins'), $a->plugins )
428         ));
429 }
430
431
432 /**
433  * @brief process send data from Admin Site Page
434  * @param App $a
435  */
436 function admin_page_site_post(&$a){
437         if (!x($_POST,"page_site")){
438                 return;
439         }
440
441         check_form_security_token_redirectOnErr('/admin/site', 'admin_site');
442
443         // relocate
444         if (x($_POST,'relocate') && x($_POST,'relocate_url') && $_POST['relocate_url']!=""){
445                 $new_url = $_POST['relocate_url'];
446                 $new_url = rtrim($new_url,"/");
447
448                 $parsed = @parse_url($new_url);
449                 if (!$parsed || (!x($parsed,'host') || !x($parsed,'scheme'))) {
450                         notice(t("Can not parse base url. Must have at least <scheme>://<domain>"));
451                         goaway($a->get_baseurl(true) . '/admin/site' );
452                 }
453
454                 /* steps:
455                  * replace all "baseurl" to "new_url" in config, profile, term, items and contacts
456                  * send relocate for every local user
457                  * */
458
459                 $old_url = $a->get_baseurl(true);
460
461                 function update_table($table_name, $fields, $old_url, $new_url) {
462                         global $db, $a;
463
464                         $dbold = dbesc($old_url);
465                         $dbnew = dbesc($new_url);
466
467                         $upd = array();
468                         foreach ($fields as $f) {
469                                 $upd[] = "`$f` = REPLACE(`$f`, '$dbold', '$dbnew')";
470                         }
471
472                         $upds = implode(", ", $upd);
473
474
475
476                         $q = sprintf("UPDATE %s SET %s;", $table_name, $upds);
477                         $r = q($q);
478                         if (!$r) {
479                                 notice( "Failed updating '$table_name': " . $db->error );
480                                 goaway($a->get_baseurl(true) . '/admin/site' );
481                         }
482                 }
483
484                 // update tables
485                 update_table("profile", array('photo', 'thumb'), $old_url, $new_url);
486                 update_table("term", array('url'), $old_url, $new_url);
487                 update_table("contact", array('photo','thumb','micro','url','nurl','request','notify','poll','confirm','poco'), $old_url, $new_url);
488                 update_table("gcontact", array('photo','url','nurl','server_url'), $old_url, $new_url);
489                 update_table("item", array('owner-link','owner-avatar','author-name','author-link','author-avatar','body','plink','tag'), $old_url, $new_url);
490
491                 // update config
492                 $a->set_baseurl($new_url);
493                 set_config('system','url',$new_url);
494
495                 // send relocate
496                 $users = q("SELECT uid FROM user WHERE account_removed = 0 AND account_expired = 0");
497
498                 foreach ($users as $user) {
499                         proc_run('php', 'include/notifier.php', 'relocate', $user['uid']);
500                 }
501
502                 info("Relocation started. Could take a while to complete.");
503
504                 goaway($a->get_baseurl(true) . '/admin/site' );
505         }
506         // end relocate
507
508         $sitename               =       ((x($_POST,'sitename'))                 ? notags(trim($_POST['sitename']))              : '');
509         $hostname               =       ((x($_POST,'hostname'))                 ? notags(trim($_POST['hostname']))              : '');
510         $sender_email           =       ((x($_POST,'sender_email'))             ? notags(trim($_POST['sender_email']))          : '');
511         $banner                 =       ((x($_POST,'banner'))                   ? trim($_POST['banner'])                        : false);
512         $shortcut_icon          =       ((x($_POST,'shortcut_icon'))            ? notags(trim($_POST['shortcut_icon']))         : '');
513         $touch_icon             =       ((x($_POST,'touch_icon'))               ? notags(trim($_POST['touch_icon']))            : '');
514         $info                   =       ((x($_POST,'info'))                     ? trim($_POST['info'])                  : false);
515         $language               =       ((x($_POST,'language'))                 ? notags(trim($_POST['language']))              : '');
516         $theme                  =       ((x($_POST,'theme'))                    ? notags(trim($_POST['theme']))                 : '');
517         $theme_mobile           =       ((x($_POST,'theme_mobile'))             ? notags(trim($_POST['theme_mobile']))          : '');
518         $maximagesize           =       ((x($_POST,'maximagesize'))             ? intval(trim($_POST['maximagesize']))          :  0);
519         $maximagelength         =       ((x($_POST,'maximagelength'))           ? intval(trim($_POST['maximagelength']))        :  MAX_IMAGE_LENGTH);
520         $jpegimagequality       =       ((x($_POST,'jpegimagequality'))         ? intval(trim($_POST['jpegimagequality']))      :  JPEG_QUALITY);
521
522
523         $register_policy        =       ((x($_POST,'register_policy'))          ? intval(trim($_POST['register_policy']))       :  0);
524         $daily_registrations    =       ((x($_POST,'max_daily_registrations'))  ? intval(trim($_POST['max_daily_registrations']))       :0);
525         $abandon_days           =       ((x($_POST,'abandon_days'))             ? intval(trim($_POST['abandon_days']))          :  0);
526
527         $register_text          =       ((x($_POST,'register_text'))            ? notags(trim($_POST['register_text']))         : '');
528
529         $allowed_sites          =       ((x($_POST,'allowed_sites'))            ? notags(trim($_POST['allowed_sites']))         : '');
530         $allowed_email          =       ((x($_POST,'allowed_email'))            ? notags(trim($_POST['allowed_email']))         : '');
531         $block_public           =       ((x($_POST,'block_public'))             ? True                                          : False);
532         $force_publish          =       ((x($_POST,'publish_all'))              ? True                                          : False);
533         $global_directory       =       ((x($_POST,'directory'))                ? notags(trim($_POST['directory']))     : '');
534         $thread_allow           =       ((x($_POST,'thread_allow'))             ? True                                          : False);
535         $newuser_private                =       ((x($_POST,'newuser_private'))          ? True                                          : False);
536         $enotify_no_content             =       ((x($_POST,'enotify_no_content'))       ? True                                          : False);
537         $private_addons                 =       ((x($_POST,'private_addons'))           ? True                                          : False);
538         $disable_embedded               =       ((x($_POST,'disable_embedded'))         ? True                                          : False);
539         $allow_users_remote_self        =       ((x($_POST,'allow_users_remote_self'))          ? True                                          : False);
540
541         $no_multi_reg           =       ((x($_POST,'no_multi_reg'))             ? True                                          : False);
542         $no_openid              =       !((x($_POST,'no_openid'))               ? True                                          : False);
543         $no_regfullname         =       !((x($_POST,'no_regfullname'))          ? True                                          : False);
544         $no_utf                 =       !((x($_POST,'no_utf'))                  ? True                                          : False);
545         $community_page_style   =       ((x($_POST,'community_page_style'))     ? intval(trim($_POST['community_page_style']))  : 0);
546         $max_author_posts_community_page        =       ((x($_POST,'max_author_posts_community_page'))  ? intval(trim($_POST['max_author_posts_community_page']))       : 0);
547
548         $verifyssl              =       ((x($_POST,'verifyssl'))                ? True                                          : False);
549         $proxyuser              =       ((x($_POST,'proxyuser'))                ? notags(trim($_POST['proxyuser']))             : '');
550         $proxy                  =       ((x($_POST,'proxy'))                    ? notags(trim($_POST['proxy']))                 : '');
551         $timeout                =       ((x($_POST,'timeout'))                  ? intval(trim($_POST['timeout']))               : 60);
552         $delivery_interval      =       ((x($_POST,'delivery_interval'))        ? intval(trim($_POST['delivery_interval']))     : 0);
553         $poll_interval          =       ((x($_POST,'poll_interval'))            ? intval(trim($_POST['poll_interval']))         : 0);
554         $maxloadavg             =       ((x($_POST,'maxloadavg'))               ? intval(trim($_POST['maxloadavg']))            : 50);
555         $maxloadavg_frontend    =       ((x($_POST,'maxloadavg_frontend'))      ? intval(trim($_POST['maxloadavg_frontend']))   : 50);
556         $optimize_max_tablesize =       ((x($_POST,'optimize_max_tablesize'))   ? intval(trim($_POST['optimize_max_tablesize'])): 100);
557         $optimize_fragmentation =       ((x($_POST,'optimize_fragmentation'))   ? intval(trim($_POST['optimize_fragmentation'])): 30);
558         $poco_completion        =       ((x($_POST,'poco_completion'))          ? intval(trim($_POST['poco_completion']))       : false);
559         $poco_requery_days      =       ((x($_POST,'poco_requery_days'))        ? intval(trim($_POST['poco_requery_days']))     : 7);
560         $poco_discovery         =       ((x($_POST,'poco_discovery'))           ? intval(trim($_POST['poco_discovery']))        : 0);
561         $poco_discovery_since   =       ((x($_POST,'poco_discovery_since'))     ? intval(trim($_POST['poco_discovery_since']))  : 30);
562         $poco_local_search      =       ((x($_POST,'poco_local_search'))        ? intval(trim($_POST['poco_local_search']))     : false);
563         $nodeinfo               =       ((x($_POST,'nodeinfo'))                 ? intval(trim($_POST['nodeinfo']))              : false);
564         $dfrn_only              =       ((x($_POST,'dfrn_only'))                ? True                                          : False);
565         $ostatus_disabled       =       !((x($_POST,'ostatus_disabled'))        ? True                                          : False);
566         $ostatus_poll_interval  =       ((x($_POST,'ostatus_poll_interval'))    ? intval(trim($_POST['ostatus_poll_interval'])) :  0);
567         $diaspora_enabled       =       ((x($_POST,'diaspora_enabled'))         ? True                                          : False);
568         $ssl_policy             =       ((x($_POST,'ssl_policy'))               ? intval($_POST['ssl_policy'])                  : 0);
569         $force_ssl              =       ((x($_POST,'force_ssl'))                ? True                                          : False);
570         $old_share              =       ((x($_POST,'old_share'))                ? True                                          : False);
571         $hide_help              =       ((x($_POST,'hide_help'))                ? True                                          : False);
572         $suppress_language      =       ((x($_POST,'suppress_language'))        ? True                                          : False);
573         $suppress_tags          =       ((x($_POST,'suppress_tags'))            ? True                                          : False);
574         $use_fulltext_engine    =       ((x($_POST,'use_fulltext_engine'))      ? True                                          : False);
575         $itemcache              =       ((x($_POST,'itemcache'))                ? notags(trim($_POST['itemcache']))             : '');
576         $itemcache_duration     =       ((x($_POST,'itemcache_duration'))       ? intval($_POST['itemcache_duration'])          : 0);
577         $max_comments           =       ((x($_POST,'max_comments'))             ? intval($_POST['max_comments'])                : 0);
578         $lockpath               =       ((x($_POST,'lockpath'))                 ? notags(trim($_POST['lockpath']))              : '');
579         $temppath               =       ((x($_POST,'temppath'))                 ? notags(trim($_POST['temppath']))              : '');
580         $basepath               =       ((x($_POST,'basepath'))                 ? notags(trim($_POST['basepath']))              : '');
581         $singleuser             =       ((x($_POST,'singleuser'))               ? notags(trim($_POST['singleuser']))            : '');
582         $proxy_disabled         =       ((x($_POST,'proxy_disabled'))           ? True                                          : False);
583         $old_pager              =       ((x($_POST,'old_pager'))                ? True                                          : False);
584         $only_tag_search        =       ((x($_POST,'only_tag_search'))          ? True                                          : False);
585         $rino                   =       ((x($_POST,'rino'))                             ? intval($_POST['rino'])                                : 0);
586         $embedly                =       ((x($_POST,'embedly'))                  ? notags(trim($_POST['embedly']))               : '');
587
588         if ($a->get_path() != "")
589                 $diaspora_enabled = false;
590
591         if (!$thread_allow)
592                 $ostatus_disabled = true;
593
594         if($ssl_policy != intval(get_config('system','ssl_policy'))) {
595                 if($ssl_policy == SSL_POLICY_FULL) {
596                         q("update `contact` set
597                                 `url`     = replace(`url`    , 'http:' , 'https:'),
598                                 `photo`   = replace(`photo`  , 'http:' , 'https:'),
599                                 `thumb`   = replace(`thumb`  , 'http:' , 'https:'),
600                                 `micro`   = replace(`micro`  , 'http:' , 'https:'),
601                                 `request` = replace(`request`, 'http:' , 'https:'),
602                                 `notify`  = replace(`notify` , 'http:' , 'https:'),
603                                 `poll`    = replace(`poll`   , 'http:' , 'https:'),
604                                 `confirm` = replace(`confirm`, 'http:' , 'https:'),
605                                 `poco`    = replace(`poco`   , 'http:' , 'https:')
606                                 where `self` = 1"
607                         );
608                         q("update `profile` set
609                                 `photo`   = replace(`photo`  , 'http:' , 'https:'),
610                                 `thumb`   = replace(`thumb`  , 'http:' , 'https:')
611                                 where 1 "
612                         );
613                 }
614                 elseif($ssl_policy == SSL_POLICY_SELFSIGN) {
615                         q("update `contact` set
616                                 `url`     = replace(`url`    , 'https:' , 'http:'),
617                                 `photo`   = replace(`photo`  , 'https:' , 'http:'),
618                                 `thumb`   = replace(`thumb`  , 'https:' , 'http:'),
619                                 `micro`   = replace(`micro`  , 'https:' , 'http:'),
620                                 `request` = replace(`request`, 'https:' , 'http:'),
621                                 `notify`  = replace(`notify` , 'https:' , 'http:'),
622                                 `poll`    = replace(`poll`   , 'https:' , 'http:'),
623                                 `confirm` = replace(`confirm`, 'https:' , 'http:'),
624                                 `poco`    = replace(`poco`   , 'https:' , 'http:')
625                                 where `self` = 1"
626                         );
627                         q("update `profile` set
628                                 `photo`   = replace(`photo`  , 'https:' , 'http:'),
629                                 `thumb`   = replace(`thumb`  , 'https:' , 'http:')
630                                 where 1 "
631                         );
632                 }
633         }
634         set_config('system','ssl_policy',$ssl_policy);
635         set_config('system','delivery_interval',$delivery_interval);
636         set_config('system','poll_interval',$poll_interval);
637         set_config('system','maxloadavg',$maxloadavg);
638         set_config('system','maxloadavg_frontend',$maxloadavg_frontend);
639         set_config('system','optimize_max_tablesize',$optimize_max_tablesize);
640         set_config('system','optimize_fragmentation',$optimize_fragmentation);
641         set_config('system','poco_completion',$poco_completion);
642         set_config('system','poco_requery_days',$poco_requery_days);
643         set_config('system','poco_discovery',$poco_discovery);
644         set_config('system','poco_discovery_since',$poco_discovery_since);
645         set_config('system','poco_local_search',$poco_local_search);
646         set_config('system','nodeinfo',$nodeinfo);
647         set_config('config','sitename',$sitename);
648         set_config('config','hostname',$hostname);
649         set_config('config','sender_email', $sender_email);
650         set_config('system','suppress_language',$suppress_language);
651         set_config('system','suppress_tags',$suppress_tags);
652         set_config('system','shortcut_icon',$shortcut_icon);
653         set_config('system','touch_icon',$touch_icon);
654
655         if ($banner==""){
656                 // don't know why, but del_config doesn't work...
657                 q("DELETE FROM `config` WHERE `cat` = '%s' AND `k` = '%s' LIMIT 1",
658                         dbesc("system"),
659                         dbesc("banner")
660                 );
661         } else {
662                 set_config('system','banner', $banner);
663         }
664         if ($info=="") {
665                 del_config('config','info');
666         } else {
667                 set_config('config','info',$info);
668         }
669         set_config('system','language', $language);
670         set_config('system','theme', $theme);
671         if ( $theme_mobile === '---' ) {
672                 del_config('system','mobile-theme');
673         } else {
674                 set_config('system','mobile-theme', $theme_mobile);
675                 }
676                 if ( $singleuser === '---' ) {
677                         del_config('system','singleuser');
678                 } else {
679                         set_config('system','singleuser', $singleuser);
680                 }
681         set_config('system','maximagesize', $maximagesize);
682         set_config('system','max_image_length', $maximagelength);
683         set_config('system','jpeg_quality', $jpegimagequality);
684
685         set_config('config','register_policy', $register_policy);
686         set_config('system','max_daily_registrations', $daily_registrations);
687         set_config('system','account_abandon_days', $abandon_days);
688         set_config('config','register_text', $register_text);
689         set_config('system','allowed_sites', $allowed_sites);
690         set_config('system','allowed_email', $allowed_email);
691         set_config('system','block_public', $block_public);
692         set_config('system','publish_all', $force_publish);
693         set_config('system','directory', $global_directory);
694         set_config('system','thread_allow', $thread_allow);
695         set_config('system','newuser_private', $newuser_private);
696         set_config('system','enotify_no_content', $enotify_no_content);
697         set_config('system','disable_embedded', $disable_embedded);
698         set_config('system','allow_users_remote_self', $allow_users_remote_self);
699
700         set_config('system','block_extended_register', $no_multi_reg);
701         set_config('system','no_openid', $no_openid);
702         set_config('system','no_regfullname', $no_regfullname);
703         set_config('system','community_page_style', $community_page_style);
704         set_config('system','max_author_posts_community_page', $max_author_posts_community_page);
705         set_config('system','no_utf', $no_utf);
706         set_config('system','verifyssl', $verifyssl);
707         set_config('system','proxyuser', $proxyuser);
708         set_config('system','proxy', $proxy);
709         set_config('system','curl_timeout', $timeout);
710         set_config('system','dfrn_only', $dfrn_only);
711         set_config('system','ostatus_disabled', $ostatus_disabled);
712         set_config('system','ostatus_poll_interval', $ostatus_poll_interval);
713         set_config('system','diaspora_enabled', $diaspora_enabled);
714
715         set_config('config','private_addons', $private_addons);
716
717         set_config('system','force_ssl', $force_ssl);
718         set_config('system','old_share', $old_share);
719         set_config('system','hide_help', $hide_help);
720         set_config('system','use_fulltext_engine', $use_fulltext_engine);
721         set_config('system','itemcache', $itemcache);
722         set_config('system','itemcache_duration', $itemcache_duration);
723         set_config('system','max_comments', $max_comments);
724         set_config('system','lockpath', $lockpath);
725         set_config('system','temppath', $temppath);
726         set_config('system','basepath', $basepath);
727         set_config('system','proxy_disabled', $proxy_disabled);
728         set_config('system','old_pager', $old_pager);
729         set_config('system','only_tag_search', $only_tag_search);
730
731
732         if ($rino==2 and !function_exists('mcrypt_create_iv')){
733                 notice(t("RINO2 needs mcrypt php extension to work."));
734         } else {
735                 set_config('system','rino_encrypt', $rino);
736         }
737
738         set_config('system','embedly', $embedly);
739
740
741         info( t('Site settings updated.') . EOL);
742         goaway($a->get_baseurl(true) . '/admin/site' );
743         return; // NOTREACHED
744
745 }
746
747 /**
748  * @brief generate Admin Site subpage
749  *
750  * This function generates the main configuration page of the admin panel.
751  *
752  * @param  App $a
753  * @return string
754  */
755 function admin_page_site(&$a) {
756
757         /* Installed langs */
758         $lang_choices = get_avaiable_languages();
759
760         if (strlen(get_config('system','directory_submit_url')) AND
761                 !strlen(get_config('system','directory'))) {
762                 set_config('system','directory', dirname(get_config('system','directory_submit_url')));
763                 del_config('system','directory_submit_url');
764         }
765
766         /* Installed themes */
767         $theme_choices = array();
768         $theme_choices_mobile = array();
769         $theme_choices_mobile["---"] = t("No special theme for mobile devices");
770         $files = glob('view/theme/*'); /**/
771         if($files) {
772                 foreach($files as $file) {
773                         if (intval(file_exists($file . '/unsupported')))
774                                 continue;
775
776                         $f = basename($file);
777                         $theme_name = ((file_exists($file . '/experimental')) ?  sprintf("%s - \x28Experimental\x29", $f) : $f);
778                         if (file_exists($file . '/mobile')) {
779                                 $theme_choices_mobile[$f] = $theme_name;
780                         } else {
781                                 $theme_choices[$f] = $theme_name;
782                         }
783                 }
784         }
785
786         /* Community page style */
787         $community_page_style_choices = array(
788                 CP_NO_COMMUNITY_PAGE => t("No community page"),
789                 CP_USERS_ON_SERVER => t("Public postings from users of this site"),
790                 CP_GLOBAL_COMMUNITY => t("Global community page")
791                 );
792
793         /* OStatus conversation poll choices */
794         $ostatus_poll_choices = array(
795                 "-2" => t("Never"),
796                 "-1" => t("At post arrival"),
797                 "0" => t("Frequently"),
798                 "60" => t("Hourly"),
799                 "720" => t("Twice daily"),
800                 "1440" => t("Daily")
801                 );
802
803         $poco_discovery_choices = array(
804                 "0" => t("Disabled"),
805                 "1" => t("Users"),
806                 "2" => t("Users, Global Contacts"),
807                 "3" => t("Users, Global Contacts/fallback"),
808                 );
809
810         $poco_discovery_since_choices = array(
811                 "30" => t("One month"),
812                 "91" => t("Three months"),
813                 "182" => t("Half a year"),
814                 "365" => t("One year"),
815                 );
816
817         /* get user names to make the install a personal install of X */
818         $user_names = array();
819         $user_names['---'] = t('Multi user instance');
820         $users = q("SELECT username, nickname FROM `user`");
821         foreach ($users as $user) {
822                 $user_names[$user['nickname']] = $user['username'];
823         }
824
825         /* Banner */
826         $banner = get_config('system','banner');
827         if($banner == false)
828                 $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>';
829         $banner = htmlspecialchars($banner);
830         $info = get_config('config','info');
831         $info = htmlspecialchars($info);
832
833         // Automatically create temporary paths
834         get_temppath();
835         get_lockpath();
836         get_itemcachepath();
837
838         //echo "<pre>"; var_dump($lang_choices); die("</pre>");
839
840         /* Register policy */
841         $register_choices = Array(
842                 REGISTER_CLOSED => t("Closed"),
843                 REGISTER_APPROVE => t("Requires approval"),
844                 REGISTER_OPEN => t("Open")
845         );
846
847         $ssl_choices = array(
848                 SSL_POLICY_NONE => t("No SSL policy, links will track page SSL state"),
849                 SSL_POLICY_FULL => t("Force all links to use SSL"),
850                 SSL_POLICY_SELFSIGN => t("Self-signed certificate, use SSL for local links only (discouraged)")
851         );
852
853         if ($a->config['hostname'] == "")
854                 $a->config['hostname'] = $a->get_hostname();
855
856         $diaspora_able = ($a->get_path() == "");
857
858         $t = get_markup_template("admin_site.tpl");
859         return replace_macros($t, array(
860                 '$title' => t('Administration'),
861                 '$page' => t('Site'),
862                 '$submit' => t('Save Settings'),
863                 '$registration' => t('Registration'),
864                 '$upload' => t('File upload'),
865                 '$corporate' => t('Policies'),
866                 '$advanced' => t('Advanced'),
867                 '$portable_contacts' => t('Auto Discovered Contact Directory'),
868                 '$performance' => t('Performance'),
869                 '$relocate'=> t('Relocate - WARNING: advanced function. Could make this server unreachable.'),
870                 '$baseurl' => $a->get_baseurl(true),
871                 // name, label, value, help string, extra data...
872                 '$sitename'             => array('sitename', t("Site name"), $a->config['sitename'],''),
873                 '$hostname'             => array('hostname', t("Host name"), $a->config['hostname'], ""),
874                 '$sender_email'         => array('sender_email', t("Sender Email"), $a->config['sender_email'], t("The email address your server shall use to send notification emails from."), "", "", "email"),
875                 '$banner'               => array('banner', t("Banner/Logo"), $banner, ""),
876                 '$shortcut_icon'        => array('shortcut_icon', t("Shortcut icon"), get_config('system','shortcut_icon'),  t("Link to an icon that will be used for browsers.")),
877                 '$touch_icon'           => array('touch_icon', t("Touch icon"), get_config('system','touch_icon'),  t("Link to an icon that will be used for tablets and mobiles.")),
878                 '$info' => array('info',t('Additional Info'), $info, sprintf(t('For public servers: you can add additional information here that will be listed at %s/siteinfo.'), get_server())),
879                 '$language'             => array('language', t("System language"), get_config('system','language'), "", $lang_choices),
880                 '$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),
881                 '$theme_mobile'         => array('theme_mobile', t("Mobile system theme"), get_config('system','mobile-theme'), t("Theme for mobile devices"), $theme_choices_mobile),
882                 '$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),
883                 '$force_ssl'            => array('force_ssl', t("Force SSL"), get_config('system','force_ssl'), t("Force all Non-SSL requests to SSL - Attention: on some systems it could lead to endless loops.")),
884                 '$old_share'            => array('old_share', t("Old style 'Share'"), get_config('system','old_share'), t("Deactivates the bbcode element 'share' for repeating items.")),
885                 '$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.")),
886                 '$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),
887                 '$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.")),
888                 '$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.")),
889                 '$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.")),
890
891                 '$register_policy'      => array('register_policy', t("Register policy"), $a->config['register_policy'], "", $register_choices),
892                 '$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.")),
893                 '$register_text'        => array('register_text', t("Register text"), $a->config['register_text'], t("Will be displayed prominently on the registration page.")),
894                 '$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.')),
895                 '$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")),
896                 '$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")),
897                 '$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.")),
898                 '$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.")),
899                 '$global_directory'     => array('directory', t("Global directory URL"), get_config('system','directory'), t("URL to the global directory. If this is not set, the global directory is completely unavailable to the application.")),
900                 '$thread_allow'         => array('thread_allow', t("Allow threaded items"), get_config('system','thread_allow'), t("Allow infinite level threading for items on this site.")),
901                 '$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.")),
902                 '$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.")),
903                 '$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.")),
904                 '$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.")),
905                 '$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.')),
906                 '$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.")),
907                 '$no_openid'            => array('no_openid', t("OpenID support"), !get_config('system','no_openid'), t("OpenID support for registration and logins.")),
908                 '$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")),
909                 '$no_utf'               => array('no_utf', t("UTF-8 Regular expressions"), !get_config('system','no_utf'), t("Use PHP UTF8 regular expressions")),
910                 '$community_page_style' => array('community_page_style', t("Community Page Style"), get_config('system','community_page_style'), t("Type of community page to show. 'Global community' shows every public posting from an open distributed network that arrived on this server."), $community_page_style_choices),
911                 '$max_author_posts_community_page' => array('max_author_posts_community_page', t("Posts per user on community page"), get_config('system','max_author_posts_community_page'), t("The maximum number of posts per user on the community page. (Not valid for 'Global Community')")),
912                 '$ostatus_disabled'     => array('ostatus_disabled', t("Enable OStatus support"), !get_config('system','ostatus_disabled'), t("Provide built-in OStatus \x28StatusNet, GNU Social etc.\x29 compatibility. All communications in OStatus are public, so privacy warnings will be occasionally displayed.")),
913                 '$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),
914                 '$ostatus_not_able'     => t("OStatus support can only be enabled if threading is enabled."),
915                 '$diaspora_able'        => $diaspora_able,
916                 '$diaspora_not_able'    => t("Diaspora support can't be enabled because Friendica was installed into a sub directory."),
917                 '$diaspora_enabled'     => array('diaspora_enabled', t("Enable Diaspora support"), get_config('system','diaspora_enabled'), t("Provide built-in Diaspora network compatibility.")),
918                 '$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.")),
919                 '$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.")),
920                 '$proxyuser'            => array('proxyuser', t("Proxy user"), get_config('system','proxyuser'), ""),
921                 '$proxy'                => array('proxy', t("Proxy URL"), get_config('system','proxy'), ""),
922                 '$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).")),
923                 '$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.")),
924                 '$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.")),
925                 '$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.")),
926                 '$maxloadavg_frontend'  => array('maxloadavg_frontend', t("Maximum Load Average (Frontend)"), ((intval(get_config('system','maxloadavg_frontend')) > 0)?get_config('system','maxloadavg_frontend'):50), t("Maximum system load before the frontend quits service - default 50.")),
927                 '$optimize_max_tablesize'=> array('optimize_max_tablesize', t("Maximum table size for optimization"), ((intval(get_config('system','optimize_max_tablesize')) > 0)?get_config('system','optimize_max_tablesize'):100), t("Maximum table size (in MB) for the automatic optimization - default 100 MB. Enter -1 to disable it.")),
928                 '$optimize_fragmentation'=> array('optimize_fragmentation', t("Minimum level of fragmentation"), ((intval(get_config('system','optimize_fragmentation')) > 0)?get_config('system','optimize_fragmentation'):30), t("Minimum fragmenation level to start the automatic optimization - default value is 30%.")),
929
930                 '$poco_completion'      => array('poco_completion', t("Periodical check of global contacts"), get_config('system','poco_completion'), t("If enabled, the global contacts are checked periodically for missing or outdated data and the vitality of the contacts and servers.")),
931                 '$poco_requery_days'    => array('poco_requery_days', t("Days between requery"), get_config('system','poco_requery_days'), t("Number of days after which a server is requeried for his contacts.")),
932                 '$poco_discovery'       => array('poco_discovery', t("Discover contacts from other servers"), (string) intval(get_config('system','poco_discovery')), t("Periodically query other servers for contacts. You can choose between 'users': the users on the remote system, 'Global Contacts': active contacts that are known on the system. The fallback is meant for Redmatrix servers and older friendica servers, where global contacts weren't available. The fallback increases the server load, so the recommened setting is 'Users, Global Contacts'."), $poco_discovery_choices),
933                 '$poco_discovery_since' => array('poco_discovery_since', t("Timeframe for fetching global contacts"), (string) intval(get_config('system','poco_discovery_since')), t("When the discovery is activated, this value defines the timeframe for the activity of the global contacts that are fetched from other servers."), $poco_discovery_since_choices),
934                 '$poco_local_search'    => array('poco_local_search', t("Search the local directory"), get_config('system','poco_local_search'), t("Search the local directory instead of the global directory. When searching locally, every search will be executed on the global directory in the background. This improves the search results when the search is repeated.")),
935
936                 '$nodeinfo'             => array('nodeinfo', t("Publish server information"), get_config('system','nodeinfo'), t("If enabled, general server and usage data will be published. The data contains the name and version of the server, number of users with public profiles, number of posts and the activated protocols and connectors. See <a href='http://the-federation.info/'>the-federation.info</a> for details.")),
937
938                 '$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.")),
939                 '$suppress_language'    => array('suppress_language', t("Suppress Language"), get_config('system','suppress_language'), t("Suppress language information in meta information about a posting.")),
940                 '$suppress_tags'        => array('suppress_tags', t("Suppress Tags"), get_config('system','suppress_tags'), t("Suppress showing a list of hashtags at the end of the posting.")),
941                 '$itemcache'            => array('itemcache', t("Path to item cache"), get_config('system','itemcache'), t("The item caches buffers generated bbcode and external images.")),
942                 '$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). To disable the item cache, set the value to -1.")),
943                 '$max_comments'         => array('max_comments', t("Maximum numbers of comments per post"), get_config('system','max_comments'), t("How much comments should be shown for each post? Default value is 100.")),
944                 '$lockpath'             => array('lockpath', t("Path for lock file"), get_config('system','lockpath'), t("The lock file is used to avoid multiple pollers at one time. Only define a folder here.")),
945                 '$temppath'             => array('temppath', t("Temp path"), get_config('system','temppath'), t("If you have a restricted system where the webserver can't access the system temp path, enter another path here.")),
946                 '$basepath'             => array('basepath', t("Base path to installation"), get_config('system','basepath'), t("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.")),
947                 '$proxy_disabled'       => array('proxy_disabled', t("Disable picture proxy"), get_config('system','proxy_disabled'), t("The picture proxy increases performance and privacy. It shouldn't be used on systems with very low bandwith.")),
948                 '$old_pager'            => array('old_pager', t("Enable old style pager"), get_config('system','old_pager'), t("The old style pager has page numbers but slows down massively the page speed.")),
949                 '$only_tag_search'      => array('only_tag_search', t("Only search in tags"), get_config('system','only_tag_search'), t("On large systems the text search can slow down the system extremely.")),
950
951                 '$relocate_url'         => array('relocate_url', t("New base url"), $a->get_baseurl(), t("Change base url for this server. Sends relocate message to all DFRN contacts of all users.")),
952
953                 '$rino'                 => array('rino', t("RINO Encryption"), intval(get_config('system','rino_encrypt')), t("Encryption layer between nodes."), array("Disabled", "RINO1 (deprecated)", "RINO2")),
954                 '$embedly'              => array('embedly', t("Embedly API key"), get_config('system','embedly'), t("<a href='http://embed.ly'>Embedly</a> is used to fetch additional data for web pages. This is an optional parameter.")),
955
956                 '$form_security_token' => get_form_security_token("admin_site")
957
958         ));
959
960 }
961
962 /**
963  * @brief generates admin panel subpage for DB syncronization
964  *
965  * This page checks if the database of friendica is in sync with the specs.
966  * Should this not be the case, it attemps to sync the structure and notifies
967  * the admin if the automatic process was failing.
968  *
969  * The returned string holds the HTML code of the page.
970  *
971  * @param App $a
972  * @return string
973  **/
974 function admin_page_dbsync(&$a) {
975
976         $o = '';
977
978         if($a->argc > 3 && intval($a->argv[3]) && $a->argv[2] === 'mark') {
979                 set_config('database', 'update_' . intval($a->argv[3]), 'success');
980                 $curr = get_config('system','build');
981                 if(intval($curr) == intval($a->argv[3]))
982                         set_config('system','build',intval($curr) + 1);
983                 info( t('Update has been marked successful') . EOL);
984                 goaway($a->get_baseurl(true) . '/admin/dbsync');
985         }
986
987         if(($a->argc > 2) AND (intval($a->argv[2]) OR ($a->argv[2] === 'check'))) {
988                 require_once("include/dbstructure.php");
989                 $retval = update_structure(false, true);
990                 if (!$retval) {
991                         $o .= sprintf(t("Database structure update %s was successfully applied."), DB_UPDATE_VERSION)."<br />";
992                         set_config('database', 'dbupdate_'.DB_UPDATE_VERSION, 'success');
993                 } else
994                         $o .= sprintf(t("Executing of database structure update %s failed with error: %s"),
995                                         DB_UPDATE_VERSION, $retval)."<br />";
996                 if ($a->argv[2] === 'check')
997                         return $o;
998         }
999
1000         if ($a->argc > 2 && intval($a->argv[2])) {
1001                 require_once('update.php');
1002                 $func = 'update_' . intval($a->argv[2]);
1003                 if(function_exists($func)) {
1004                         $retval = $func();
1005                         if($retval === UPDATE_FAILED) {
1006                                 $o .= sprintf(t("Executing %s failed with error: %s"), $func, $retval);
1007                         }
1008                         elseif($retval === UPDATE_SUCCESS) {
1009                                 $o .= sprintf(t('Update %s was successfully applied.', $func));
1010                                 set_config('database',$func, 'success');
1011                         }
1012                         else
1013                                 $o .= sprintf(t('Update %s did not return a status. Unknown if it succeeded.'), $func);
1014                 } else {
1015                         $o .= sprintf(t('There was no additional update function %s that needed to be called.'), $func)."<br />";
1016                         set_config('database',$func, 'success');
1017                 }
1018                 return $o;
1019         }
1020
1021         $failed = array();
1022         $r = q("select k, v from config where `cat` = 'database' ");
1023         if(count($r)) {
1024                 foreach($r as $rr) {
1025                         $upd = intval(substr($rr['k'],7));
1026                         if($upd < 1139 || $rr['v'] === 'success')
1027                                 continue;
1028                         $failed[] = $upd;
1029                 }
1030         }
1031         if(! count($failed)) {
1032                 $o = replace_macros(get_markup_template('structure_check.tpl'),array(
1033                         '$base' => $a->get_baseurl(true),
1034                         '$banner' => t('No failed updates.'),
1035                         '$check' => t('Check database structure'),
1036                 ));
1037         } else {
1038                 $o = replace_macros(get_markup_template('failed_updates.tpl'),array(
1039                         '$base' => $a->get_baseurl(true),
1040                         '$banner' => t('Failed Updates'),
1041                         '$desc' => t('This does not include updates prior to 1139, which did not return a status.'),
1042                         '$mark' => t('Mark success (if update was manually applied)'),
1043                         '$apply' => t('Attempt to execute this update step automatically'),
1044                         '$failed' => $failed
1045                 ));
1046         }
1047
1048         return $o;
1049
1050 }
1051
1052 /**
1053  * @brief process data send by Users admin page
1054  * @param App $a
1055  */
1056 function admin_page_users_post(&$a){
1057         $pending = ( x($_POST, 'pending') ? $_POST['pending'] : Array() );
1058         $users = ( x($_POST, 'user') ? $_POST['user'] : Array() );
1059         $nu_name = ( x($_POST, 'new_user_name') ? $_POST['new_user_name'] : '');
1060         $nu_nickname = ( x($_POST, 'new_user_nickname') ? $_POST['new_user_nickname'] : '');
1061         $nu_email = ( x($_POST, 'new_user_email') ? $_POST['new_user_email'] : '');
1062
1063         check_form_security_token_redirectOnErr('/admin/users', 'admin_users');
1064
1065         if (!($nu_name==="") && !($nu_email==="") && !($nu_nickname==="")) {
1066                 require_once('include/user.php');
1067
1068                 $result = create_user( array('username'=>$nu_name, 'email'=>$nu_email, 'nickname'=>$nu_nickname, 'verified'=>1)  );
1069                 if(! $result['success']) {
1070                         notice($result['message']);
1071                         return;
1072                 }
1073                 $nu = $result['user'];
1074                 $preamble = deindent(t('
1075                         Dear %1$s,
1076                                 the administrator of %2$s has set up an account for you.'));
1077                 $body = deindent(t('
1078                         The login details are as follows:
1079
1080                         Site Location:  %1$s
1081                         Login Name:             %2$s
1082                         Password:               %3$s
1083
1084                         You may change your password from your account "Settings" page after logging
1085                         in.
1086
1087                         Please take a few moments to review the other account settings on that page.
1088
1089                         You may also wish to add some basic information to your default profile
1090                         (on the "Profiles" page) so that other people can easily find you.
1091
1092                         We recommend setting your full name, adding a profile photo,
1093                         adding some profile "keywords" (very useful in making new friends) - and
1094                         perhaps what country you live in; if you do not wish to be more specific
1095                         than that.
1096
1097                         We fully respect your right to privacy, and none of these items are necessary.
1098                         If you are new and do not know anybody here, they may help
1099                         you to make some new and interesting friends.
1100
1101                         Thank you and welcome to %4$s.'));
1102
1103                 $preamble = sprintf($preamble, $nu['username'], $a->config['sitename']);
1104                 $body = sprintf($body, $a->get_baseurl(), $nu['email'], $result['password'], $a->config['sitename']);
1105
1106                 notification(array(
1107                         'type' => "SYSTEM_EMAIL",
1108                         'to_email' => $nu['email'],
1109                         'subject'=> sprintf( t('Registration details for %s'), $a->config['sitename']),
1110                         'preamble'=> $preamble,
1111                         'body' => $body));
1112
1113         }
1114
1115         if (x($_POST,'page_users_block')){
1116                 foreach($users as $uid){
1117                         q("UPDATE `user` SET `blocked`=1-`blocked` WHERE `uid`=%s",
1118                                 intval( $uid )
1119                         );
1120                 }
1121                 notice( sprintf( tt("%s user blocked/unblocked", "%s users blocked/unblocked", count($users)), count($users)) );
1122         }
1123         if (x($_POST,'page_users_delete')){
1124                 require_once("include/Contact.php");
1125                 foreach($users as $uid){
1126                         user_remove($uid);
1127                 }
1128                 notice( sprintf( tt("%s user deleted", "%s users deleted", count($users)), count($users)) );
1129         }
1130
1131         if (x($_POST,'page_users_approve')){
1132                 require_once("mod/regmod.php");
1133                 foreach($pending as $hash){
1134                         user_allow($hash);
1135                 }
1136         }
1137         if (x($_POST,'page_users_deny')){
1138                 require_once("mod/regmod.php");
1139                 foreach($pending as $hash){
1140                         user_deny($hash);
1141                 }
1142         }
1143         goaway($a->get_baseurl(true) . '/admin/users' );
1144         return; // NOTREACHED
1145 }
1146
1147 /**
1148  * @brief admin panel subpage for User management
1149  *
1150  * This function generates the admin panel page for user management of the
1151  * node. It offers functionality to add/block/delete users and offers some
1152  * statistics about the userbase.
1153  *
1154  * The returned string holds the HTML code of the page.
1155  *
1156  * @param App $a
1157  * @return string
1158  */
1159 function admin_page_users(&$a){
1160         if ($a->argc>2) {
1161                 $uid = $a->argv[3];
1162                 $user = q("SELECT username, blocked FROM `user` WHERE `uid`=%d", intval($uid));
1163                 if (count($user)==0){
1164                         notice( 'User not found' . EOL);
1165                         goaway($a->get_baseurl(true) . '/admin/users' );
1166                         return ''; // NOTREACHED
1167                 }
1168                 switch($a->argv[2]){
1169                         case "delete":{
1170                                 check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't');
1171                                 // delete user
1172                                 require_once("include/Contact.php");
1173                                 user_remove($uid);
1174
1175                                 notice( sprintf(t("User '%s' deleted"), $user[0]['username']) . EOL);
1176                         }; break;
1177                         case "block":{
1178                                 check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't');
1179                                 q("UPDATE `user` SET `blocked`=%d WHERE `uid`=%s",
1180                                         intval( 1-$user[0]['blocked'] ),
1181                                         intval( $uid )
1182                                 );
1183                                 notice( sprintf( ($user[0]['blocked']?t("User '%s' unblocked"):t("User '%s' blocked")) , $user[0]['username']) . EOL);
1184                         }; break;
1185                 }
1186                 goaway($a->get_baseurl(true) . '/admin/users' );
1187                 return ''; // NOTREACHED
1188
1189         }
1190
1191         /* get pending */
1192         $pending = q("SELECT `register`.*, `contact`.`name`, `user`.`email`
1193                                  FROM `register`
1194                                  LEFT JOIN `contact` ON `register`.`uid` = `contact`.`uid`
1195                                  LEFT JOIN `user` ON `register`.`uid` = `user`.`uid`;");
1196
1197
1198         /* get users */
1199
1200         $total = q("SELECT count(*) as total FROM `user` where 1");
1201         if(count($total)) {
1202                 $a->set_pager_total($total[0]['total']);
1203                 $a->set_pager_itemspage(100);
1204         }
1205
1206
1207         $users = q("SELECT `user` . * , `contact`.`name` , `contact`.`url` , `contact`.`micro`, `lastitem`.`lastitem_date`, `user`.`account_expired`
1208                                 FROM
1209                                         (SELECT MAX(`item`.`changed`) as `lastitem_date`, `item`.`uid`
1210                                         FROM `item`
1211                                         WHERE `item`.`type` = 'wall'
1212                                         GROUP BY `item`.`uid`) AS `lastitem`
1213                                                  RIGHT OUTER JOIN `user` ON `user`.`uid` = `lastitem`.`uid`,
1214                                            `contact`
1215                                 WHERE
1216                                            `user`.`uid` = `contact`.`uid`
1217                                                 AND `user`.`verified` =1
1218                                         AND `contact`.`self` =1
1219                                 ORDER BY `contact`.`name` LIMIT %d, %d
1220                                 ",
1221                                 intval($a->pager['start']),
1222                                 intval($a->pager['itemspage'])
1223                                 );
1224
1225         $adminlist = explode(",", str_replace(" ", "", $a->config['admin_email']));
1226         $_setup_users = function ($e) use ($adminlist){
1227                 $accounts = Array(
1228                         t('Normal Account'),
1229                         t('Soapbox Account'),
1230                         t('Community/Celebrity Account'),
1231                                                 t('Automatic Friend Account')
1232                 );
1233                 $e['page-flags'] = $accounts[$e['page-flags']];
1234                 $e['register_date'] = relative_date($e['register_date']);
1235                 $e['login_date'] = relative_date($e['login_date']);
1236                 $e['lastitem_date'] = relative_date($e['lastitem_date']);
1237                 //$e['is_admin'] = ($e['email'] === $a->config['admin_email']);
1238                 $e['is_admin'] = in_array($e['email'], $adminlist);
1239                 $e['is_deletable'] = (intval($e['uid']) != local_user());
1240                 $e['deleted'] = ($e['account_removed']?relative_date($e['account_expires_on']):False);
1241                 return $e;
1242         };
1243         $users = array_map($_setup_users, $users);
1244
1245
1246         // Get rid of dashes in key names, Smarty3 can't handle them
1247         // and extracting deleted users
1248
1249         $tmp_users = Array();
1250         $deleted = Array();
1251
1252         while(count($users)) {
1253                 $new_user = Array();
1254                 foreach( array_pop($users) as $k => $v) {
1255                         $k = str_replace('-','_',$k);
1256                         $new_user[$k] = $v;
1257                 }
1258                 if($new_user['deleted']) {
1259                         array_push($deleted, $new_user);
1260                 }
1261                 else {
1262                         array_push($tmp_users, $new_user);
1263                 }
1264         }
1265         //Reversing the two array, and moving $tmp_users to $users
1266         array_reverse($deleted);
1267         while(count($tmp_users)) {
1268                 array_push($users, array_pop($tmp_users));
1269         }
1270
1271         $t = get_markup_template("admin_users.tpl");
1272         $o = replace_macros($t, array(
1273                 // strings //
1274                 '$title' => t('Administration'),
1275                 '$page' => t('Users'),
1276                 '$submit' => t('Add User'),
1277                 '$select_all' => t('select all'),
1278                 '$h_pending' => t('User registrations waiting for confirm'),
1279                 '$h_deleted' => t('User waiting for permanent deletion'),
1280                 '$th_pending' => array( t('Request date'), t('Name'), t('Email') ),
1281                 '$no_pending' =>  t('No registrations.'),
1282                 '$approve' => t('Approve'),
1283                 '$deny' => t('Deny'),
1284                 '$delete' => t('Delete'),
1285                 '$block' => t('Block'),
1286                 '$unblock' => t('Unblock'),
1287                 '$siteadmin' => t('Site admin'),
1288                 '$accountexpired' => t('Account expired'),
1289
1290                 '$h_users' => t('Users'),
1291                 '$h_newuser' => t('New User'),
1292                 '$th_deleted' => array( t('Name'), t('Email'), t('Register date'), t('Last login'), t('Last item'), t('Deleted since') ),
1293                 '$th_users' => array( t('Name'), t('Email'), t('Register date'), t('Last login'), t('Last item'),  t('Account') ),
1294
1295                 '$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?'),
1296                 '$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?'),
1297
1298                 '$form_security_token' => get_form_security_token("admin_users"),
1299
1300                 // values //
1301                 '$baseurl' => $a->get_baseurl(true),
1302
1303                 '$pending' => $pending,
1304                 'deleted' => $deleted,
1305                 '$users' => $users,
1306                 '$newusername'  => array('new_user_name', t("Name"), '', t("Name of the new user.")),
1307                 '$newusernickname'  => array('new_user_nickname', t("Nickname"), '', t("Nickname of the new user.")),
1308                 '$newuseremail'  => array('new_user_email', t("Email"), '', t("Email address of the new user."), '', '', 'email'),
1309         ));
1310         $o .= paginate($a);
1311         return $o;
1312 }
1313
1314
1315 /**
1316  * @brief Plugins admin page
1317  * @param App $a
1318  * @return string
1319  */
1320 function admin_page_plugins(&$a){
1321
1322         /**
1323          * Single plugin
1324          */
1325         if ($a->argc == 3){
1326                 $plugin = $a->argv[2];
1327                 if (!is_file("addon/$plugin/$plugin.php")){
1328                         notice( t("Item not found.") );
1329                         return '';
1330                 }
1331
1332                 if (x($_GET,"a") && $_GET['a']=="t"){
1333                         check_form_security_token_redirectOnErr('/admin/plugins', 'admin_themes', 't');
1334
1335                         // Toggle plugin status
1336                         $idx = array_search($plugin, $a->plugins);
1337                         if ($idx !== false){
1338                                 unset($a->plugins[$idx]);
1339                                 uninstall_plugin($plugin);
1340                                 info( sprintf( t("Plugin %s disabled."), $plugin ) );
1341                         } else {
1342                                 $a->plugins[] = $plugin;
1343                                 install_plugin($plugin);
1344                                 info( sprintf( t("Plugin %s enabled."), $plugin ) );
1345                         }
1346                         set_config("system","addon", implode(", ",$a->plugins));
1347                         goaway($a->get_baseurl(true) . '/admin/plugins' );
1348                         return ''; // NOTREACHED
1349                 }
1350                 // display plugin details
1351                 require_once('library/markdown.php');
1352
1353                 if (in_array($plugin, $a->plugins)){
1354                         $status="on"; $action= t("Disable");
1355                 } else {
1356                         $status="off"; $action= t("Enable");
1357                 }
1358
1359                 $readme=Null;
1360                 if (is_file("addon/$plugin/README.md")){
1361                         $readme = file_get_contents("addon/$plugin/README.md");
1362                         $readme = Markdown($readme);
1363                 } else if (is_file("addon/$plugin/README")){
1364                         $readme = "<pre>". file_get_contents("addon/$plugin/README") ."</pre>";
1365                 }
1366
1367                 $admin_form="";
1368                 if (is_array($a->plugins_admin) && in_array($plugin, $a->plugins_admin)){
1369                         @require_once("addon/$plugin/$plugin.php");
1370                         $func = $plugin.'_plugin_admin';
1371                         $func($a, $admin_form);
1372                 }
1373
1374                 $t = get_markup_template("admin_plugins_details.tpl");
1375
1376                 return replace_macros($t, array(
1377                         '$title' => t('Administration'),
1378                         '$page' => t('Plugins'),
1379                         '$toggle' => t('Toggle'),
1380                         '$settings' => t('Settings'),
1381                         '$baseurl' => $a->get_baseurl(true),
1382
1383                         '$plugin' => $plugin,
1384                         '$status' => $status,
1385                         '$action' => $action,
1386                         '$info' => get_plugin_info($plugin),
1387                         '$str_author' => t('Author: '),
1388                         '$str_maintainer' => t('Maintainer: '),
1389
1390                         '$admin_form' => $admin_form,
1391                         '$function' => 'plugins',
1392                         '$screenshot' => '',
1393                         '$readme' => $readme,
1394
1395                         '$form_security_token' => get_form_security_token("admin_themes"),
1396                 ));
1397         }
1398
1399
1400
1401         /**
1402          * List plugins
1403          */
1404
1405         if (x($_GET,"a") && $_GET['a']=="r"){
1406                 check_form_security_token_redirectOnErr($a->get_baseurl().'/admin/plugins', 'admin_themes', 't');
1407                 reload_plugins();
1408                 info("Plugins reloaded");
1409                 goaway($a->get_baseurl().'/admin/plugins');
1410         }
1411
1412         $plugins = array();
1413         $files = glob("addon/*/"); /* */
1414         if($files) {
1415                 foreach($files as $file) {
1416                         if (is_dir($file)){
1417                                 list($tmp, $id)=array_map("trim", explode("/",$file));
1418                                 $info = get_plugin_info($id);
1419                                 $show_plugin = true;
1420
1421                                 // If the addon is unsupported, then only show it, when it is enabled
1422                                 if ((strtolower($info["status"]) == "unsupported") AND !in_array($id,  $a->plugins))
1423                                         $show_plugin = false;
1424
1425                                 // Override the above szenario, when the admin really wants to see outdated stuff
1426                                 if (get_config("system", "show_unsupported_addons"))
1427                                         $show_plugin = true;
1428
1429                                 if ($show_plugin)
1430                                         $plugins[] = array($id, (in_array($id,  $a->plugins)?"on":"off") , $info);
1431                         }
1432                 }
1433         }
1434
1435         $t = get_markup_template("admin_plugins.tpl");
1436         return replace_macros($t, array(
1437                 '$title' => t('Administration'),
1438                 '$page' => t('Plugins'),
1439                 '$submit' => t('Save Settings'),
1440                 '$reload' => t('Reload active plugins'),
1441                 '$baseurl' => $a->get_baseurl(true),
1442                 '$function' => 'plugins',
1443                 '$plugins' => $plugins,
1444                 '$pcount' => count($plugins), 
1445                 '$noplugshint' => sprintf( t('There are currently no plugins available on your node. You can find the official plugin repository at %1$s and might find other interesting plugins in the open plugin registry at %2$s'), 'https://github.com/friendica/friendica-addons', 'http://addons.friendi.ca'),
1446                 '$form_security_token' => get_form_security_token("admin_themes"),
1447         ));
1448 }
1449
1450 /**
1451  * @param array $themes
1452  * @param string $th
1453  * @param int $result
1454  */
1455 function toggle_theme(&$themes,$th,&$result) {
1456         for($x = 0; $x < count($themes); $x ++) {
1457                 if($themes[$x]['name'] === $th) {
1458                         if($themes[$x]['allowed']) {
1459                                 $themes[$x]['allowed'] = 0;
1460                                 $result = 0;
1461                         }
1462                         else {
1463                                 $themes[$x]['allowed'] = 1;
1464                                 $result = 1;
1465                         }
1466                 }
1467         }
1468 }
1469
1470 /**
1471  * @param array $themes
1472  * @param string $th
1473  * @return int
1474  */
1475 function theme_status($themes,$th) {
1476         for($x = 0; $x < count($themes); $x ++) {
1477                 if($themes[$x]['name'] === $th) {
1478                         if($themes[$x]['allowed']) {
1479                                 return 1;
1480                         }
1481                         else {
1482                                 return 0;
1483                         }
1484                 }
1485         }
1486         return 0;
1487 }
1488
1489
1490 /**
1491  * @param array $themes
1492  * @return string
1493  */
1494 function rebuild_theme_table($themes) {
1495         $o = '';
1496         if(count($themes)) {
1497                 foreach($themes as $th) {
1498                         if($th['allowed']) {
1499                                 if(strlen($o))
1500                                         $o .= ',';
1501                                 $o .= $th['name'];
1502                         }
1503                 }
1504         }
1505         return $o;
1506 }
1507
1508
1509 /**
1510  * Themes admin page
1511  *
1512  * @param App $a
1513  * @return string
1514  */
1515 function admin_page_themes(&$a){
1516
1517         $allowed_themes_str = get_config('system','allowed_themes');
1518         $allowed_themes_raw = explode(',',$allowed_themes_str);
1519         $allowed_themes = array();
1520         if(count($allowed_themes_raw))
1521                 foreach($allowed_themes_raw as $x)
1522                         if(strlen(trim($x)))
1523                                 $allowed_themes[] = trim($x);
1524
1525         $themes = array();
1526         $files = glob('view/theme/*'); /* */
1527         if($files) {
1528                 foreach($files as $file) {
1529                         $f = basename($file);
1530                         $is_experimental = intval(file_exists($file . '/experimental'));
1531                         $is_supported = 1-(intval(file_exists($file . '/unsupported')));
1532                         $is_allowed = intval(in_array($f,$allowed_themes));
1533
1534                         if ($is_allowed OR $is_supported OR get_config("system", "show_unsupported_themes"))
1535                                 $themes[] = array('name' => $f, 'experimental' => $is_experimental, 'supported' => $is_supported, 'allowed' => $is_allowed);
1536                 }
1537         }
1538
1539         if(! count($themes)) {
1540                 notice( t('No themes found.'));
1541                 return '';
1542         }
1543
1544         /**
1545          * Single theme
1546          */
1547
1548         if ($a->argc == 3){
1549                 $theme = $a->argv[2];
1550                 if(! is_dir("view/theme/$theme")){
1551                         notice( t("Item not found.") );
1552                         return '';
1553                 }
1554
1555                 if (x($_GET,"a") && $_GET['a']=="t"){
1556                         check_form_security_token_redirectOnErr('/admin/themes', 'admin_themes', 't');
1557
1558                         // Toggle theme status
1559
1560                         toggle_theme($themes,$theme,$result);
1561                         $s = rebuild_theme_table($themes);
1562                         if($result) {
1563                                 install_theme($theme);
1564                                 info( sprintf('Theme %s enabled.',$theme));
1565                         }
1566                         else {
1567                                 uninstall_theme($theme);
1568                                 info( sprintf('Theme %s disabled.',$theme));
1569                         }
1570
1571                         set_config('system','allowed_themes',$s);
1572                         goaway($a->get_baseurl(true) . '/admin/themes' );
1573                         return ''; // NOTREACHED
1574                 }
1575
1576                 // display theme details
1577                 require_once('library/markdown.php');
1578
1579                 if (theme_status($themes,$theme)) {
1580                         $status="on"; $action= t("Disable");
1581                 } else {
1582                         $status="off"; $action= t("Enable");
1583                 }
1584
1585                 $readme=Null;
1586                 if (is_file("view/theme/$theme/README.md")){
1587                         $readme = file_get_contents("view/theme/$theme/README.md");
1588                         $readme = Markdown($readme);
1589                 } else if (is_file("view/theme/$theme/README")){
1590                         $readme = "<pre>". file_get_contents("view/theme/$theme/README") ."</pre>";
1591                 }
1592
1593                 $admin_form="";
1594                 if (is_file("view/theme/$theme/config.php")){
1595                         function __get_theme_admin_form(&$a, $theme) {
1596                                 $orig_theme = $a->theme;
1597                                 $orig_page = $a->page;
1598                                 $orig_session_theme = $_SESSION['theme'];
1599                                 require_once("view/theme/$theme/theme.php");
1600                                 require_once("view/theme/$theme/config.php");
1601                                 $_SESSION['theme'] = $theme;
1602
1603
1604                                 $init = $theme."_init";
1605                                 if(function_exists($init)) $init($a);
1606                                 if(function_exists("theme_admin")){
1607                                         $admin_form = theme_admin($a);
1608                                 }
1609
1610                                 $_SESSION['theme'] = $orig_session_theme;
1611                                 $a->theme = $orig_theme;
1612                                 $a->page = $orig_page;
1613                                 return $admin_form;
1614                         }
1615                         $admin_form = __get_theme_admin_form($a, $theme);
1616                 }
1617
1618                 $screenshot = array( get_theme_screenshot($theme), t('Screenshot'));
1619                 if(! stristr($screenshot[0],$theme))
1620                         $screenshot = null;
1621
1622                 $t = get_markup_template("admin_plugins_details.tpl");
1623                 return replace_macros($t, array(
1624                         '$title' => t('Administration'),
1625                         '$page' => t('Themes'),
1626                         '$toggle' => t('Toggle'),
1627                         '$settings' => t('Settings'),
1628                         '$baseurl' => $a->get_baseurl(true),
1629
1630                         '$plugin' => $theme,
1631                         '$status' => $status,
1632                         '$action' => $action,
1633                         '$info' => get_theme_info($theme),
1634                         '$function' => 'themes',
1635                         '$admin_form' => $admin_form,
1636                         '$str_author' => t('Author: '),
1637                         '$str_maintainer' => t('Maintainer: '),
1638                         '$screenshot' => $screenshot,
1639                         '$readme' => $readme,
1640
1641                         '$form_security_token' => get_form_security_token("admin_themes"),
1642                 ));
1643         }
1644
1645
1646         // reload active themes
1647         if (x($_GET,"a") && $_GET['a']=="r"){
1648                 check_form_security_token_redirectOnErr($a->get_baseurl().'/admin/themes', 'admin_themes', 't');
1649                 if ($themes) {
1650                         foreach($themes as $th) {
1651                                 if ($th['allowed']) {
1652                                         uninstall_theme($th['name']);
1653                                         install_theme($th['name']);
1654                                 }
1655                         }
1656                 }
1657                 info("Themes reloaded");
1658                 goaway($a->get_baseurl().'/admin/themes');
1659         }
1660
1661         /**
1662          * List themes
1663          */
1664
1665         $xthemes = array();
1666         if($themes) {
1667                 foreach($themes as $th) {
1668                         $xthemes[] = array($th['name'],(($th['allowed']) ? "on" : "off"), get_theme_info($th['name']));
1669                 }
1670         }
1671
1672
1673         $t = get_markup_template("admin_plugins.tpl");
1674         return replace_macros($t, array(
1675                 '$title' => t('Administration'),
1676                 '$page' => t('Themes'),
1677                 '$submit' => t('Save Settings'),
1678                 '$reload' => t('Reload active themes'),
1679                 '$baseurl' => $a->get_baseurl(true),
1680                 '$function' => 'themes',
1681                 '$plugins' => $xthemes,
1682                 '$experimental' => t('[Experimental]'),
1683                 '$unsupported' => t('[Unsupported]'),
1684                 '$form_security_token' => get_form_security_token("admin_themes"),
1685         ));
1686 }
1687
1688
1689 /**
1690  * @brief prosesses data send by Logs admin page
1691  * @param App $a
1692  */
1693
1694 function admin_page_logs_post(&$a) {
1695         if (x($_POST,"page_logs")) {
1696                 check_form_security_token_redirectOnErr('/admin/logs', 'admin_logs');
1697
1698                 $logfile                =       ((x($_POST,'logfile'))          ? notags(trim($_POST['logfile']))       : '');
1699                 $debugging              =       ((x($_POST,'debugging'))        ? true                                  : false);
1700                 $loglevel               =       ((x($_POST,'loglevel'))         ? intval(trim($_POST['loglevel']))      : 0);
1701
1702                 set_config('system','logfile', $logfile);
1703                 set_config('system','debugging',  $debugging);
1704                 set_config('system','loglevel', $loglevel);
1705         }
1706
1707         info( t("Log settings updated.") );
1708         goaway($a->get_baseurl(true) . '/admin/logs' );
1709         return; // NOTREACHED
1710 }
1711
1712 /**
1713  * @brief generates admin panel subpage for configuration of the logs
1714  *
1715  * This function take the view/templates/admin_logs.tpl file and generates a
1716  * page where admin can configure the logging of friendica.
1717  *
1718  * Displaying the log is separated from the log config as the logfile can get
1719  * big depending on the settings and changing settings regarding the logs can
1720  * thus waste bandwidth.
1721  *
1722  * The string returned contains the content of the template file with replaced
1723  * macros.
1724  *
1725  * @param App $a
1726  * @return string
1727  */
1728 function admin_page_logs(&$a){
1729
1730         $log_choices = Array(
1731                 LOGGER_NORMAL => 'Normal',
1732                 LOGGER_TRACE => 'Trace',
1733                 LOGGER_DEBUG => 'Debug',
1734                 LOGGER_DATA => 'Data',
1735                 LOGGER_ALL => 'All'
1736         );
1737
1738         $t = get_markup_template("admin_logs.tpl");
1739
1740 /*      $f = get_config('system','logfile');
1741
1742         $data = '';
1743
1744         if(!file_exists($f)) {
1745                 $data = t("Error trying to open <strong>$f</strong> log file.\r\n<br/>Check to see if file $f exist and is
1746 readable.");
1747         }
1748         else {
1749                 $fp = fopen($f, 'r');
1750                 if(!$fp) {
1751                         $data = t("Couldn't open <strong>$f</strong> log file.\r\n<br/>Check to see if file $f is readable.");
1752                 }
1753                 else {
1754                         $fstat = fstat($fp);
1755                         $size = $fstat['size'];
1756                         if($size != 0)
1757                         {
1758                                 if($size > 5000000 || $size < 0)
1759                                         $size = 5000000;
1760                                 $seek = fseek($fp,0-$size,SEEK_END);
1761                                 if($seek === 0) {
1762                                         $data = escape_tags(fread($fp,$size));
1763                                         while(! feof($fp))
1764                                                 $data .= escape_tags(fread($fp,4096));
1765                                 }
1766                         }
1767                         fclose($fp);
1768                 }
1769         }*/
1770
1771         return replace_macros($t, array(
1772                 '$title' => t('Administration'),
1773                 '$page' => t('Logs'),
1774                 '$submit' => t('Save Settings'),
1775                 '$clear' => t('Clear'),
1776 //              '$data' => $data,
1777                 '$baseurl' => $a->get_baseurl(true),
1778                 '$logname' =>  get_config('system','logfile'),
1779
1780                                                                         // name, label, value, help string, extra data...
1781                 '$debugging'            => array('debugging', t("Enable Debugging"),get_config('system','debugging'), ""),
1782                 '$logfile'                      => array('logfile', t("Log file"), get_config('system','logfile'), t("Must be writable by web server. Relative to your Friendica top-level directory.")),
1783                 '$loglevel'             => array('loglevel', t("Log level"), get_config('system','loglevel'), "", $log_choices),
1784
1785                 '$form_security_token' => get_form_security_token("admin_logs"),
1786                 '$phpheader' => t("PHP logging"),
1787                 '$phphint' => t("To enable logging of PHP errors and warnings you can add the following to the .htconfig.php file of your installation. The filename set in the 'error_log' line is relative to the friendica top-level directory and must be writeable by the web server. The option '1' for 'log_errors' and 'display_errors' is to enable these options, set to '0' to disable them."),
1788                 '$phplogcode' => "error_reporting(E_ERROR | E_WARNING | E_PARSE );\nini_set('error_log','php.out');\nini_set('log_errors','1');\nini_set('display_errors', '1');",
1789         ));
1790 }
1791
1792 /**
1793  * @brief generates admin panel subpage to view the Friendica log
1794  *
1795  * This function loads the template view/templates/admin_viewlogs.tpl to
1796  * display the systemlog content. The filename for the systemlog of friendica
1797  * is relative to the base directory and taken from the config entry 'logfile'
1798  * in the 'system' category.
1799  *
1800  * Displaying the log is separated from the log config as the logfile can get
1801  * big depending on the settings and changing settings regarding the logs can
1802  * thus waste bandwidth.
1803  *
1804  * The string returned contains the content of the template file with replaced
1805  * macros.
1806  *
1807  * @param App $a
1808  * @return string
1809  */
1810 function admin_page_viewlogs(&$a){
1811         $t = get_markup_template("admin_viewlogs.tpl");
1812         $f = get_config('system','logfile');
1813         $data = '';
1814
1815         if(!file_exists($f)) {
1816                 $data = t("Error trying to open <strong>$f</strong> log file.\r\n<br/>Check to see if file $f exist and is readable.");
1817         }
1818         else {
1819                 $fp = fopen($f, 'r');
1820                 if(!$fp) {
1821                         $data = t("Couldn't open <strong>$f</strong> log file.\r\n<br/>Check to see if file $f is readable.");
1822                 }
1823                 else {
1824                         $fstat = fstat($fp);
1825                         $size = $fstat['size'];
1826                         if($size != 0)
1827                         {
1828                                 if($size > 5000000 || $size < 0)
1829                                         $size = 5000000;
1830                                 $seek = fseek($fp,0-$size,SEEK_END);
1831                                 if($seek === 0) {
1832                                         $data = escape_tags(fread($fp,$size));
1833                                         while(! feof($fp))
1834                                                 $data .= escape_tags(fread($fp,4096));
1835                                 }
1836                         }
1837                         fclose($fp);
1838                 }
1839         }
1840         return replace_macros($t, array(
1841                 '$title' => t('Administration'),
1842                 '$page' => t('View Logs'),
1843                 '$data' => $data,
1844                 '$logname' =>  get_config('system','logfile')
1845         ));
1846 }
1847 /**
1848  * @param App $a
1849  */
1850 function admin_page_remoteupdate_post(&$a) {
1851         // this function should be called via ajax post
1852         if(!is_site_admin()) {
1853                 return;
1854         }
1855
1856
1857         if (x($_POST,'remotefile') && $_POST['remotefile']!=""){
1858                 $remotefile = $_POST['remotefile'];
1859                 $ftpdata = (x($_POST['ftphost'])?$_POST:false);
1860                 doUpdate($remotefile, $ftpdata);
1861         } else {
1862                 echo "No remote file to download. Abort!";
1863         }
1864
1865         killme();
1866 }
1867
1868 /**
1869  * @param App $a
1870  * @return string
1871  */
1872 function admin_page_remoteupdate(&$a) {
1873         if(!is_site_admin()) {
1874                 return login(false);
1875         }
1876
1877         $canwrite = canWeWrite();
1878         $canftp = function_exists('ftp_connect');
1879
1880         $needupdate = true;
1881         $u = checkUpdate();
1882         if (!is_array($u)){
1883                 $needupdate = false;
1884                 $u = array('','','');
1885         }
1886
1887         $tpl = get_markup_template("admin_remoteupdate.tpl");
1888         return replace_macros($tpl, array(
1889                 '$baseurl' => $a->get_baseurl(true),
1890                 '$submit' => t("Update now"),
1891                 '$close' => t("Close"),
1892                 '$localversion' => FRIENDICA_VERSION,
1893                 '$remoteversion' => $u[1],
1894                 '$needupdate' => $needupdate,
1895                 '$canwrite' => $canwrite,
1896                 '$canftp'       => $canftp,
1897                 '$ftphost'      => array('ftphost', t("FTP Host"), '',''),
1898                 '$ftppath'      => array('ftppath', t("FTP Path"), '/',''),
1899                 '$ftpuser'      => array('ftpuser', t("FTP User"), '',''),
1900                 '$ftppwd'       => array('ftppwd', t("FTP Password"), '',''),
1901                 '$remotefile'=>array('remotefile','', $u['2'],''),
1902         ));
1903
1904 }