]> git.mxchange.org Git - friendica.git/blob - mod/contacts.php
69f1884960145776dae8ef104ce0c2490ef69c0e
[friendica.git] / mod / contacts.php
1 <?php
2 /**
3  * @file mod/contacts.php
4  */
5 use Friendica\App;
6 use Friendica\Core\System;
7 use Friendica\Core\Worker;
8 use Friendica\Database\DBM;
9 use Friendica\Model\GlobalContact;
10 use Friendica\Network\Probe;
11 use Friendica\Object\Contact;
12
13 require_once 'include/contact_selectors.php';
14 require_once 'mod/proxy.php';
15
16 function contacts_init(App $a) {
17         if (! local_user()) {
18                 return;
19         }
20
21         $contact_id = 0;
22
23         if((($a->argc == 2) && intval($a->argv[1])) || (($a->argc == 3) && intval($a->argv[1]) && ($a->argv[2] == "posts"))) {
24                 $contact_id = intval($a->argv[1]);
25                 $r = q("SELECT * FROM `contact` WHERE `uid` = %d and `id` = %d LIMIT 1",
26                         intval(local_user()),
27                         intval($contact_id)
28                 );
29                 if (! DBM::is_result($r)) {
30                         $contact_id = 0;
31                 }
32         }
33
34         require_once 'include/group.php';
35         require_once 'include/contact_widgets.php';
36
37         if ($_GET['nets'] == "all") {
38                 $_GET['nets'] = "";
39         }
40
41         if (! x($a->page,'aside')) {
42                 $a->page['aside'] = '';
43         }
44
45         if ($contact_id) {
46                 $a->data['contact'] = $r[0];
47
48                 if (($a->data['contact']['network'] != "") && ($a->data['contact']['network'] != NETWORK_DFRN)) {
49                         $networkname = format_network_name($a->data['contact']['network'],$a->data['contact']['url']);
50                 } else {
51                         $networkname = '';
52                 }
53
54                 /// @TODO Add nice spaces
55                 $vcard_widget = replace_macros(get_markup_template("vcard-widget.tpl"),array(
56                         '$name' => htmlentities($a->data['contact']['name']),
57                         '$photo' => $a->data['contact']['photo'],
58                         '$url' => ($a->data['contact']['network'] == NETWORK_DFRN) ? "redir/".$a->data['contact']['id'] : $a->data['contact']['url'],
59                         '$addr' => (($a->data['contact']['addr'] != "") ? ($a->data['contact']['addr']) : ""),
60                         '$network_name' => $networkname,
61                         '$network' => t('Network:'),
62                         '$account_type' => Contact::getAccountType($a->data['contact'])
63                 ));
64
65                 $finpeople_widget = '';
66                 $follow_widget = '';
67                 $networks_widget = '';
68         } else {
69                 $vcard_widget = '';
70                 $networks_widget .= networks_widget('contacts',$_GET['nets']);
71                 if (isset($_GET['add'])) {
72                         $follow_widget = follow_widget($_GET['add']);
73                 } else {
74                         $follow_widget = follow_widget();
75                 }
76
77                 $findpeople_widget .= findpeople_widget();
78         }
79
80         $groups_widget .= group_side('contacts','group','full',0,$contact_id);
81
82         $a->page['aside'] .= replace_macros(get_markup_template("contacts-widget-sidebar.tpl"),array(
83                 '$vcard_widget' => $vcard_widget,
84                 '$findpeople_widget' => $findpeople_widget,
85                 '$follow_widget' => $follow_widget,
86                 '$groups_widget' => $groups_widget,
87                 '$networks_widget' => $networks_widget
88         ));
89
90         $base = System::baseUrl();
91         $tpl = get_markup_template("contacts-head.tpl");
92         $a->page['htmlhead'] .= replace_macros($tpl,array(
93                 '$baseurl' => System::baseUrl(true),
94                 '$base' => $base
95         ));
96
97         $tpl = get_markup_template("contacts-end.tpl");
98         $a->page['end'] .= replace_macros($tpl,array(
99                 '$baseurl' => System::baseUrl(true),
100                 '$base' => $base
101         ));
102
103
104 }
105
106 function contacts_batch_actions(App $a) {
107         $contacts_id = $_POST['contact_batch'];
108         if (!is_array($contacts_id)) return;
109
110         $orig_records = q("SELECT * FROM `contact` WHERE `id` IN (%s) AND `uid` = %d AND `self` = 0",
111                 implode(",", $contacts_id),
112                 intval(local_user())
113         );
114
115         $count_actions=0;
116         foreach($orig_records as $orig_record) {
117                 $contact_id = $orig_record['id'];
118                 if (x($_POST, 'contacts_batch_update')) {
119                         _contact_update($contact_id);
120                         $count_actions++;
121                 }
122                 if (x($_POST, 'contacts_batch_block')) {
123                         $r  = _contact_block($contact_id, $orig_record);
124                         if ($r) $count_actions++;
125                 }
126                 if (x($_POST, 'contacts_batch_ignore')) {
127                         $r = _contact_ignore($contact_id, $orig_record);
128                         if ($r) $count_actions++;
129                 }
130                 if (x($_POST, 'contacts_batch_archive')) {
131                         $r = _contact_archive($contact_id, $orig_record);
132                         if ($r) $count_actions++;
133                 }
134                 if (x($_POST, 'contacts_batch_drop')) {
135                         _contact_drop($orig_record);
136                         $count_actions++;
137                 }
138         }
139         if ($count_actions>0) {
140                 info ( sprintf( tt("%d contact edited.", "%d contacts edited.", $count_actions), $count_actions) );
141         }
142
143         if (x($_SESSION,'return_url')) {
144                 goaway('' . $_SESSION['return_url']);
145         }
146         else {
147                 goaway('contacts');
148         }
149
150 }
151
152
153 function contacts_post(App $a) {
154
155         if (! local_user()) {
156                 return;
157         }
158
159         if ($a->argv[1]==="batch") {
160                 contacts_batch_actions($a);
161                 return;
162         }
163
164         $contact_id = intval($a->argv[1]);
165         if (! $contact_id) {
166                 return;
167         }
168
169         $orig_record = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
170                 intval($contact_id),
171                 intval(local_user())
172         );
173
174         if (! count($orig_record)) {
175                 notice( t('Could not access contact record.') . EOL);
176                 goaway('contacts');
177                 return; // NOTREACHED
178         }
179
180         call_hooks('contact_edit_post', $_POST);
181
182         $profile_id = intval($_POST['profile-assign']);
183         if ($profile_id) {
184                 $r = q("SELECT `id` FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1",
185                         intval($profile_id),
186                         intval(local_user())
187                 );
188                 if (! DBM::is_result($r)) {
189                         notice( t('Could not locate selected profile.') . EOL);
190                         return;
191                 }
192         }
193
194         $hidden = intval($_POST['hidden']);
195
196         $notify = intval($_POST['notify']);
197
198         $fetch_further_information = intval($_POST['fetch_further_information']);
199
200         $ffi_keyword_blacklist = escape_tags(trim($_POST['ffi_keyword_blacklist']));
201
202         $priority = intval($_POST['poll']);
203         if($priority > 5 || $priority < 0)
204                 $priority = 0;
205
206         $info = escape_tags(trim($_POST['info']));
207
208         $r = q("UPDATE `contact` SET `profile-id` = %d, `priority` = %d , `info` = '%s',
209                 `hidden` = %d, `notify_new_posts` = %d, `fetch_further_information` = %d,
210                 `ffi_keyword_blacklist` = '%s' WHERE `id` = %d AND `uid` = %d",
211                 intval($profile_id),
212                 intval($priority),
213                 dbesc($info),
214                 intval($hidden),
215                 intval($notify),
216                 intval($fetch_further_information),
217                 dbesc($ffi_keyword_blacklist),
218                 intval($contact_id),
219                 intval(local_user())
220         );
221         if($r)
222                 info( t('Contact updated.') . EOL);
223         else
224                 notice( t('Failed to update contact record.') . EOL);
225
226         $r = q("select * from contact where id = %d and uid = %d limit 1",
227                 intval($contact_id),
228                 intval(local_user())
229         );
230         if($r && DBM::is_result($r))
231                 $a->data['contact'] = $r[0];
232
233         return;
234
235 }
236
237 /*contact actions*/
238 function _contact_update($contact_id) {
239         $r = q("SELECT `uid`, `url`, `network` FROM `contact` WHERE `id` = %d", intval($contact_id));
240         if (!$r)
241                 return;
242
243         $uid = $r[0]["uid"];
244
245         if ($uid != local_user())
246                 return;
247
248         if ($r[0]["network"] == NETWORK_OSTATUS) {
249                 $result = new_contact($uid, $r[0]["url"], false, $r[0]["network"]);
250
251                 if ($result['success'])
252                         $r = q("UPDATE `contact` SET `subhub` = 1 WHERE `id` = %d",
253                                 intval($contact_id));
254         } else
255                 // pull feed and consume it, which should subscribe to the hub.
256                 Worker::add(PRIORITY_HIGH, "OnePoll", $contact_id, "force");
257 }
258
259 function _contact_update_profile($contact_id) {
260         $r = q("SELECT `uid`, `url`, `network` FROM `contact` WHERE `id` = %d", intval($contact_id));
261         if (!$r)
262                 return;
263
264         $uid = $r[0]["uid"];
265
266         if ($uid != local_user())
267                 return;
268
269         $data = Probe::uri($r[0]["url"], "", 0, false);
270
271         // "Feed" or "Unknown" is mostly a sign of communication problems
272         if ((in_array($data["network"], array(NETWORK_FEED, NETWORK_PHANTOM))) && ($data["network"] != $r[0]["network"]))
273                 return;
274
275         $updatefields = array("name", "nick", "url", "addr", "batch", "notify", "poll", "request", "confirm",
276                                 "poco", "network", "alias");
277         $update = array();
278
279         if ($data["network"] == NETWORK_OSTATUS) {
280                 $result = new_contact($uid, $data["url"], false);
281
282                 if ($result['success'])
283                         $update["subhub"] = true;
284         }
285
286         foreach($updatefields AS $field)
287                 if (isset($data[$field]) && ($data[$field] != ""))
288                         $update[$field] = $data[$field];
289
290         $update["nurl"] = normalise_link($data["url"]);
291
292         $query = "";
293
294         if (isset($data["priority"]) && ($data["priority"] != 0))
295                 $query = "`priority` = ".intval($data["priority"]);
296
297         foreach($update AS $key => $value) {
298                 if ($query != "")
299                         $query .= ", ";
300
301                 $query .= "`".$key."` = '".dbesc($value)."'";
302         }
303
304         if ($query == "")
305                 return;
306
307         $r = q("UPDATE `contact` SET $query WHERE `id` = %d AND `uid` = %d",
308                 intval($contact_id),
309                 intval(local_user())
310         );
311
312         // Update the entry in the contact table
313         Contact::updateAvatar($data['photo'], local_user(), $contact_id, true);
314
315         // Update the entry in the gcontact table
316         GlobalContact::updateFromProbe($data["url"]);
317 }
318
319 function _contact_block($contact_id, $orig_record) {
320         $blocked = (($orig_record['blocked']) ? 0 : 1);
321         $r = q("UPDATE `contact` SET `blocked` = %d WHERE `id` = %d AND `uid` = %d",
322                 intval($blocked),
323                 intval($contact_id),
324                 intval(local_user())
325         );
326         return $r;
327
328 }
329 function _contact_ignore($contact_id, $orig_record) {
330         $readonly = (($orig_record['readonly']) ? 0 : 1);
331         $r = q("UPDATE `contact` SET `readonly` = %d WHERE `id` = %d AND `uid` = %d",
332                 intval($readonly),
333                 intval($contact_id),
334                 intval(local_user())
335         );
336         return $r;
337 }
338 function _contact_archive($contact_id, $orig_record) {
339         $archived = (($orig_record['archive']) ? 0 : 1);
340         $r = q("UPDATE `contact` SET `archive` = %d WHERE `id` = %d AND `uid` = %d",
341                 intval($archived),
342                 intval($contact_id),
343                 intval(local_user())
344         );
345         if ($archived) {
346                 q("UPDATE `item` SET `private` = 2 WHERE `contact-id` = %d AND `uid` = %d", intval($contact_id), intval(local_user()));
347         }
348         return $r;
349 }
350
351 function _contact_drop($orig_record)
352 {
353         $a = get_app();
354
355         $r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid`
356                 WHERE `user`.`uid` = %d AND `contact`.`self` LIMIT 1",
357                 intval($a->user['uid'])
358         );
359         if (!DBM::is_result($r)) {
360                 return;
361         }
362
363         Contact::terminateFriendship($r[0], $orig_record);
364         Contact::remove($orig_record['id']);
365 }
366
367
368 function contacts_content(App $a) {
369
370         $sort_type = 0;
371         $o = '';
372         nav_set_selected('contacts');
373
374
375         if (! local_user()) {
376                 notice( t('Permission denied.') . EOL);
377                 return;
378         }
379
380         if($a->argc == 3) {
381
382                 $contact_id = intval($a->argv[1]);
383                 if(! $contact_id)
384                         return;
385
386                 $cmd = $a->argv[2];
387
388                 $orig_record = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d AND `self` = 0 LIMIT 1",
389                         intval($contact_id),
390                         intval(local_user())
391                 );
392
393                 if(! count($orig_record)) {
394                         notice( t('Could not access contact record.') . EOL);
395                         goaway('contacts');
396                         return; // NOTREACHED
397                 }
398
399                 if($cmd === 'update') {
400                         _contact_update($contact_id);
401                         goaway('contacts/' . $contact_id);
402                         // NOTREACHED
403                 }
404
405                 if($cmd === 'updateprofile') {
406                         _contact_update_profile($contact_id);
407                         goaway('crepair/' . $contact_id);
408                         // NOTREACHED
409                 }
410
411                 if($cmd === 'block') {
412                         $r = _contact_block($contact_id, $orig_record[0]);
413                         if ($r) {
414                                 $blocked = (($orig_record[0]['blocked']) ? 0 : 1);
415                                 info((($blocked) ? t('Contact has been blocked') : t('Contact has been unblocked')).EOL);
416                         }
417
418                         goaway('contacts/' . $contact_id);
419                         return; // NOTREACHED
420                 }
421
422                 if($cmd === 'ignore') {
423                         $r = _contact_ignore($contact_id, $orig_record[0]);
424                         if ($r) {
425                                 $readonly = (($orig_record[0]['readonly']) ? 0 : 1);
426                                 info((($readonly) ? t('Contact has been ignored') : t('Contact has been unignored')).EOL);
427                         }
428
429                         goaway('contacts/' . $contact_id);
430                         return; // NOTREACHED
431                 }
432
433
434                 if($cmd === 'archive') {
435                         $r = _contact_archive($contact_id, $orig_record[0]);
436                         if ($r) {
437                                 $archived = (($orig_record[0]['archive']) ? 0 : 1);
438                                 info((($archived) ? t('Contact has been archived') : t('Contact has been unarchived')).EOL);
439                         }
440
441                         goaway('contacts/' . $contact_id);
442                         return; // NOTREACHED
443                 }
444
445                 if($cmd === 'drop') {
446
447                         // Check if we should do HTML-based delete confirmation
448                         if($_REQUEST['confirm']) {
449                                 // <form> can't take arguments in its "action" parameter
450                                 // so add any arguments as hidden inputs
451                                 $query = explode_querystring($a->query_string);
452                                 $inputs = array();
453                                 foreach($query['args'] as $arg) {
454                                         if(strpos($arg, 'confirm=') === false) {
455                                                 $arg_parts = explode('=', $arg);
456                                                 $inputs[] = array('name' => $arg_parts[0], 'value' => $arg_parts[1]);
457                                         }
458                                 }
459
460                                 $a->page['aside'] = '';
461
462                                 return replace_macros(get_markup_template('contact_drop_confirm.tpl'), array(
463                                         '$header' => t('Drop contact'),
464                                         '$contact' => _contact_detail_for_template($orig_record[0]),
465                                         '$method' => 'get',
466                                         '$message' => t('Do you really want to delete this contact?'),
467                                         '$extra_inputs' => $inputs,
468                                         '$confirm' => t('Yes'),
469                                         '$confirm_url' => $query['base'],
470                                         '$confirm_name' => 'confirmed',
471                                         '$cancel' => t('Cancel'),
472                                 ));
473                         }
474                         // Now check how the user responded to the confirmation query
475                         if ($_REQUEST['canceled']) {
476                                 if (x($_SESSION,'return_url')) {
477                                         goaway('' . $_SESSION['return_url']);
478                                 }
479                                 else {
480                                         goaway('contacts');
481                                 }
482                         }
483
484                         _contact_drop($orig_record[0]);
485                         info( t('Contact has been removed.') . EOL );
486                         if (x($_SESSION,'return_url')) {
487                                 goaway('' . $_SESSION['return_url']);
488                         }
489                         else {
490                                 goaway('contacts');
491                         }
492                         return; // NOTREACHED
493                 }
494                 if ($cmd === 'posts') {
495                         return contact_posts($a, $contact_id);
496                 }
497         }
498
499
500
501         $_SESSION['return_url'] = $a->query_string;
502
503         if((x($a->data,'contact')) && (is_array($a->data['contact']))) {
504
505                 $contact_id = $a->data['contact']['id'];
506                 $contact = $a->data['contact'];
507
508                 $a->page['htmlhead'] .= replace_macros(get_markup_template('contact_head.tpl'), array(
509                         '$baseurl' => System::baseUrl(true),
510                 ));
511                 $a->page['end'] .= replace_macros(get_markup_template('contact_end.tpl'), array(
512                         '$baseurl' => System::baseUrl(true),
513                 ));
514
515                 require_once 'include/contact_selectors.php';
516
517                 $tpl = get_markup_template("contact_edit.tpl");
518
519                 switch($contact['rel']) {
520                         case CONTACT_IS_FRIEND:
521                                 $dir_icon = 'images/lrarrow.gif';
522                                 $relation_text = t('You are mutual friends with %s');
523                                 break;
524                         case CONTACT_IS_FOLLOWER;
525                                 $dir_icon = 'images/larrow.gif';
526                                 $relation_text = t('You are sharing with %s');
527                                 break;
528
529                         case CONTACT_IS_SHARING;
530                                 $dir_icon = 'images/rarrow.gif';
531                                 $relation_text = t('%s is sharing with you');
532                                 break;
533                         default:
534                                 break;
535                 }
536
537                 if(!in_array($contact['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA)))
538                                 $relation_text = "";
539
540                 $relation_text = sprintf($relation_text,htmlentities($contact['name']));
541
542                 if(($contact['network'] === NETWORK_DFRN) && ($contact['rel'])) {
543                         $url = "redir/{$contact['id']}";
544                         $sparkle = ' class="sparkle" ';
545                 }
546                 else {
547                         $url = $contact['url'];
548                         $sparkle = '';
549                 }
550
551                 $insecure = t('Private communications are not available for this contact.');
552
553                 $last_update = (($contact['last-update'] <= NULL_DATE)
554                                 ? t('Never')
555                                 : datetime_convert('UTC',date_default_timezone_get(),$contact['last-update'],'D, j M Y, g:i A'));
556
557                 if ($contact['last-update'] > NULL_DATE) {
558                         $last_update .= ' ' . (($contact['last-update'] <= $contact['success_update']) ? t("\x28Update was successful\x29") : t("\x28Update was not successful\x29"));
559                 }
560                 $lblsuggest = (($contact['network'] === NETWORK_DFRN) ? t('Suggest friends') : '');
561
562                 $poll_enabled = in_array($contact['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_FEED, NETWORK_MAIL, NETWORK_MAIL2));
563
564                 $nettype = sprintf( t('Network type: %s'),network_to_name($contact['network'], $contact["url"]));
565
566                 //$common = GlobalContact::countCommonFriends(local_user(),$contact['id']);
567                 //$common_text = (($common) ? sprintf( tt('%d contact in common','%d contacts in common', $common),$common) : '');
568
569                 $polling = (($contact['network'] === NETWORK_MAIL | $contact['network'] === NETWORK_FEED) ? 'polling' : '');
570
571                 //$x = GlobalContact::countAllFriends(local_user(), $contact['id']);
572                 //$all_friends = (($x) ? t('View all contacts') : '');
573
574                 // tabs
575                 $tab_str = contacts_tab($a, $contact_id, 2);
576
577                 $lost_contact = (($contact['archive'] && $contact['term-date'] > NULL_DATE && $contact['term-date'] < datetime_convert('','','now')) ? t('Communications lost with this contact!') : '');
578
579                 if ($contact['network'] == NETWORK_FEED) {
580                         $fetch_further_information = array('fetch_further_information',
581                                                         t('Fetch further information for feeds'),
582                                                         $contact['fetch_further_information'],
583                                                         t("Fetch information like preview pictures, title and teaser from the feed item. You can activate this if the feed doesn't contain much text. Keywords are taken from the meta header in the feed item and are posted as hash tags."),
584                                                                 array('0' => t('Disabled'),
585                                                                         '1' => t('Fetch information'),
586                                                                         '3' => t('Fetch keywords'),
587                                                                         '2' => t('Fetch information and keywords')));
588                 }
589                 if (in_array($contact['network'], array(NETWORK_FEED, NETWORK_MAIL, NETWORK_MAIL2)))
590                         $poll_interval = contact_poll_interval($contact['priority'],(! $poll_enabled));
591
592                 if ($contact['network'] == NETWORK_DFRN)
593                         $profile_select = contact_profile_assign($contact['profile-id'],(($contact['network'] !== NETWORK_DFRN) ? true : false));
594
595                 if (in_array($contact['network'], array(NETWORK_DIASPORA, NETWORK_OSTATUS))) {
596                         if ($contact['rel'] == CONTACT_IS_FOLLOWER) {
597                                 $follow = System::baseUrl(true)."/follow?url=".urlencode($contact["url"]);
598                                 $follow_text = t("Connect/Follow");
599                         } elseif ($contact['rel'] == CONTACT_IS_FRIEND) {
600                                 $follow = System::baseUrl(true)."/unfollow?url=".urlencode($contact["url"]);
601                                 $follow_text = t("Disconnect/Unfollow");
602                         }
603                 }
604
605                 // Load contactact related actions like hide, suggest, delete and others
606                 $contact_actions = contact_actions($contact);
607
608
609                 $o .= replace_macros($tpl, array(
610                         //'$header' => t('Contact Editor'),
611                         '$header' => t("Contact"),
612                         '$tab_str' => $tab_str,
613                         '$submit' => t('Submit'),
614                         '$lbl_vis1' => t('Profile Visibility'),
615                         '$lbl_vis2' => sprintf( t('Please choose the profile you would like to display to %s when viewing your profile securely.'), $contact['name']),
616                         '$lbl_info1' => t('Contact Information / Notes'),
617                         '$lbl_info2' => t('Their personal note'),
618                         '$reason' => trim(notags($contact['reason'])),
619                         '$infedit' => t('Edit contact notes'),
620                         '$common_text' => $common_text,
621                         '$common_link' => 'common/loc/' . local_user() . '/' . $contact['id'],
622                         '$all_friends' => $all_friends,
623                         '$relation_text' => $relation_text,
624                         '$visit' => sprintf( t('Visit %s\'s profile [%s]'),$contact['name'],$contact['url']),
625                         '$blockunblock' => t('Block/Unblock contact'),
626                         '$ignorecont' => t('Ignore contact'),
627                         '$lblcrepair' => t("Repair URL settings"),
628                         '$lblrecent' => t('View conversations'),
629                         '$lblsuggest' => $lblsuggest,
630                         //'$delete' => t('Delete contact'),
631                         '$nettype' => $nettype,
632                         '$poll_interval' => $poll_interval,
633                         '$poll_enabled' => $poll_enabled,
634                         '$lastupdtext' => t('Last update:'),
635                         '$lost_contact' => $lost_contact,
636                         '$updpub' => t('Update public posts'),
637                         '$last_update' => $last_update,
638                         '$udnow' => t('Update now'),
639                         '$follow' => $follow,
640                         '$follow_text' => $follow_text,
641                         '$profile_select' => $profile_select,
642                         '$contact_id' => $contact['id'],
643                         '$block_text' => (($contact['blocked']) ? t('Unblock') : t('Block') ),
644                         '$ignore_text' => (($contact['readonly']) ? t('Unignore') : t('Ignore') ),
645                         '$insecure' => (($contact['network'] !== NETWORK_DFRN && $contact['network'] !== NETWORK_MAIL && $contact['network'] !== NETWORK_FACEBOOK && $contact['network'] !== NETWORK_DIASPORA) ? $insecure : ''),
646                         '$info' => $contact['info'],
647                         '$cinfo' => array('info', '', $contact['info'], ''),
648                         '$blocked' => (($contact['blocked']) ? t('Currently blocked') : ''),
649                         '$ignored' => (($contact['readonly']) ? t('Currently ignored') : ''),
650                         '$archived' => (($contact['archive']) ? t('Currently archived') : ''),
651                         '$pending' => (($contact['pending']) ? t('Awaiting connection acknowledge') : ''),
652                         '$hidden' => array('hidden', t('Hide this contact from others'), ($contact['hidden'] == 1), t('Replies/likes to your public posts <strong>may</strong> still be visible')),
653                         '$notify' => array('notify', t('Notification for new posts'), ($contact['notify_new_posts'] == 1), t('Send a notification of every new post of this contact')),
654                         '$fetch_further_information' => $fetch_further_information,
655                         '$ffi_keyword_blacklist' => $contact['ffi_keyword_blacklist'],
656                         '$ffi_keyword_blacklist' => array('ffi_keyword_blacklist', t('Blacklisted keywords'), $contact['ffi_keyword_blacklist'], t('Comma separated list of keywords that should not be converted to hashtags, when "Fetch information and keywords" is selected')),
657                         '$photo' => $contact['photo'],
658                         '$name' => htmlentities($contact['name']),
659                         '$dir_icon' => $dir_icon,
660                         '$alt_text' => $alt_text,
661                         '$sparkle' => $sparkle,
662                         '$url' => $url,
663                         '$profileurllabel' => t('Profile URL'),
664                         '$profileurl' => $contact['url'],
665                         '$account_type' => Contact::getAccountType($contact),
666                         '$location' => bbcode($contact["location"]),
667                         '$location_label' => t("Location:"),
668                         '$xmpp' => bbcode($contact["xmpp"]),
669                         '$xmpp_label' => t("XMPP:"),
670                         '$about' => bbcode($contact["about"], false, false),
671                         '$about_label' => t("About:"),
672                         '$keywords' => $contact["keywords"],
673                         '$keywords_label' => t("Tags:"),
674                         '$contact_action_button' => t("Actions"),
675                         '$contact_actions' => $contact_actions,
676                         '$contact_status' => t("Status"),
677                         '$contact_settings_label' => t('Contact Settings'),
678                         '$contact_profile_label' => t("Profile"),
679
680                 ));
681
682                 $arr = array('contact' => $contact,'output' => $o);
683
684                 call_hooks('contact_edit', $arr);
685
686                 return $arr['output'];
687
688         }
689
690         $blocked = false;
691         $hidden = false;
692         $ignored = false;
693         $all = false;
694
695         if(($a->argc == 2) && ($a->argv[1] === 'all')) {
696                 $sql_extra = '';
697                 $all = true;
698         }
699         elseif(($a->argc == 2) && ($a->argv[1] === 'blocked')) {
700                 $sql_extra = " AND `blocked` = 1 ";
701                 $blocked = true;
702         }
703         elseif(($a->argc == 2) && ($a->argv[1] === 'hidden')) {
704                 $sql_extra = " AND `hidden` = 1 ";
705                 $hidden = true;
706         }
707         elseif(($a->argc == 2) && ($a->argv[1] === 'ignored')) {
708                 $sql_extra = " AND `readonly` = 1 ";
709                 $ignored = true;
710         }
711         elseif(($a->argc == 2) && ($a->argv[1] === 'archived')) {
712                 $sql_extra = " AND `archive` = 1 ";
713                 $archived = true;
714         }
715         else
716                 $sql_extra = " AND `blocked` = 0 ";
717
718         $search = ((x($_GET,'search')) ? notags(trim($_GET['search'])) : '');
719         $nets = ((x($_GET,'nets')) ? notags(trim($_GET['nets'])) : '');
720
721         $tabs = array(
722                 array(
723                         'label' => t('Suggestions'),
724                         'url'   => 'suggest',
725                         'sel'   => '',
726                         'title' => t('Suggest potential friends'),
727                         'id'    => 'suggestions-tab',
728                         'accesskey' => 'g',
729                 ),
730                 array(
731                         'label' => t('All Contacts'),
732                         'url'   => 'contacts/all',
733                         'sel'   => ($all) ? 'active' : '',
734                         'title' => t('Show all contacts'),
735                         'id'    => 'showall-tab',
736                         'accesskey' => 'l',
737                 ),
738                 array(
739                         'label' => t('Unblocked'),
740                         'url'   => 'contacts',
741                         'sel'   => ((! $all) && (! $blocked) && (! $hidden) && (! $search) && (! $nets) && (! $ignored) && (! $archived)) ? 'active' : '',
742                         'title' => t('Only show unblocked contacts'),
743                         'id'    => 'showunblocked-tab',
744                         'accesskey' => 'o',
745                 ),
746
747                 array(
748                         'label' => t('Blocked'),
749                         'url'   => 'contacts/blocked',
750                         'sel'   => ($blocked) ? 'active' : '',
751                         'title' => t('Only show blocked contacts'),
752                         'id'    => 'showblocked-tab',
753                         'accesskey' => 'b',
754                 ),
755
756                 array(
757                         'label' => t('Ignored'),
758                         'url'   => 'contacts/ignored',
759                         'sel'   => ($ignored) ? 'active' : '',
760                         'title' => t('Only show ignored contacts'),
761                         'id'    => 'showignored-tab',
762                         'accesskey' => 'i',
763                 ),
764
765                 array(
766                         'label' => t('Archived'),
767                         'url'   => 'contacts/archived',
768                         'sel'   => ($archived) ? 'active' : '',
769                         'title' => t('Only show archived contacts'),
770                         'id'    => 'showarchived-tab',
771                         'accesskey' => 'y',
772                 ),
773
774                 array(
775                         'label' => t('Hidden'),
776                         'url'   => 'contacts/hidden',
777                         'sel'   => ($hidden) ? 'active' : '',
778                         'title' => t('Only show hidden contacts'),
779                         'id'    => 'showhidden-tab',
780                         'accesskey' => 'h',
781                 ),
782
783         );
784
785         $tab_tpl = get_markup_template('common_tabs.tpl');
786         $t = replace_macros($tab_tpl, array('$tabs'=>$tabs));
787
788
789
790         $searching = false;
791         if($search) {
792                 $search_hdr = $search;
793                 $search_txt = dbesc(protect_sprintf(preg_quote($search)));
794                 $searching = true;
795         }
796         $sql_extra .= (($searching) ? " AND (name REGEXP '$search_txt' OR url REGEXP '$search_txt'  OR nick REGEXP '$search_txt') " : "");
797
798         if($nets)
799                 $sql_extra .= sprintf(" AND network = '%s' ", dbesc($nets));
800
801         $sql_extra2 = ((($sort_type > 0) && ($sort_type <= CONTACT_IS_FRIEND)) ? sprintf(" AND `rel` = %d ",intval($sort_type)) : '');
802
803
804         $r = q("SELECT COUNT(*) AS `total` FROM `contact`
805                 WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 ",
806                 intval($_SESSION['uid']));
807         if (DBM::is_result($r)) {
808                 $a->set_pager_total($r[0]['total']);
809                 $total = $r[0]['total'];
810         }
811
812         $sql_extra3 = unavailable_networks();
813
814         $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 $sql_extra3 ORDER BY `name` ASC LIMIT %d , %d ",
815                 intval($_SESSION['uid']),
816                 intval($a->pager['start']),
817                 intval($a->pager['itemspage'])
818         );
819
820         $contacts = array();
821
822         if (DBM::is_result($r)) {
823                 foreach ($r as $rr) {
824                         $contacts[] = _contact_detail_for_template($rr);
825                 }
826         }
827
828         $tpl = get_markup_template("contacts-template.tpl");
829         $o .= replace_macros($tpl, array(
830                 '$baseurl' => System::baseUrl(),
831                 '$header' => t('Contacts') . (($nets) ? ' - ' . network_to_name($nets) : ''),
832                 '$tabs' => $t,
833                 '$total' => $total,
834                 '$search' => $search_hdr,
835                 '$desc' => t('Search your contacts'),
836                 '$finding' => (($searching) ? sprintf(t('Results for: %s'),$search) : ""),
837                 '$submit' => t('Find'),
838                 '$cmd' => $a->cmd,
839                 '$contacts' => $contacts,
840                 '$contact_drop_confirm' => t('Do you really want to delete this contact?'),
841                 'multiselect' => 1,
842                 '$batch_actions' => array(
843                         'contacts_batch_update' => t('Update'),
844                         'contacts_batch_block' => t('Block')."/".t("Unblock"),
845                         "contacts_batch_ignore" => t('Ignore')."/".t("Unignore"),
846                         "contacts_batch_archive" => t('Archive')."/".t("Unarchive"),
847                         "contacts_batch_drop" => t('Delete'),
848                 ),
849                 '$h_batch_actions' => t('Batch Actions'),
850                 '$paginate' => paginate($a),
851
852         ));
853
854         return $o;
855 }
856
857 /**
858  * @brief List of pages for the Contact TabBar
859  *
860  * Available Pages are 'Status', 'Profile', 'Contacts' and 'Common Friends'
861  *
862  * @param App $a
863  * @param int $contact_id The ID of the contact
864  * @param int $active_tab 1 if tab should be marked as active
865  *
866  * @return array with with contact TabBar data
867  */
868 function contacts_tab($a, $contact_id, $active_tab) {
869         // tabs
870         $tabs = array(
871                 array(
872                         'label'=>t('Status'),
873                         'url' => "contacts/".$contact_id."/posts",
874                         'sel' => (($active_tab == 1)?'active':''),
875                         'title' => t('Status Messages and Posts'),
876                         'id' => 'status-tab',
877                         'accesskey' => 'm',
878                 ),
879                 array(
880                         'label'=>t('Profile'),
881                         'url' => "contacts/".$contact_id,
882                         'sel' => (($active_tab == 2)?'active':''),
883                         'title' => t('Profile Details'),
884                         'id' => 'profile-tab',
885                         'accesskey' => 'o',
886                 )
887         );
888
889         // Show this tab only if there is visible friend list
890         $x = GlobalContact::countAllFriends(local_user(), $contact_id);
891         if ($x)
892                 $tabs[] = array('label'=>t('Contacts'),
893                                 'url' => "allfriends/".$contact_id,
894                                 'sel' => (($active_tab == 3)?'active':''),
895                                 'title' => t('View all contacts'),
896                                 'id' => 'allfriends-tab',
897                                 'accesskey' => 't');
898
899         // Show this tab only if there is visible common friend list
900         $common = GlobalContact::countCommonFriends(local_user(), $contact_id);
901         if ($common)
902                 $tabs[] = array('label'=>t('Common Friends'),
903                                 'url' => "common/loc/".local_user()."/".$contact_id,
904                                 'sel' => (($active_tab == 4)?'active':''),
905                                 'title' => t('View all common friends'),
906                                 'id' => 'common-loc-tab',
907                                 'accesskey' => 'd');
908
909         $tabs[] = array('label' => t('Advanced'),
910                         'url'   => 'crepair/' . $contact_id,
911                         'sel' => (($active_tab == 5)?'active':''),
912                         'title' => t('Advanced Contact Settings'),
913                         'id'    => 'advanced-tab',
914                         'accesskey' => 'r');
915
916         $tab_tpl = get_markup_template('common_tabs.tpl');
917         $tab_str = replace_macros($tab_tpl, array('$tabs' => $tabs));
918
919         return $tab_str;
920 }
921
922 function contact_posts($a, $contact_id) {
923
924         $r = q("SELECT `url` FROM `contact` WHERE `id` = %d", intval($contact_id));
925         if ($r) {
926                 $contact = $r[0];
927                 $a->page['aside'] = "";
928                 profile_load($a, "", 0, Contact::getDetailsByURL($contact["url"]));
929         } else
930                 $profile = "";
931
932         $tab_str = contacts_tab($a, $contact_id, 1);
933
934         $o .= $tab_str;
935
936         $o .= Contact::getPostsFromUrl($contact["url"]);
937
938         return $o;
939 }
940
941 function _contact_detail_for_template($rr){
942
943         switch($rr['rel']) {
944                 case CONTACT_IS_FRIEND:
945                         $dir_icon = 'images/lrarrow.gif';
946                         $alt_text = t('Mutual Friendship');
947                         break;
948                 case  CONTACT_IS_FOLLOWER;
949                         $dir_icon = 'images/larrow.gif';
950                         $alt_text = t('is a fan of yours');
951                         break;
952                 case CONTACT_IS_SHARING;
953                         $dir_icon = 'images/rarrow.gif';
954                         $alt_text = t('you are a fan of');
955                         break;
956                 default:
957                         break;
958         }
959         if(($rr['network'] === NETWORK_DFRN) && ($rr['rel'])) {
960                 $url = "redir/{$rr['id']}";
961                 $sparkle = ' class="sparkle" ';
962         }
963         else {
964                 $url = $rr['url'];
965                 $sparkle = '';
966         }
967
968         return array(
969                 'img_hover' => sprintf( t('Visit %s\'s profile [%s]'),$rr['name'],$rr['url']),
970                 'edit_hover' => t('Edit contact'),
971                 'photo_menu' => Contact::photoMenu($rr),
972                 'id' => $rr['id'],
973                 'alt_text' => $alt_text,
974                 'dir_icon' => $dir_icon,
975                 'thumb' => proxy_url($rr['thumb'], false, PROXY_SIZE_THUMB),
976                 'name' => htmlentities($rr['name']),
977                 'username' => htmlentities($rr['name']),
978                 'account_type' => Contact::getAccountType($rr),
979                 'sparkle' => $sparkle,
980                 'itemurl' => (($rr['addr'] != "") ? $rr['addr'] : $rr['url']),
981                 'url' => $url,
982                 'network' => network_to_name($rr['network'], $rr['url']),
983         );
984
985 }
986
987 /**
988  * @brief Gives a array with actions which can performed to a given contact
989  *
990  * This includes actions like e.g. 'block', 'hide', 'archive', 'delete' and others
991  *
992  * @param array $contact Data about the Contact
993  * @return array with contact related actions
994  */
995 function contact_actions($contact) {
996
997         $poll_enabled = in_array($contact['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_FEED, NETWORK_MAIL, NETWORK_MAIL2));
998         $contact_action = array();
999
1000         // Provide friend suggestion only for Friendica contacts
1001         if($contact['network'] === NETWORK_DFRN) {
1002                 $contact_actions['suggest'] = array(
1003                                                         'label' => t('Suggest friends'),
1004                                                         'url'   => 'fsuggest/' . $contact['id'],
1005                                                         'title' => '',
1006                                                         'sel'   => '',
1007                                                         'id'    =>  'suggest',
1008                                         );
1009         }
1010
1011         if($poll_enabled) {
1012                 $contact_actions['update'] = array(
1013                                                         'label' => t('Update now'),
1014                                                         'url'   => 'contacts/' . $contact['id'] . '/update',
1015                                                         'title' => '',
1016                                                         'sel'   => '',
1017                                                         'id'    => 'update',
1018                                         );
1019         }
1020
1021         $contact_actions['block'] = array(
1022                                                 'label' => (intval($contact['blocked']) ? t('Unblock') : t('Block') ),
1023                                                 'url'   => 'contacts/' . $contact['id'] . '/block',
1024                                                 'title' => t('Toggle Blocked status'),
1025                                                 'sel'   => (intval($contact['blocked']) ? 'active' : ''),
1026                                                 'id'    => 'toggle-block',
1027                                 );
1028
1029         $contact_actions['ignore'] = array(
1030                                                 'label' => (intval($contact['readonly']) ? t('Unignore') : t('Ignore') ),
1031                                                 'url'   => 'contacts/' . $contact['id'] . '/ignore',
1032                                                 'title' => t('Toggle Ignored status'),
1033                                                 'sel'   => (intval($contact['readonly']) ? 'active' : ''),
1034                                                 'id'    => 'toggle-ignore',
1035                                 );
1036
1037         $contact_actions['archive'] = array(
1038                                                 'label' => (intval($contact['archive']) ? t('Unarchive') : t('Archive') ),
1039                                                 'url'   => 'contacts/' . $contact['id'] . '/archive',
1040                                                 'title' => t('Toggle Archive status'),
1041                                                 'sel'   => (intval($contact['archive']) ? 'active' : ''),
1042                                                 'id'    => 'toggle-archive',
1043                                 );
1044
1045         $contact_actions['delete'] = array(
1046                                                 'label' => t('Delete'),
1047                                                 'url'   => 'contacts/' . $contact['id'] . '/drop',
1048                                                 'title' => t('Delete contact'),
1049                                                 'sel'   => '',
1050                                                 'id'    => 'delete',
1051                                 );
1052
1053         return $contact_actions;
1054 }