]> git.mxchange.org Git - friendica.git/blob - mod/display.php
Merge remote-tracking branch 'upstream/develop' into 1706-worker-even-faster
[friendica.git] / mod / display.php
1 <?php
2
3 use Friendica\App;
4
5 require_once('include/dfrn.php');
6
7 function display_init(App $a) {
8
9         if ((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
10                 return;
11         }
12
13         $nick = (($a->argc > 1) ? $a->argv[1] : '');
14         $profiledata = array();
15
16         if ($a->argc == 3) {
17                 if (substr($a->argv[2], -5) == '.atom') {
18                         $item_id = substr($a->argv[2], 0, -5);
19                         $xml = dfrn::itemFeed($item_id);
20                         header("Content-type: application/atom+xml");
21                         echo $xml;
22                         http_status_exit(($xml) ? 200 : 500);
23                 }
24         }
25
26         // If there is only one parameter, then check if this parameter could be a guid
27         if ($a->argc == 2) {
28                 $nick = "";
29                 $itemuid = 0;
30
31                 // Does the local user have this item?
32                 if (local_user()) {
33                         $r = qu("SELECT `id`, `parent`, `author-name`, `author-link`, `author-avatar`, `network`, `body`, `uid`, `owner-link` FROM `item`
34                                 WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
35                                         AND `guid` = '%s' AND `uid` = %d", dbesc($a->argv[1]), local_user());
36                         if (dbm::is_result($r)) {
37                                 $nick = $a->user["nickname"];
38                                 $itemuid = local_user();
39                         }
40                 }
41
42                 // Or is it anywhere on the server?
43                 if ($nick == "") {
44                         $r = qu("SELECT `user`.`nickname`, `item`.`id`, `item`.`parent`, `item`.`author-name`,
45                                 `item`.`author-link`, `item`.`author-avatar`, `item`.`network`, `item`.`uid`, `item`.`owner-link`, `item`.`body`
46                                 FROM `item` STRAIGHT_JOIN `user` ON `user`.`uid` = `item`.`uid`
47                                 WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
48                                         AND `item`.`allow_cid` = ''  AND `item`.`allow_gid` = ''
49                                         AND `item`.`deny_cid`  = '' AND `item`.`deny_gid`  = ''
50                                         AND NOT `item`.`private` AND NOT `user`.`hidewall`
51                                         AND `item`.`guid` = '%s'", dbesc($a->argv[1]));
52                         if (dbm::is_result($r)) {
53                                 $nick = $r[0]["nickname"];
54                                 $itemuid = $r[0]["uid"];
55                         }
56                 }
57
58                 // Is it an item with uid=0?
59                 if ($nick == "") {
60                         $r = qu("SELECT `item`.`id`, `item`.`parent`, `item`.`author-name`, `item`.`author-link`,
61                                 `item`.`author-avatar`, `item`.`network`, `item`.`uid`, `item`.`owner-link`, `item`.`body`
62                                 FROM `item` WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
63                                         AND `item`.`allow_cid` = ''  AND `item`.`allow_gid` = ''
64                                         AND `item`.`deny_cid`  = '' AND `item`.`deny_gid`  = ''
65                                         AND NOT `item`.`private` AND `item`.`uid` = 0
66                                         AND `item`.`guid` = '%s'", dbesc($a->argv[1]));
67                 }
68                 if (dbm::is_result($r)) {
69                         if ($r[0]["id"] != $r[0]["parent"]) {
70                                 $r = qu("SELECT `id`, `author-name`, `author-link`, `author-avatar`, `network`, `body`, `uid`, `owner-link` FROM `item`
71                                         WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
72                                                 AND `id` = %d", $r[0]["parent"]);
73                         }
74                         if (($itemuid != local_user()) && local_user()) {
75                                 // Do we know this contact but we haven't got this item?
76                                 // Copy the wohle thread to our local storage so that we can interact.
77                                 // We really should change this need for the future since it scales very bad.
78                                 $contactid = get_contact($r[0]['owner-link'], local_user());
79                                 if ($contactid) {
80                                         $items = qu("SELECT * FROM `item` WHERE `parent` = %d ORDER BY `id`", intval($r[0]["id"]));
81                                         foreach ($items AS $item) {
82                                                 $itemcontactid = get_contact($item['owner-link'], local_user());
83                                                 if (!$itemcontactid) {
84                                                         $itemcontactid = $contactid;
85                                                 }
86                                                 unset($item['id']);
87                                                 $item['uid'] = local_user();
88                                                 $item['origin'] = 0;
89                                                 $item['contact-id'] = $itemcontactid;
90                                                 $local_copy = item_store($item, false, false, true);
91                                                 logger("Stored local copy for post ".$item['guid']." under id ".$local_copy, LOGGER_DEBUG);
92                                         }
93                                 }
94                         }
95
96                         $profiledata = display_fetchauthor($a, $r[0]);
97
98                         if (strstr(normalise_link($profiledata["url"]), normalise_link(App::get_baseurl()))) {
99                                 $nickname = str_replace(normalise_link(App::get_baseurl())."/profile/", "", normalise_link($profiledata["url"]));
100
101                                 if (($nickname != $a->user["nickname"])) {
102                                         $r = qu("SELECT `profile`.`uid` AS `profile_uid`, `profile`.* , `contact`.`avatar-date` AS picdate, `user`.* FROM `profile`
103                                                 INNER JOIN `contact` on `contact`.`uid` = `profile`.`uid` INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
104                                                 WHERE `user`.`nickname` = '%s' AND `profile`.`is-default` AND `contact`.`self` LIMIT 1",
105                                                 dbesc($nickname)
106                                         );
107                                         if (dbm::is_result($r)) {
108                                                 $profiledata = $r[0];
109                                         }
110                                         $profiledata["network"] = NETWORK_DFRN;
111                                 } else {
112                                         $profiledata = array();
113                                 }
114                         }
115                 } else {
116                         $a->error = 404;
117                         notice(t('Item not found.') . EOL);
118                         return;
119                 }
120         }
121
122         profile_load($a, $nick, 0, $profiledata);
123 }
124
125 function display_fetchauthor($a, $item) {
126
127         require_once("include/Contact.php");
128
129         $profiledata = array();
130         $profiledata["uid"] = -1;
131         $profiledata["nickname"] = $item["author-name"];
132         $profiledata["name"] = $item["author-name"];
133         $profiledata["picdate"] = "";
134         $profiledata["photo"] = $item["author-avatar"];
135         $profiledata["url"] = $item["author-link"];
136         $profiledata["network"] = $item["network"];
137
138         // Check for a repeated message
139         $skip = false;
140         $body = trim($item["body"]);
141
142         // Skip if it isn't a pure repeated messages
143         // Does it start with a share?
144         if (!$skip && strpos($body, "[share") > 0) {
145                 $skip = true;
146         }
147         // Does it end with a share?
148         if (!$skip && (strlen($body) > (strrpos($body, "[/share]") + 8))) {
149                 $skip = true;
150         }
151         if (!$skip) {
152                 $attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body);
153                 // Skip if there is no shared message in there
154                 if ($body == $attributes) {
155                         $skip = true;
156                 }
157         }
158
159         if (!$skip) {
160                 $author = "";
161                 preg_match("/author='(.*?)'/ism", $attributes, $matches);
162                 if ($matches[1] != "") {
163                         $profiledata["name"] = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8');
164                 }
165                 preg_match('/author="(.*?)"/ism', $attributes, $matches);
166                 if ($matches[1] != "") {
167                         $profiledata["name"] = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8');
168                 }
169                 $profile = "";
170                 preg_match("/profile='(.*?)'/ism", $attributes, $matches);
171                 if ($matches[1] != "") {
172                         $profiledata["url"] = $matches[1];
173                 }
174                 preg_match('/profile="(.*?)"/ism', $attributes, $matches);
175                 if ($matches[1] != "") {
176                         $profiledata["url"] = $matches[1];
177                 }
178                 $avatar = "";
179                 preg_match("/avatar='(.*?)'/ism", $attributes, $matches);
180                 if ($matches[1] != "") {
181                         $profiledata["photo"] = $matches[1];
182                 }
183                 preg_match('/avatar="(.*?)"/ism', $attributes, $matches);
184                 if ($matches[1] != "") {
185                         $profiledata["photo"] = $matches[1];
186                 }
187                 $profiledata["nickname"] = $profiledata["name"];
188                 $profiledata["network"] = GetProfileUsername($profiledata["url"], "", false, true);
189
190                 $profiledata["address"] = "";
191                 $profiledata["about"] = "";
192         }
193
194         $profiledata = get_contact_details_by_url($profiledata["url"], local_user(), $profiledata);
195
196         $profiledata["photo"] = App::remove_baseurl($profiledata["photo"]);
197
198         if (local_user()) {
199                 if (in_array($profiledata["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS))) {
200                         $profiledata["remoteconnect"] = App::get_baseurl()."/follow?url=".urlencode($profiledata["url"]);
201                 }
202         } elseif ($profiledata["network"] == NETWORK_DFRN) {
203                 $connect = str_replace("/profile/", "/dfrn_request/", $profiledata["url"]);
204                 $profiledata["remoteconnect"] = $connect;
205         }
206
207         return($profiledata);
208 }
209
210 function display_content(App $a, $update = 0) {
211
212         if ((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
213                 notice(t('Public access denied.') . EOL);
214                 return;
215         }
216
217         require_once('include/security.php');
218         require_once('include/conversation.php');
219         require_once('include/acl_selectors.php');
220
221
222         $o = '';
223
224         if ($update) {
225                 $nick = $_REQUEST['nick'];
226         } else {
227                 $nick = (($a->argc > 1) ? $a->argv[1] : '');
228         }
229
230         if ($update) {
231                 $item_id = $_REQUEST['item_id'];
232                 $a->profile = array('uid' => intval($update), 'profile_uid' => intval($update));
233         } else {
234                 $item_id = (($a->argc > 2) ? $a->argv[2] : 0);
235
236                 if ($a->argc == 2) {
237                         $nick = "";
238
239                         if (local_user()) {
240                                 $r = qu("SELECT `id` FROM `item`
241                                         WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
242                                                 AND `guid` = '%s' AND `uid` = %d", dbesc($a->argv[1]), local_user());
243                                 if (dbm::is_result($r)) {
244                                         $item_id = $r[0]["id"];
245                                         $nick = $a->user["nickname"];
246                                 }
247                         }
248
249                         if ($nick == "") {
250                                 $r = qu("SELECT `user`.`nickname`, `item`.`id` FROM `item` STRAIGHT_JOIN `user` ON `user`.`uid` = `item`.`uid`
251                                         WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
252                                                 AND `item`.`allow_cid` = ''  AND `item`.`allow_gid` = ''
253                                                 AND `item`.`deny_cid`  = '' AND `item`.`deny_gid`  = ''
254                                                 AND NOT `item`.`private` AND NOT `user`.`hidewall`
255                                                 AND `item`.`guid` = '%s'", dbesc($a->argv[1]));
256                                         //      AND NOT `item`.`private` AND `item`.`wall`
257                                 if (dbm::is_result($r)) {
258                                         $item_id = $r[0]["id"];
259                                         $nick = $r[0]["nickname"];
260                                 }
261                         }
262                         if ($nick == "") {
263                                 $r = qu("SELECT `item`.`id` FROM `item`
264                                         WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
265                                                 AND `item`.`allow_cid` = ''  AND `item`.`allow_gid` = ''
266                                                 AND `item`.`deny_cid`  = '' AND `item`.`deny_gid`  = ''
267                                                 AND NOT `item`.`private` AND `item`.`uid` = 0
268                                                 AND `item`.`guid` = '%s'", dbesc($a->argv[1]));
269                                         //      AND NOT `item`.`private` AND `item`.`wall`
270                                 if (dbm::is_result($r)) {
271                                         $item_id = $r[0]["id"];
272                                 }
273                         }
274                 }
275         }
276
277         if ($item_id && !is_numeric($item_id)) {
278                 $r = qu("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
279                         dbesc($item_id), intval($a->profile['uid']));
280                 if (dbm::is_result($r)) {
281                         $item_id = $r[0]["id"];
282                 } else {
283                         $item_id = false;
284                 }
285         }
286
287         if (!$item_id) {
288                 $a->error = 404;
289                 notice(t('Item not found.').EOL);
290                 return;
291         }
292
293         // We are displaying an "alternate" link if that post was public. See issue 2864
294         $items = q("SELECT `id` FROM `item` WHERE `id` = %d AND NOT `private` AND `wall`", intval($item_id));
295         if (dbm::is_result($items)) {
296                 $alternate = App::get_baseurl().'/display/'.$nick.'/'.$item_id.'.atom';
297         } else {
298                 $alternate = '';
299         }
300
301         $a->page['htmlhead'] .= replace_macros(get_markup_template('display-head.tpl'),
302                                 array('$alternate' => $alternate));
303
304         $groups = array();
305
306         $contact = null;
307         $remote_contact = false;
308
309         $contact_id = 0;
310
311         if (is_array($_SESSION['remote'])) {
312                 foreach ($_SESSION['remote'] as $v) {
313                         if ($v['uid'] == $a->profile['uid']) {
314                                 $contact_id = $v['cid'];
315                                 break;
316                         }
317                 }
318         }
319
320         if ($contact_id) {
321                 $groups = init_groups_visitor($contact_id);
322                 $r = qu("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
323                         intval($contact_id),
324                         intval($a->profile['uid'])
325                 );
326                 if (dbm::is_result($r)) {
327                         $contact = $r[0];
328                         $remote_contact = true;
329                 }
330         }
331
332         if (!$remote_contact) {
333                 if (local_user()) {
334                         $contact_id = $_SESSION['cid'];
335                         $contact = $a->contact;
336                 }
337         }
338
339         $r = qu("SELECT * FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1",
340                 intval($a->profile['uid'])
341         );
342         if (dbm::is_result($r)) {
343                 $a->page_contact = $r[0];
344         }
345         $is_owner = ((local_user()) && (local_user() == $a->profile['profile_uid']) ? true : false);
346
347         if ($a->profile['hidewall'] && (! $is_owner) && (! $remote_contact)) {
348                 notice(t('Access to this profile has been restricted.') . EOL);
349                 return;
350         }
351
352         // We need the editor here to be able to reshare an item.
353
354         if ($is_owner) {
355                 $x = array(
356                         'is_owner' => true,
357                         'allow_location' => $a->user['allow_location'],
358                         'default_location' => $a->user['default-location'],
359                         'nickname' => $a->user['nickname'],
360                         'lockstate' => ( (is_array($a->user)) && ((strlen($a->user['allow_cid'])) || (strlen($a->user['allow_gid'])) || (strlen($a->user['deny_cid'])) || (strlen($a->user['deny_gid']))) ? 'lock' : 'unlock'),
361                         'acl' => populate_acl($a->user, true),
362                         'bang' => '',
363                         'visitor' => 'block',
364                         'profile_uid' => local_user(),
365                         'acl_data' => construct_acl_data($a, $a->user), // For non-Javascript ACL selector
366                 );
367                 $o .= status_editor($a,$x,0,true);
368         }
369
370         $sql_extra = item_permissions_sql($a->profile['uid'],$remote_contact,$groups);
371
372         if ($update) {
373
374                 $r = qu("SELECT `id` FROM `item` WHERE `item`.`uid` = %d
375                         AND `item`.`parent` = (SELECT `parent` FROM `item` WHERE `id` = %d)
376                         $sql_extra AND `unseen`",
377                         intval($a->profile['uid']),
378                         intval($item_id)
379                 );
380
381                 if (!$r) {
382                         return '';
383                 }
384         }
385
386         $r = qu(item_query()." AND `item`.`uid` = %d
387                 AND `item`.`parent` = (SELECT `parent` FROM `item` WHERE `id` = %d)
388                 $sql_extra
389                 ORDER BY `parent` DESC, `gravity` ASC, `id` ASC",
390                 intval($a->profile['uid']),
391                 intval($item_id)
392         );
393
394
395         if (!$r && local_user()) {
396                 // Check if this is another person's link to a post that we have
397                 $r = qu("SELECT `item`.uri FROM `item`
398                         WHERE (`item`.`id` = %d OR `item`.`uri` = '%s')
399                         LIMIT 1",
400                         intval($item_id),
401                         dbesc($item_id)
402                 );
403                 if (dbm::is_result($r)) {
404                         $item_uri = $r[0]['uri'];
405
406                         $r = qu(item_query()." AND `item`.`uid` = %d
407                                 AND `item`.`parent` = (SELECT `parent` FROM `item` WHERE `uri` = '%s' AND uid = %d)
408                                 ORDER BY `parent` DESC, `gravity` ASC, `id` ASC ",
409                                 intval(local_user()),
410                                 dbesc($item_uri),
411                                 intval(local_user())
412                         );
413                 }
414         }
415
416         if ($r) {
417
418                 if ((local_user()) && (local_user() == $a->profile['uid'])) {
419                         $unseen = q("SELECT `id` FROM `item` WHERE `unseen` AND `parent` = %d",
420                                         intval($r[0]['parent']));
421
422                         if ($unseen) {
423                                 q("UPDATE `item` SET `unseen` = 0 WHERE `parent` = %d AND `unseen`",
424                                         intval($r[0]['parent'])
425                                 );
426                         }
427                 }
428
429                 $items = conv_sort($r,"`commented`");
430
431                 if (!$update) {
432                         $o .= "<script> var netargs = '?f=&nick=" . $nick . "&item_id=" . $item_id . "'; </script>";
433                 }
434                 $o .= conversation($a,$items,'display', $update);
435
436                 // Preparing the meta header
437                 require_once('include/bbcode.php');
438                 require_once("include/html2plain.php");
439                 $description = trim(html2plain(bbcode($r[0]["body"], false, false), 0, true));
440                 $title = trim(html2plain(bbcode($r[0]["title"], false, false), 0, true));
441                 $author_name = $r[0]["author-name"];
442
443                 $image = $a->remove_baseurl($r[0]["author-thumb"]);
444
445                 if ($title == "") {
446                         $title = $author_name;
447                 }
448
449                 // Limit the description to 160 characters
450                 if (strlen($description) > 160) {
451                         $description = substr($description, 0, 157) . '...';
452                 }
453
454                 $description = htmlspecialchars($description, ENT_COMPAT, 'UTF-8', true); // allow double encoding here
455                 $title = htmlspecialchars($title, ENT_COMPAT, 'UTF-8', true); // allow double encoding here
456                 $author_name = htmlspecialchars($author_name, ENT_COMPAT, 'UTF-8', true); // allow double encoding here
457
458                 //<meta name="keywords" content="">
459                 $a->page['htmlhead'] .= '<meta name="author" content="'.$author_name.'" />'."\n";
460                 $a->page['htmlhead'] .= '<meta name="title" content="'.$title.'" />'."\n";
461                 $a->page['htmlhead'] .= '<meta name="fulltitle" content="'.$title.'" />'."\n";
462                 $a->page['htmlhead'] .= '<meta name="description" content="'.$description.'" />'."\n";
463
464                 // Schema.org microdata
465                 $a->page['htmlhead'] .= '<meta itemprop="name" content="'.$title.'" />'."\n";
466                 $a->page['htmlhead'] .= '<meta itemprop="description" content="'.$description.'" />'."\n";
467                 $a->page['htmlhead'] .= '<meta itemprop="image" content="'.$image.'" />'."\n";
468                 $a->page['htmlhead'] .= '<meta itemprop="author" content="'.$author_name.'" />'."\n";
469
470                 // Twitter cards
471                 $a->page['htmlhead'] .= '<meta name="twitter:card" content="summary" />'."\n";
472                 $a->page['htmlhead'] .= '<meta name="twitter:title" content="'.$title.'" />'."\n";
473                 $a->page['htmlhead'] .= '<meta name="twitter:description" content="'.$description.'" />'."\n";
474                 $a->page['htmlhead'] .= '<meta name="twitter:image" content="'.$image.'" />'."\n";
475                 $a->page['htmlhead'] .= '<meta name="twitter:url" content="'.$r[0]["plink"].'" />'."\n";
476
477                 // Dublin Core
478                 $a->page['htmlhead'] .= '<meta name="DC.title" content="'.$title.'" />'."\n";
479                 $a->page['htmlhead'] .= '<meta name="DC.description" content="'.$description.'" />'."\n";
480
481                 // Open Graph
482                 $a->page['htmlhead'] .= '<meta property="og:type" content="website" />'."\n";
483                 $a->page['htmlhead'] .= '<meta property="og:title" content="'.$title.'" />'."\n";
484                 $a->page['htmlhead'] .= '<meta property="og:image" content="'.$image.'" />'."\n";
485                 $a->page['htmlhead'] .= '<meta property="og:url" content="'.$r[0]["plink"].'" />'."\n";
486                 $a->page['htmlhead'] .= '<meta property="og:description" content="'.$description.'" />'."\n";
487                 $a->page['htmlhead'] .= '<meta name="og:article:author" content="'.$author_name.'" />'."\n";
488                 // article:tag
489
490                 return $o;
491         }
492
493         $r = qu("SELECT `id`,`deleted` FROM `item` WHERE `id` = '%s' OR `uri` = '%s' LIMIT 1",
494                 dbesc($item_id),
495                 dbesc($item_id)
496         );
497         if ($r) {
498                 if ($r[0]['deleted']) {
499                         notice(t('Item has been removed.') . EOL );
500                 } else {
501                         notice(t('Permission denied.') . EOL );
502                 }
503         } else {
504                 notice(t('Item not found.') . EOL );
505         }
506
507         return $o;
508 }
509