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