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