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