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