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