]> git.mxchange.org Git - friendica.git/blob - include/diaspora2.php
"profile". "like" and "comment" could work, status messages only partly.
[friendica.git] / include / diaspora2.php
1 <?php
2 /**
3  * @file include/diaspora.php
4  * @brief The implementation of the diaspora protocol
5  */
6
7 require_once("include/bb2diaspora.php");
8 require_once("include/Scrape.php");
9 require_once("include/Contact.php");
10 require_once("include/Photo.php");
11 require_once("include/socgraph.php");
12
13 class xml {
14         function from_array($array, &$xml) {
15
16                 if (!is_object($xml)) {
17                         foreach($array as $key => $value) {
18                                 $root = new SimpleXMLElement('<'.$key.'/>');
19                                 array_to_xml($value, $root);
20
21                                 $dom = dom_import_simplexml($root)->ownerDocument;
22                                 $dom->formatOutput = true;
23                                 return $dom->saveXML();
24                         }
25                 }
26
27                 foreach($array as $key => $value) {
28                         if (!is_array($value) AND !is_numeric($key))
29                                 $xml->addChild($key, $value);
30                         elseif (is_array($value))
31                                 array_to_xml($value, $xml->addChild($key));
32                 }
33         }
34
35         function copy(&$source, &$target, $elementname) {
36                 if (count($source->children()) == 0)
37                         $target->addChild($elementname, $source);
38                 else {
39                         $child = $target->addChild($elementname);
40                         foreach ($source->children() AS $childfield => $childentry)
41                                 self::copy($childentry, $child, $childfield);
42                 }
43         }
44 }
45 /**
46  * @brief This class contain functions to create and send Diaspora XML files
47  *
48  */
49 class diaspora {
50
51         public static function dispatch_public($msg) {
52
53                 $enabled = intval(get_config("system", "diaspora_enabled"));
54                 if (!$enabled) {
55                         logger("diaspora is disabled");
56                         return false;
57                 }
58
59                 // Use a dummy importer to import the data for the public copy
60                 $importer = array("uid" => 0, "page-flags" => PAGE_FREELOVE);
61                 self::dispatch($importer,$msg);
62
63                 // Now distribute it to the followers
64                 $r = q("SELECT `user`.* FROM `user` WHERE `user`.`uid` IN
65                         (SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s')
66                         AND NOT `account_expired` AND NOT `account_removed`",
67                         dbesc(NETWORK_DIASPORA),
68                         dbesc($msg["author"])
69                 );
70                 if(count($r)) {
71                         foreach($r as $rr) {
72                                 logger("delivering to: ".$rr["username"]);
73                                 self::dispatch($rr,$msg);
74                         }
75                 } else
76                         logger("No subscribers for ".$msg["author"]." ".print_r($msg, true));
77         }
78
79         public static function dispatch($importer, $msg) {
80
81                 // The sender is the handle of the contact that sent the message.
82                 // This will often be different with relayed messages (for example "like" and "comment")
83                 $sender = $msg["author"];
84
85                 if (!diaspora::valid_posting($msg, $fields, $data2)) {
86                         logger("Invalid posting");
87                         return false;
88                 }
89
90                 $type = $fields->getName();
91
92                 switch ($type) {
93                         case "account_deletion": // Not implemented
94                                 return self::import_account_deletion($importer, $fields);
95
96                         case "comment":
97                                 return true;
98                                 //return self::import_comment($importer, $sender, $fields);
99
100                         case "conversation":
101                                 return self::import_conversation($importer, $fields);
102
103                         case "like":
104                                 return true;
105                                 //return self::import_like($importer, $sender, $fields);
106
107                         case "message":
108                                 return true;
109                                 //return self::import_message($importer, $fields);
110
111                         case "participation": // Not implemented
112                                 return self::import_participation($importer, $fields);
113
114                         case "photo":
115                                 return self::import_photo($importer, $fields);
116
117                         case "poll_participation": // Not implemented
118                                 return self::import_poll_participation($importer, $fields);
119
120                         case "profile":
121                                 return true;
122                                 //return self::import_profile($importer, $fields);
123
124                         case "request":
125                                 return self::import_request($importer, $fields);
126
127                         case "reshare":
128                                 return self::import_reshare($importer, $fields);
129
130                         case "retraction":
131                                 return self::import_retraction($importer, $fields);
132
133                         case "status_message":
134                                 return self::import_status_message($importer, $fields, $msg, $data2);
135
136                         default:
137                                 logger("Unknown message type ".$type);
138                                 return false;
139                 }
140
141                 return true;
142         }
143
144         /**
145          * @brief Checks if a posting is valid and fetches the data fields.
146          *
147          * This function does not only check the signature.
148          * It also does the conversion between the old and the new diaspora format.
149          *
150          * @param array $msg Array with the XML, the sender handle and the sender signature
151          * @param object $fields SimpleXML object that contains the posting when it is valid
152          *
153          * @return bool Is the posting valid?
154          */
155         private function valid_posting($msg, &$fields, &$element) {
156
157                 $data = parse_xml_string($msg["message"], false);
158
159                 if (!is_object($data))
160                         return false;
161
162                 $first_child = $data->getName();
163
164                 // Is this the new or the old version?
165                 if ($data->getName() == "XML") {
166                         $oldXML = true;
167                         foreach ($data->post->children() as $child)
168                                 $element = $child;
169                 } else {
170                         $oldXML = false;
171                         $element = $data;
172                 }
173
174                 $type = $element->getName();
175
176                 // All retractions are handled identically from now on.
177                 // In the new version there will only be "retraction".
178                 if (in_array($type, array("signed_retraction", "relayable_retraction")))
179                         $type = "retraction";
180
181                 $fields = new SimpleXMLElement("<".$type."/>");
182
183                 $signed_data = "";
184
185                 foreach ($element->children() AS $fieldname => $entry) {
186                         if ($oldXML) {
187                                 // Translation for the old XML structure
188                                 if ($fieldname == "diaspora_handle")
189                                         $fieldname = "author";
190
191                                 if ($fieldname == "participant_handles")
192                                         $fieldname = "participants";
193
194                                 if (in_array($type, array("like", "participation"))) {
195                                         if ($fieldname == "target_type")
196                                                 $fieldname = "parent_type";
197                                 }
198
199                                 if ($fieldname == "sender_handle")
200                                         $fieldname = "author";
201
202                                 if ($fieldname == "recipient_handle")
203                                         $fieldname = "recipient";
204
205                                 if ($fieldname == "root_diaspora_id")
206                                         $fieldname = "root_author";
207
208                                 if ($type == "retraction") {
209                                         if ($fieldname == "post_guid")
210                                                 $fieldname = "target_guid";
211
212                                         if ($fieldname == "type")
213                                                 $fieldname = "target_type";
214                                 }
215                         }
216
217                         if ($fieldname == "author_signature")
218                                 $author_signature = base64_decode($entry);
219                         elseif ($fieldname == "parent_author_signature")
220                                 $parent_author_signature = base64_decode($entry);
221                         elseif ($fieldname != "target_author_signature") {
222                                 if ($signed_data != "") {
223                                         $signed_data .= ";";
224                                         $signed_data_parent .= ";";
225                                 }
226
227                                 $signed_data .= $entry;
228                         }
229                         if (!in_array($fieldname, array("parent_author_signature", "target_author_signature")))
230                                 xml::copy($entry, $fields, $fieldname);
231                 }
232
233                 // This is something that shouldn't happen at all.
234                 if (in_array($type, array("status_message", "reshare", "profile")))
235                         if ($msg["author"] != $fields->author) {
236                                 logger("Message handle is not the same as envelope sender. Quitting this message.");
237                                 return false;
238                         }
239
240                 // Only some message types have signatures. So we quit here for the other types.
241                 if (!in_array($type, array("comment", "conversation", "message", "like")))
242                         return true;
243
244                 // No author_signature? This is a must, so we quit.
245                 if (!isset($author_signature))
246                         return false;
247
248                 if (isset($parent_author_signature)) {
249                         $key = self::get_key($msg["author"]);
250
251                         if (!rsa_verify($signed_data, $parent_author_signature, $key, "sha256"))
252                                 return false;
253                 }
254
255                 $key = self::get_key($fields->author);
256
257                 return rsa_verify($signed_data, $author_signature, $key, "sha256");
258         }
259
260         private function get_key($handle) {
261                 logger("Fetching diaspora key for: ".$handle);
262
263                 $r = self::get_person_by_handle($handle);
264                 if($r)
265                         return $r["pubkey"];
266
267                 return "";
268         }
269
270         private function get_person_by_handle($handle) {
271
272                 $r = q("SELECT * FROM `fcontact` WHERE `network` = '%s' AND `addr` = '%s' LIMIT 1",
273                         dbesc(NETWORK_DIASPORA),
274                         dbesc($handle)
275                 );
276                 if (count($r)) {
277                         $person = $r[0];
278                         logger("In cache ".print_r($r,true), LOGGER_DEBUG);
279
280                         // update record occasionally so it doesn't get stale
281                         $d = strtotime($person["updated"]." +00:00");
282                         if ($d < strtotime("now - 14 days"))
283                                 $update = true;
284                 }
285
286                 if (!$person OR $update) {
287                         logger("create or refresh", LOGGER_DEBUG);
288                         $r = probe_url($handle, PROBE_DIASPORA);
289
290                         // Note that Friendica contacts will return a "Diaspora person"
291                         // if Diaspora connectivity is enabled on their server
292                         if (count($r) AND ($r["network"] === NETWORK_DIASPORA)) {
293                                 self::add_fcontact($r, $update);
294                                 $person = $r;
295                         }
296                 }
297                 return $person;
298         }
299
300         private function add_fcontact($arr, $update = false) {
301                 /// @todo Remove this function from include/network.php
302
303                 if($update) {
304                         $r = q("UPDATE `fcontact` SET
305                                         `name` = '%s',
306                                         `photo` = '%s',
307                                         `request` = '%s',
308                                         `nick` = '%s',
309                                         `addr` = '%s',
310                                         `batch` = '%s',
311                                         `notify` = '%s',
312                                         `poll` = '%s',
313                                         `confirm` = '%s',
314                                         `alias` = '%s',
315                                         `pubkey` = '%s',
316                                         `updated` = '%s'
317                                 WHERE `url` = '%s' AND `network` = '%s'",
318                                         dbesc($arr["name"]),
319                                         dbesc($arr["photo"]),
320                                         dbesc($arr["request"]),
321                                         dbesc($arr["nick"]),
322                                         dbesc($arr["addr"]),
323                                         dbesc($arr["batch"]),
324                                         dbesc($arr["notify"]),
325                                         dbesc($arr["poll"]),
326                                         dbesc($arr["confirm"]),
327                                         dbesc($arr["alias"]),
328                                         dbesc($arr["pubkey"]),
329                                         dbesc(datetime_convert()),
330                                         dbesc($arr["url"]),
331                                         dbesc($arr["network"])
332                                 );
333                 } else {
334                         $r = q("INSERT INTO `fcontact` (`url`,`name`,`photo`,`request`,`nick`,`addr`,
335                                         `batch`, `notify`,`poll`,`confirm`,`network`,`alias`,`pubkey`,`updated`)
336                                 VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')",
337                                         dbesc($arr["url"]),
338                                         dbesc($arr["name"]),
339                                         dbesc($arr["photo"]),
340                                         dbesc($arr["request"]),
341                                         dbesc($arr["nick"]),
342                                         dbesc($arr["addr"]),
343                                         dbesc($arr["batch"]),
344                                         dbesc($arr["notify"]),
345                                         dbesc($arr["poll"]),
346                                         dbesc($arr["confirm"]),
347                                         dbesc($arr["network"]),
348                                         dbesc($arr["alias"]),
349                                         dbesc($arr["pubkey"]),
350                                         dbesc(datetime_convert())
351                                 );
352                 }
353
354                 return $r;
355         }
356
357         private function get_contact_by_handle($uid, $handle) {
358                 $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `addr` = '%s' LIMIT 1",
359                         intval($uid),
360                         dbesc($handle)
361                 );
362
363                 if ($r AND count($r))
364                         return $r[0];
365
366                 $handle_parts = explode("@", $handle);
367                 $nurl_sql = '%%://' . $handle_parts[1] . '%%/profile/' . $handle_parts[0];
368                 $r = q("SELECT * FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `nurl` LIKE '%s' LIMIT 1",
369                         dbesc(NETWORK_DFRN),
370                         intval($uid),
371                         dbesc($nurl_sql)
372                 );
373                 if($r AND count($r))
374                         return $r[0];
375
376                 return false;
377         }
378
379         private function fetch_guid($item) {
380                 preg_replace_callback("&\[url=/posts/([^\[\]]*)\](.*)\[\/url\]&Usi",
381                         function ($match) use ($item){
382                                 return(self::fetch_guid_sub($match, $item));
383                         },$item["body"]);
384         }
385
386         private function fetch_guid_sub($match, $item) {
387                 $a = get_app();
388
389                 if (!self::store_by_guid($match[1], $item["author-link"]))
390                         self::store_by_guid($match[1], $item["owner-link"]);
391         }
392
393         private function store_by_guid($guid, $server, $uid = 0) {
394                 $serverparts = parse_url($server);
395                 $server = $serverparts["scheme"]."://".$serverparts["host"];
396
397                 logger("Trying to fetch item ".$guid." from ".$server, LOGGER_DEBUG);
398
399                 $msg = self::fetch_message($guid, $server);
400
401                 if (!$msg)
402                         return false;
403
404                 logger("Successfully fetched item ".$guid." from ".$server, LOGGER_DEBUG);
405
406                 // Now call the dispatcher
407                 return self::dispatch_public($msg);
408         }
409
410         private function fetch_message($guid, $server, $level = 0) {
411
412                 if ($level > 5)
413                         return false;
414
415                 // This will not work if the server is not a Diaspora server
416                 $source_url = $server."/p/".$guid.".xml";
417                 $x = fetch_url($source_url);
418                 if(!$x)
419                         return false;
420
421                 /// @todo - should maybe solved by the dispatcher
422                 $source_xml = parse_xml_string($x, false);
423
424                 if (!is_object($source_xml))
425                         return false;
426
427                 if ($source_xml->post->reshare) {
428                         // Reshare of a reshare - old Diaspora version
429                         return self::fetch_message($source_xml->post->reshare->root_guid, $server, ++$level);
430                 } elseif ($source_xml->getName() == "reshare") {
431                         // Reshare of a reshare - new Diaspora version
432                         return self::fetch_message($source_xml->root_guid, $server, ++$level);
433                 }
434
435                 // Fetch the author - for the old and the new Diaspora version
436                 if ($source_xml->post->status_message->diaspora_handle)
437                         $author = (string)$source_xml->post->status_message->diaspora_handle;
438                 elseif ($source_xml->author)
439                         $author = (string)$source_xml->author;
440
441                 if (!$author)
442                         return false;
443
444                 $msg = array("message" => $x, "author" => $author);
445
446                 // We don't really need this, but until the work is unfinished we better will keep this
447                 $msg["key"] = self::get_key($msg["author"]);
448
449                 return $msg;
450         }
451
452         private function post_allow($importer, $contact, $is_comment = false) {
453
454                 // perhaps we were already sharing with this person. Now they're sharing with us.
455                 // That makes us friends.
456                 // Normally this should have handled by getting a request - but this could get lost
457                 if($contact["rel"] == CONTACT_IS_FOLLOWER && in_array($importer["page-flags"], array(PAGE_FREELOVE))) {
458                         q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
459                                 intval(CONTACT_IS_FRIEND),
460                                 intval($contact["id"]),
461                                 intval($importer["uid"])
462                         );
463                         $contact["rel"] = CONTACT_IS_FRIEND;
464                         logger("defining user ".$contact["nick"]." as friend");
465                 }
466
467                 if(($contact["blocked"]) || ($contact["readonly"]) || ($contact["archive"]))
468                         return false;
469                 if($contact["rel"] == CONTACT_IS_SHARING || $contact["rel"] == CONTACT_IS_FRIEND)
470                         return true;
471                 if($contact["rel"] == CONTACT_IS_FOLLOWER)
472                         if(($importer["page-flags"] == PAGE_COMMUNITY) OR $is_comment)
473                                 return true;
474
475                 // Messages for the global users are always accepted
476                 if ($importer["uid"] == 0)
477                         return true;
478
479                 return false;
480         }
481
482         private function fetch_parent_item($uid, $guid, $author, $contact) {
483                 $r = q("SELECT `id`, `body`, `wall`, `uri`, `private`, `origin`,
484                                 `author-name`, `author-link`, `author-avatar`,
485                                 `owner-name`, `owner-link`, `owner-avatar`
486                         FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
487                         intval($uid), dbesc($guid));
488
489                 if(!count($r)) {
490                         $result = self::store_by_guid($guid, $contact["url"], $uid);
491
492                         if (!$result) {
493                                 $person = self::get_person_by_handle($author);
494                                 $result = self::store_by_guid($guid, $person["url"], $uid);
495                         }
496
497                         if ($result) {
498                                 logger("Fetched missing item ".$guid." - result: ".$result, LOGGER_DEBUG);
499
500                                 $r = q("SELECT `id`, `body`, `wall`, `uri`, `private`, `origin`,
501                                                 `author-name`, `author-link`, `author-avatar`,
502                                                 `owner-name`, `owner-link`, `owner-avatar`
503                                         FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
504                                         intval($uid), dbesc($guid));
505                         }
506                 }
507
508                 if (!count($r)) {
509                         logger("parent item not found: parent: ".$guid." item: ".$guid);
510                         return false;
511                 } else
512                         return $r[0];
513         }
514
515         private function get_author_contact_by_url($contact, $person, $uid) {
516
517                 $r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
518                         dbesc(normalise_link($person["url"])), intval($uid));
519                 if ($r) {
520                         $cid = $r[0]["id"];
521                         $network = $r[0]["network"];
522                 } else {
523                         $cid = $contact["id"];
524                         $network = NETWORK_DIASPORA;
525                 }
526
527                 return (array("cid" => $cid, "network" => $network));
528         }
529
530         public static function is_redmatrix($url) {
531                 return(strstr($url, "/channel/"));
532         }
533
534         private function plink($addr, $guid) {
535                 $r = q("SELECT `url`, `nick`, `network` FROM `fcontact` WHERE `addr`='%s' LIMIT 1", dbesc($addr));
536
537                 // Fallback
538                 if (!$r)
539                         return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$guid;
540
541                 // Friendica contacts are often detected as Diaspora contacts in the "fcontact" table
542                 // So we try another way as well.
543                 $s = q("SELECT `network` FROM `gcontact` WHERE `nurl`='%s' LIMIT 1", dbesc(normalise_link($r[0]["url"])));
544                 if ($s)
545                         $r[0]["network"] = $s[0]["network"];
546
547                 if ($r[0]["network"] == NETWORK_DFRN)
548                         return(str_replace("/profile/".$r[0]["nick"]."/", "/display/".$guid, $r[0]["url"]."/"));
549
550                 if (self::is_redmatrix($r[0]["url"]))
551                         return $r[0]["url"]."/?f=&mid=".$guid;
552
553                 return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$guid;
554         }
555
556         private function import_account_deletion($importer, $data) {
557                 // Not supported by now. We are waiting for sample data
558                 return true;
559         }
560
561         private function import_comment($importer, $sender, $data) {
562                 $guid = notags(unxmlify($data->guid));
563                 $parent_guid = notags(unxmlify($data->parent_guid));
564                 $text = unxmlify($data->text);
565                 $author = notags(unxmlify($data->author));
566
567                 $contact = self::get_contact_by_handle($importer["uid"], $sender);
568                 if (!$contact) {
569                         logger("cannot find contact for sender: ".$sender);
570                         return false;
571                 }
572
573                 if (!self::post_allow($importer,$contact, true)) {
574                         logger("Ignoring the author ".$sender);
575                         return false;
576                 }
577
578                 $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
579                         intval($importer["uid"]),
580                         dbesc($guid)
581                 );
582                 if(count($r)) {
583                         logger("The comment already exists: ".$guid);
584                         return false;
585                 }
586
587                 $parent_item = self::fetch_parent_item($importer["uid"], $parent_guid, $author, $contact);
588                 if (!$parent_item)
589                         return false;
590
591                 $person = self::get_person_by_handle($author);
592                 if (!is_array($person)) {
593                         logger("unable to find author details");
594                         return false;
595                 }
596
597                 // Fetch the contact id - if we know this contact
598                 $author_contact = self::get_author_contact_by_url($contact, $person, $importer["uid"]);
599
600                 $datarray = array();
601
602                 $datarray["uid"] = $importer["uid"];
603                 $datarray["contact-id"] = $author_contact["cid"];
604                 $datarray["network"]  = $author_contact["network"];
605
606                 $datarray["author-name"] = $person["name"];
607                 $datarray["author-link"] = $person["url"];
608                 $datarray["author-avatar"] = ((x($person,"thumb")) ? $person["thumb"] : $person["photo"]);
609
610                 $datarray["owner-name"] = $contact["name"];
611                 $datarray["owner-link"] = $contact["url"];
612                 $datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
613
614                 $datarray["guid"] = $guid;
615                 $datarray["uri"] = $author.":".$guid;
616
617                 $datarray["type"] = "remote-comment";
618                 $datarray["verb"] = ACTIVITY_POST;
619                 $datarray["gravity"] = GRAVITY_COMMENT;
620                 $datarray["parent-uri"] = $parent_item["uri"];
621
622                 $datarray["object-type"] = ACTIVITY_OBJ_COMMENT;
623                 $datarray["object"] = json_encode($data);
624
625                 $datarray["body"] = diaspora2bb($text);
626
627                 self::fetch_guid($datarray);
628
629                 $message_id = item_store($datarray);
630                 // print_r($datarray);
631
632                 // If we are the origin of the parent we store the original data and notify our followers
633                 if($message_id AND $parent_item["origin"]) {
634
635                         // Formerly we stored the signed text, the signature and the author in different fields.
636                         // The new Diaspora protocol can have variable fields. We now store the data in correct order in a single field.
637                         q("INSERT INTO `sign` (`iid`,`signed_text`) VALUES (%d,'%s')",
638                                 intval($message_id),
639                                 dbesc(json_encode($data))
640                         );
641
642                         // notify others
643                         proc_run("php", "include/notifier.php", "comment-import", $message_id);
644                 }
645
646                 return $message_id;
647         }
648
649         private function import_conversation($importer, $data) {
650                 return true;
651         }
652
653         private function construct_like_body($contact, $parent_item, $guid) {
654                 $bodyverb = t('%1$s likes %2$s\'s %3$s');
655
656                 $ulink = "[url=".$contact["url"]."]".$contact["name"]."[/url]";
657                 $alink = "[url=".$parent_item["author-link"]."]".$parent_item["author-name"]."[/url]";
658                 $plink = "[url=".App::get_baseurl()."/display/".urlencode($guid)."]".t("status")."[/url]";
659
660                 return sprintf($bodyverb, $ulink, $alink, $plink);
661         }
662
663         private function construct_like_object($importer, $parent_item) {
664                 $objtype = ACTIVITY_OBJ_NOTE;
665                 $link = xmlify('<link rel="alternate" type="text/html" href="'.App::get_baseurl()."/display/".$importer["nickname"]."/".$parent_item["id"].'" />'."\n") ;
666                 $parent_body = $parent_item["body"];
667
668                 $obj = <<< EOT
669
670                 <object>
671                         <type>$objtype</type>
672                         <local>1</local>
673                         <id>{$parent_item["uri"]}</id>
674                         <link>$link</link>
675                         <title></title>
676                         <content>$parent_body</content>
677                 </object>
678 EOT;
679
680                 return $obj;
681         }
682
683         private function import_like($importer, $sender, $data) {
684                 $positive = notags(unxmlify($data->positive));
685                 $guid = notags(unxmlify($data->guid));
686                 $parent_type = notags(unxmlify($data->parent_type));
687                 $parent_guid = notags(unxmlify($data->parent_guid));
688                 $author = notags(unxmlify($data->author));
689
690                 // likes on comments aren't supported by Diaspora - only on posts
691                 if ($parent_type !== "Post")
692                         return false;
693
694                 // "positive" = "false" doesn't seem to be supported by Diaspora
695                 if ($positive === "false") {
696                         logger("Received a like with positive set to 'false' - this shouldn't exist at all");
697                         return false;
698                 }
699
700                 $contact = self::get_contact_by_handle($importer["uid"], $sender);
701                 if (!$contact) {
702                         logger("cannot find contact for sender: ".$sender);
703                         return false;
704                 }
705
706                 if (!self::post_allow($importer,$contact, true)) {
707                         logger("Ignoring the author ".$sender);
708                         return false;
709                 }
710
711                 $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
712                         intval($importer["uid"]),
713                         dbesc($guid)
714                 );
715                 if(count($r)) {
716                         logger("The like already exists: ".$guid);
717                         return false;
718                 }
719
720                 $parent_item = self::fetch_parent_item($importer["uid"], $parent_guid, $author, $contact);
721                 if (!$parent_item)
722                         return false;
723
724                 $person = self::get_person_by_handle($author);
725                 if (!is_array($person)) {
726                         logger("unable to find author details");
727                         return false;
728                 }
729
730                 // Fetch the contact id - if we know this contact
731                 $author_contact = self::get_author_contact_by_url($contact, $person, $importer["uid"]);
732
733                 $datarray = array();
734
735                 $datarray["uid"] = $importer["uid"];
736                 $datarray["contact-id"] = $author_contact["cid"];
737                 $datarray["network"]  = $author_contact["network"];
738
739                 $datarray["author-name"] = $person["name"];
740                 $datarray["author-link"] = $person["url"];
741                 $datarray["author-avatar"] = ((x($person,"thumb")) ? $person["thumb"] : $person["photo"]);
742
743                 $datarray["owner-name"] = $contact["name"];
744                 $datarray["owner-link"] = $contact["url"];
745                 $datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
746
747                 $datarray["guid"] = $guid;
748                 $datarray["uri"] = $author.":".$guid;
749
750                 $datarray["type"] = "activity";
751                 $datarray["verb"] = ACTIVITY_LIKE;
752                 $datarray["gravity"] = GRAVITY_LIKE;
753                 $datarray["parent-uri"] = $parent_item["uri"];
754
755                 $datarray["object-type"] = ACTIVITY_OBJ_NOTE;
756                 $datarray["object"] = self::construct_like_object($importer, $parent_item);
757
758                 $datarray["body"] = self::construct_like_body($contact, $parent_item, $guid);
759
760                 $message_id = item_store($datarray);
761                 //print_r($datarray);
762
763                 // If we are the origin of the parent we store the original data and notify our followers
764                 if($message_id AND $parent_item["origin"]) {
765
766                         // Formerly we stored the signed text, the signature and the author in different fields.
767                         // The new Diaspora protocol can have variable fields. We now store the data in correct order in a single field.
768                         q("INSERT INTO `sign` (`iid`,`signed_text`) VALUES (%d,'%s')",
769                                 intval($message_id),
770                                 dbesc(json_encode($data))
771                         );
772
773                         // notify others
774                         proc_run("php", "include/notifier.php", "comment-import", $message_id);
775                 }
776
777                 return $message_id;
778         }
779
780         private function import_message($importer, $data) {
781                 $guid = notags(unxmlify($data->guid));
782                 $parent_guid = notags(unxmlify($data->parent_guid));
783                 $text = unxmlify($data->text);
784                 $created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
785                 $author = notags(unxmlify($data->author));
786                 $conversation_guid = notags(unxmlify($data->conversation_guid));
787
788                 $parent_uri = $author.":".$parent_guid;
789
790                 $contact = self::get_contact_by_handle($importer["uid"], $author);
791                 if (!$contact) {
792                         logger("cannot find contact: ".$author);
793                         return false;
794                 }
795
796                 if(($contact["rel"] == CONTACT_IS_FOLLOWER) || ($contact["blocked"]) || ($contact["readonly"])) {
797                         logger("Ignoring this author.");
798                         return false;
799                 }
800
801                 $conversation = null;
802
803                 $c = q("SELECT * FROM `conv` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
804                         intval($importer["uid"]),
805                         dbesc($conversation_guid)
806                 );
807                 if(count($c))
808                         $conversation = $c[0];
809                 else {
810                         logger("conversation not available.");
811                         return false;
812                 }
813
814                 $reply = 0;
815
816                 $body = diaspora2bb($text);
817                 $message_id = $author.":".$guid;
818
819                 $person = self::get_person_by_handle($author);
820                 if (!$person) {
821                         logger("unable to find author details");
822                         return false;
823                 }
824
825                 $r = q("SELECT `id` FROM `mail` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
826                         dbesc($message_id),
827                         intval($importer["uid"])
828                 );
829                 if(count($r)) {
830                         logger("duplicate message already delivered.", LOGGER_DEBUG);
831                         return false;
832                 }
833
834                 q("INSERT INTO `mail` (`uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`)
835                                 VALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')",
836                         intval($importer["uid"]),
837                         dbesc($guid),
838                         intval($conversation["id"]),
839                         dbesc($person["name"]),
840                         dbesc($person["photo"]),
841                         dbesc($person["url"]),
842                         intval($contact["id"]),
843                         dbesc($conversation["subject"]),
844                         dbesc($body),
845                         0,
846                         1,
847                         dbesc($message_id),
848                         dbesc($parent_uri),
849                         dbesc($created_at)
850                 );
851
852                 q("UPDATE `conv` SET `updated` = '%s' WHERE `id` = %d",
853                         dbesc(datetime_convert()),
854                         intval($conversation["id"])
855                 );
856
857                 return true;
858         }
859
860         private function import_participation($importer, $data) {
861                 return true;
862         }
863
864         private function import_photo($importer, $data) {
865                 return true;
866         }
867
868         private function import_poll_participation($importer, $data) {
869                 return true;
870         }
871
872         private function import_profile($importer, $data) {
873                 $author = notags(unxmlify($data->author));
874
875                 $contact = self::get_contact_by_handle($importer["uid"], $author);
876                 if (!$contact)
877                         return;
878
879                 $name = unxmlify($data->first_name).((strlen($data->last_name)) ? " ".unxmlify($data->last_name) : "");
880                 $image_url = unxmlify($data->image_url);
881                 $birthday = unxmlify($data->birthday);
882                 $location = diaspora2bb(unxmlify($data->location));
883                 $about = diaspora2bb(unxmlify($data->bio));
884                 $gender = unxmlify($data->gender);
885                 $searchable = (unxmlify($data->searchable) == "true");
886                 $nsfw = (unxmlify($data->nsfw) == "true");
887                 $tags = unxmlify($data->tag_string);
888
889                 $tags = explode("#", $tags);
890
891                 $keywords = array();
892                 foreach ($tags as $tag) {
893                         $tag = trim(strtolower($tag));
894                         if ($tag != "")
895                                 $keywords[] = $tag;
896                 }
897
898                 $keywords = implode(", ", $keywords);
899
900                 $handle_parts = explode("@", $author);
901                 $nick = $handle_parts[0];
902
903                 if($name === "")
904                         $name = $handle_parts[0];
905
906                 if( preg_match("|^https?://|", $image_url) === 0)
907                         $image_url = "http://".$handle_parts[1].$image_url;
908
909                 update_contact_avatar($image_url, $importer["uid"], $contact["id"]);
910
911                 // Generic birthday. We don't know the timezone. The year is irrelevant.
912
913                 $birthday = str_replace("1000", "1901", $birthday);
914
915                 if ($birthday != "")
916                         $birthday = datetime_convert("UTC", "UTC", $birthday, "Y-m-d");
917
918                 // this is to prevent multiple birthday notifications in a single year
919                 // if we already have a stored birthday and the 'm-d' part hasn't changed, preserve the entry, which will preserve the notify year
920
921                 if(substr($birthday,5) === substr($contact["bd"],5))
922                         $birthday = $contact["bd"];
923
924                 $r = q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `addr` = '%s', `name-date` = '%s', `bd` = '%s',
925                                 `location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s' WHERE `id` = %d AND `uid` = %d",
926                         dbesc($name),
927                         dbesc($nick),
928                         dbesc($author),
929                         dbesc(datetime_convert()),
930                         dbesc($birthday),
931                         dbesc($location),
932                         dbesc($about),
933                         dbesc($keywords),
934                         dbesc($gender),
935                         intval($contact["id"]),
936                         intval($importer["uid"])
937                 );
938
939                 if ($searchable) {
940                         poco_check($contact["url"], $name, NETWORK_DIASPORA, $image_url, $about, $location, $gender, $keywords, "",
941                                 datetime_convert(), 2, $contact["id"], $importer["uid"]);
942                 }
943
944                 $gcontact = array("url" => $contact["url"], "network" => NETWORK_DIASPORA, "generation" => 2,
945                                         "photo" => $image_url, "name" => $name, "location" => $location,
946                                         "about" => $about, "birthday" => $birthday, "gender" => $gender,
947                                         "addr" => $author, "nick" => $nick, "keywords" => $keywords,
948                                         "hide" => !$searchable, "nsfw" => $nsfw);
949
950                 update_gcontact($gcontact);
951
952                 return true;
953         }
954
955         private function import_request($importer, $data) {
956 print_r($data);
957 /*
958         $author = unxmlify($xml->author);
959         $recipient = unxmlify($xml->recipient);
960
961         if (!$author || !$recipient)
962                 return;
963
964         $contact = self::get_contact_by_handle($importer["uid"],$author);
965
966         if($contact) {
967
968                 // perhaps we were already sharing with this person. Now they're sharing with us.
969                 // That makes us friends.
970
971                 if($contact["rel"] == CONTACT_IS_FOLLOWER && in_array($importer["page-flags"], array(PAGE_FREELOVE))) {
972                         q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
973                                 intval(CONTACT_IS_FRIEND),
974                                 intval($contact["id"]),
975                                 intval($importer["uid"])
976                         );
977                 }
978                 // send notification
979
980                 $r = q("SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1",
981                         intval($importer["uid"])
982                 );
983
984                 if((count($r)) && (!$r[0]["hide-friends"]) && (!$contact["hidden"]) && intval(get_pconfig($importer["uid"],'system','post_newfriend'))) {
985                         require_once('include/items.php');
986
987                         $self = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
988                                 intval($importer["uid"])
989                         );
990
991                         // they are not CONTACT_IS_FOLLOWER anymore but that's what we have in the array
992
993                         if(count($self) && $contact["rel"] == CONTACT_IS_FOLLOWER) {
994
995                                 $arr = array();
996                                 $arr["uri"] = $arr["parent-uri"] = item_new_uri($a->get_hostname(), $importer["uid"]);
997                                 $arr["uid"] = $importer["uid"];
998                                 $arr["contact-id"] = $self[0]["id"];
999                                 $arr["wall"] = 1;
1000                                 $arr["type"] = 'wall';
1001                                 $arr["gravity"] = 0;
1002                                 $arr["origin"] = 1;
1003                                 $arr["author-name"] = $arr["owner-name"] = $self[0]["name"];
1004                                 $arr["author-link"] = $arr["owner-link"] = $self[0]["url"];
1005                                 $arr["author-avatar"] = $arr["owner-avatar"] = $self[0]["thumb"];
1006                                 $arr["verb"] = ACTIVITY_FRIEND;
1007                                 $arr["object-type"] = ACTIVITY_OBJ_PERSON;
1008
1009                                 $A = '[url=' . $self[0]["url"] . "]' . $self[0]["name"] . '[/url]';
1010                                 $B = '[url=' . $contact["url"] . "]' . $contact["name"] . '[/url]';
1011                                 $BPhoto = '[url=' . $contact["url"] . "]' . '[img]' . $contact["thumb"] . '[/img][/url]';
1012                                 $arr["body"] =  sprintf( t('%1$s is now friends with %2$s'), $A, $B)."\n\n\n".$Bphoto;
1013
1014                                 $arr["object"] = '<object><type>' . ACTIVITY_OBJ_PERSON . '</type><title>' . $contact["name"] . '</title>'
1015                                         . '<id>' . $contact["url"] . '/' . $contact["name"] . '</id>';
1016                                 $arr["object"] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $contact["url"] . '" />' . "\n")
1017 ;
1018                                 $arr["object"] .= xmlify('<link rel="photo" type="image/jpeg" href="' . $contact["thumb"] . '" />' . "\n");
1019                                 $arr["object"] .= '</link></object>' . "\n";
1020                                 $arr["last-child"] = 1;
1021
1022                                 $arr["allow_cid"] = $user[0]["allow_cid"];
1023                                 $arr["allow_gid"] = $user[0]["allow_gid"];
1024                                 $arr["deny_cid"]  = $user[0]["deny_cid"];
1025                                 $arr["deny_gid"]  = $user[0]["deny_gid"];
1026
1027                                 $i = item_store($arr);
1028                                 if($i)
1029                                 proc_run('php',"include/notifier.php","activity","$i");
1030
1031                         }
1032
1033                 }
1034
1035                 return;
1036         }
1037
1038         $ret = self::get_person_by_handle($author);
1039
1040
1041         if((! count($ret)) || ($ret["network"] != NETWORK_DIASPORA)) {
1042                 logger('diaspora_request: Cannot resolve diaspora handle ' . $author . ' for ' . $recipient);
1043                 return;
1044         }
1045
1046         $batch = (($ret["batch"]) ? $ret["batch"] : implode('/', array_slice(explode('/',$ret["url"]),0,3)) . '/receive/public');
1047
1048
1049
1050         $r = q("INSERT INTO `contact` (`uid`, `network`,`addr`,`created`,`url`,`nurl`,`batch`,`name`,`nick`,`photo`,`pubkey`,`notify`,`poll`,`blocked`,`priority`)
1051                 VALUES ( %d, '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s','%s',%d,%d) ",
1052                 intval($importer["uid"]),
1053                 dbesc($ret["network"]),
1054                 dbesc($ret["addr"]),
1055                 datetime_convert(),
1056                 dbesc($ret["url"]),
1057                 dbesc(normalise_link($ret["url"])),
1058                 dbesc($batch),
1059                 dbesc($ret["name"]),
1060                 dbesc($ret["nick"]),
1061                 dbesc($ret["photo"]),
1062                 dbesc($ret["pubkey"]),
1063                 dbesc($ret["notify"]),
1064                 dbesc($ret["poll"]),
1065                 1,
1066                 2
1067         );
1068
1069         // find the contact record we just created
1070
1071         $contact_record = diaspora_get_contact_by_handle($importer["uid"],$author);
1072
1073         if(! $contact_record) {
1074                 logger('diaspora_request: unable to locate newly created contact record.');
1075                 return;
1076         }
1077
1078         $g = q("select def_gid from user where uid = %d limit 1",
1079                 intval($importer["uid"])
1080         );
1081         if($g && intval($g[0]["def_gid"])) {
1082                 require_once('include/group.php');
1083                 group_add_member($importer["uid"],'',$contact_record["id"],$g[0]["def_gid"]);
1084         }
1085
1086         if($importer["page-flags"] == PAGE_NORMAL) {
1087
1088                 $hash = random_string() . (string) time();   // Generate a confirm_key
1089
1090                 $ret = q("INSERT INTO `intro` ( `uid`, `contact-id`, `blocked`, `knowyou`, `note`, `hash`, `datetime` )
1091                         VALUES ( %d, %d, %d, %d, '%s', '%s', '%s' )",
1092                         intval($importer["uid"]),
1093                         intval($contact_record["id"]),
1094                         0,
1095                         0,
1096                         dbesc( t('Sharing notification from Diaspora network')),
1097                         dbesc($hash),
1098                         dbesc(datetime_convert())
1099                 );
1100         }
1101         else {
1102
1103                 // automatic friend approval
1104
1105                 require_once('include/Photo.php');
1106
1107                 update_contact_avatar($contact_record["photo"],$importer["uid"],$contact_record["id"]);
1108
1109                 // technically they are sharing with us (CONTACT_IS_SHARING),
1110                 // but if our page-type is PAGE_COMMUNITY or PAGE_SOAPBOX
1111                 // we are going to change the relationship and make them a follower.
1112
1113                 if($importer["page-flags"] == PAGE_FREELOVE)
1114                         $new_relation = CONTACT_IS_FRIEND;
1115                 else
1116                         $new_relation = CONTACT_IS_FOLLOWER;
1117
1118                 $r = q("UPDATE `contact` SET `rel` = %d,
1119                         `name-date` = '%s',
1120                         `uri-date` = '%s',
1121                         `blocked` = 0,
1122                         `pending` = 0,
1123                         `writable` = 1
1124                         WHERE `id` = %d
1125                         ",
1126                         intval($new_relation),
1127                         dbesc(datetime_convert()),
1128                         dbesc(datetime_convert()),
1129                         intval($contact_record["id"])
1130                 );
1131
1132                 $u = q("select * from user where uid = %d limit 1",intval($importer["uid"]));
1133                 if($u)
1134                         $ret = diaspora_share($u[0],$contact_record);
1135         }
1136 */
1137                 return true;
1138         }
1139
1140         private function import_reshare($importer, $data) {
1141 /*
1142         $guid = notags(unxmlify($xml->guid));
1143         $author = notags(unxmlify($xml->author));
1144
1145
1146         if($author != $msg["author"]) {
1147                 logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.');
1148                 return 202;
1149         }
1150
1151         $contact = diaspora_get_contact_by_handle($importer["uid"],$author);
1152         if(! $contact)
1153                 return;
1154
1155         if(! diaspora_post_allow($importer,$contact, false)) {
1156                 logger('diaspora_reshare: Ignoring this author: ' . $author . ' ' . print_r($xml,true));
1157                 return 202;
1158         }
1159
1160         $message_id = $author . ':' . $guid;
1161         $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
1162                 intval($importer["uid"]),
1163                 dbesc($guid)
1164         );
1165         if(count($r)) {
1166                 logger('diaspora_reshare: message exists: ' . $guid);
1167                 return;
1168         }
1169
1170         $orig_author = notags(unxmlify($xml->root_diaspora_id));
1171         $orig_guid = notags(unxmlify($xml->root_guid));
1172         $orig_url = $a->get_baseurl()."/display/".$orig_guid;
1173
1174         $create_original_post = false;
1175
1176         // Do we already have this item?
1177         $r = q("SELECT `body`, `tag`, `app`, `created`, `plink`, `object`, `object-type`, `uri` FROM `item` WHERE `guid` = '%s' AND `visible` AND NOT 
1178 `deleted` AND `body` != '' LIMIT 1",
1179                 dbesc($orig_guid),
1180                 dbesc(NETWORK_DIASPORA)
1181         );
1182         if(count($r)) {
1183                 logger('reshared message '.$orig_guid." reshared by ".$guid.' already exists on system.');
1184
1185                 // Maybe it is already a reshared item?
1186                 // Then refetch the content, since there can be many side effects with reshared posts from other networks or reshares from reshares
1187                 require_once('include/api.php');
1188                 if (api_share_as_retweet($r[0]))
1189                         $r = array();
1190                 else {
1191                         $body = $r[0]["body"];
1192                         $str_tags = $r[0]["tag"];
1193                         $app = $r[0]["app"];
1194                         $orig_created = $r[0]["created"];
1195                         $orig_plink = $r[0]["plink"];
1196                         $orig_uri = $r[0]["uri"];
1197                         $object = $r[0]["object"];
1198                         $objecttype = $r[0]["object-type"];
1199                 }
1200         }
1201
1202         if (!count($r)) {
1203                 $body = "";
1204                 $str_tags = "";
1205                 $app = "";
1206
1207                 $server = 'https://'.substr($orig_author,strpos($orig_author,'@')+1);
1208                 logger('1st try: reshared message '.$orig_guid." reshared by ".$guid.' will be fetched from original server: '.$server);
1209                 $item = diaspora_fetch_message($orig_guid, $server);
1210
1211                 if (!$item) {
1212                         $server = 'https://'.substr($author,strpos($author,'@')+1);
1213                         logger('2nd try: reshared message '.$orig_guid." reshared by ".$guid." will be fetched from sharer's server: ".$server);
1214                         $item = diaspora_fetch_message($orig_guid, $server);
1215                 }
1216                 if (!$item) {
1217                         $server = 'http://'.substr($orig_author,strpos($orig_author,'@')+1);
1218                         logger('3rd try: reshared message '.$orig_guid." reshared by ".$guid.' will be fetched from original server: '.$server);
1219                         $item = diaspora_fetch_message($orig_guid, $server);
1220                 }
1221                 if (!$item) {
1222                         $server = 'http://'.substr($author,strpos($author,'@')+1);
1223                         logger('4th try: reshared message '.$orig_guid." reshared by ".$guid." will be fetched from sharer's server: ".$server);
1224                         $item = diaspora_fetch_message($orig_guid, $server);
1225                 }
1226
1227                 if ($item) {
1228                         $body = $item["body"];
1229                         $str_tags = $item["tag"];
1230                         $app = $item["app"];
1231                         $orig_created = $item["created"];
1232                         $orig_author = $item["author"];
1233                         $orig_guid = $item["guid"];
1234                         $orig_plink = diaspora_plink($orig_author, $orig_guid);
1235                         $orig_uri = $orig_author.':'.$orig_guid;
1236                         $create_original_post = ($body != "");
1237                         $object = $item["object"];
1238                         $objecttype = $item["object-type"];
1239                 }
1240         }
1241
1242         $plink = diaspora_plink($author, $guid);
1243
1244         $person = find_diaspora_person_by_handle($orig_author);
1245
1246         $created = unxmlify($xml->created_at);
1247         $private = ((unxmlify($xml->public) == 'false') ? 1 : 0);
1248
1249         $datarray = array();
1250
1251         $datarray["uid"] = $importer["uid"];
1252         $datarray["contact-id"] = $contact["id"];
1253         $datarray["wall"] = 0;
1254         $datarray["network"]  = NETWORK_DIASPORA;
1255         $datarray["guid"] = $guid;
1256         $datarray["uri"] = $datarray["parent-uri"] = $message_id;
1257         $datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert('UTC','UTC',$created);
1258         $datarray["private"] = $private;
1259         $datarray["parent"] = 0;
1260         $datarray["plink"] = $plink;
1261         $datarray["owner-name"] = $contact["name"];
1262         $datarray["owner-link"] = $contact["url"];
1263         $datarray["owner-avatar"] = ((x($contact,'thumb')) ? $contact["thumb"] : $contact["photo"]);
1264               $prefix = share_header($person["name"], $person["url"], ((x($person,'thumb')) ? $person["thumb"] : $person["photo"]), $orig_guid, $orig_created, $orig_url);
1265
1266                 $datarray["author-name"] = $contact["name"];
1267                 $datarray["author-link"] = $contact["url"];
1268                 $datarray["author-avatar"] = $contact["thumb"];
1269                 $datarray["body"] = $prefix.$body."[/share]";
1270
1271         $datarray["object"] = json_encode($xml);
1272         $datarray["object-type"] = $objecttype;
1273
1274         $datarray["tag"] = $str_tags;
1275         $datarray["app"]  = $app;
1276
1277         // if empty content it might be a photo that hasn't arrived yet. If a photo arrives, we'll make it visible. (testing)
1278         $datarray["visible"] = ((strlen($body)) ? 1 : 0);
1279
1280         // Store the original item of a reshare
1281         if ($create_original_post) {
1282                 require_once("include/Contact.php");
1283
1284                 $datarray2 = $datarray;
1285
1286                 $datarray2["uid"] = 0;
1287                 $datarray2["contact-id"] = get_contact($person["url"], 0);
1288                 $datarray2["guid"] = $orig_guid;
1289                 $datarray2["uri"] = $datarray2["parent-uri"] = $orig_uri;
1290                 $datarray2["changed"] = $datarray2["created"] = $datarray2["edited"] = $datarray2["commented"] = $datarray2["received"] = datetime_convert('UTC','UTC',$orig_created);
1291                 $datarray2["parent"] = 0;
1292                 $datarray2["plink"] = $orig_plink;
1293
1294                 $datarray2["author-name"] = $person["name"];
1295                 $datarray2["author-link"] = $person["url"];
1296                 $datarray2["author-avatar"] = ((x($person,'thumb')) ? $person["thumb"] : $person["photo"]);
1297                 $datarray2["owner-name"] = $datarray2["author-name"];
1298                 $datarray2["owner-link"] = $datarray2["author-link"];
1299                 $datarray2["owner-avatar"] = $datarray2["author-avatar"];
1300                 $datarray2["body"] = $body;
1301                 $datarray2["object"] = $object;
1302
1303                 DiasporaFetchGuid($datarray2);
1304                 $message_id = item_store($datarray2);
1305
1306                 logger("Store original item ".$orig_guid." under message id ".$message_id);
1307         }
1308
1309         DiasporaFetchGuid($datarray);
1310         $message_id = item_store($datarray);
1311 */
1312                 return true;
1313         }
1314
1315         private function import_retraction($importer, $data) {
1316                 return true;
1317         }
1318
1319         private function import_status_message($importer, $data, $msg, $data2) {
1320
1321                 $raw_message = unxmlify($data->raw_message);
1322                 $guid = notags(unxmlify($data->guid));
1323                 $author = notags(unxmlify($data->author));
1324                 $public = notags(unxmlify($data->public));
1325                 $created_at = notags(unxmlify($data->created_at));
1326                 $provider_display_name = notags(unxmlify($data->provider_display_name));
1327
1328                 foreach ($data->children() AS $name => $entry)
1329                         if (count($entry->children()))
1330                                 if (!in_array($name, array("location", "photo", "poll")))
1331                                         die("Kinder: ".$name."\n");
1332 /*
1333                 if ($data->location) {
1334                         print_r($location);
1335                         foreach ($data->location->children() AS $fieldname => $data)
1336                                 echo $fieldname." - ".$data."\n";
1337                         die("Location!\n");
1338                 }
1339 */
1340 /*
1341                 if ($data->photo) {
1342                         print_r($data->photo);
1343                         foreach ($data->photo->children() AS $fieldname => $data)
1344                                 echo $fieldname." - ".$data."\n";
1345                         die("Photo!\n");
1346                 }
1347 */
1348
1349                 if ($data->poll) {
1350                         print_r($data2);
1351                         print_r($data);
1352                         die("poll!\n");
1353                 }
1354
1355
1356                 $contact = self::get_contact_by_handle($importer["uid"], $author);
1357                 if (!$contact) {
1358                         logger("A Contact for handle ".$author." and user ".$importer["uid"]." was not found");
1359                         return false;
1360                 }
1361
1362                 if (!self::post_allow($importer, $contact, false)) {
1363                         logger("Ignoring this author.");
1364                         return false;
1365                 }
1366 /*
1367                 $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
1368                         intval($importer["uid"]),
1369                         dbesc($guid)
1370                 );
1371                 if(count($r)) {
1372                         logger("message exists: ".$guid);
1373                         return false;
1374                 }
1375 */
1376                 $private = (($public == "false") ? 1 : 0);
1377
1378                 $body = diaspora2bb($raw_message);
1379
1380                 $datarray = array();
1381
1382                 if($data->photo->remote_photo_path AND $data->photo->remote_photo_name)
1383                         $datarray["object-type"] = ACTIVITY_OBJ_PHOTO;
1384                 else {
1385                         $datarray["object-type"] = ACTIVITY_OBJ_NOTE;
1386                         // Add OEmbed and other information to the body
1387                         if (!self::is_redmatrix($contact["url"]))
1388                                 $body = add_page_info_to_body($body, false, true);
1389                 }
1390
1391                 $str_tags = "";
1392
1393                 $cnt = preg_match_all("/@\[url=(.*?)\[\/url\]/ism", $body, $matches, PREG_SET_ORDER);
1394                 if($cnt) {
1395                         foreach($matches as $mtch) {
1396                                 if(strlen($str_tags))
1397                                         $str_tags .= ",";
1398                                 $str_tags .= "@[url=".$mtch[1]."[/url]";
1399                         }
1400                 }
1401                 $plink = self::plink($author, $guid);
1402
1403                 $datarray["uid"] = $importer["uid"];
1404                 $datarray["contact-id"] = $contact["id"];
1405                 $datarray["network"] = NETWORK_DIASPORA;
1406
1407                 $datarray["author-name"] = $contact["name"];
1408                 $datarray["author-link"] = $contact["url"];
1409                 $datarray["author-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
1410
1411                 $datarray["owner-name"] = $datarray["author-name"];
1412                 $datarray["owner-link"] = $datarray["author-link"];
1413                 $datarray["owner-avatar"] = $datarray["author-avatar"];
1414
1415                 $datarray["guid"] = $guid;
1416                 $datarray["uri"] = $datarray["parent-uri"] = $author.":".$guid;
1417
1418                 $datarray["verb"] = ACTIVITY_POST;
1419                 $datarray["gravity"] = GRAVITY_PARENT;
1420
1421                 $datarray["object"] = json_encode($data);
1422
1423                 $datarray["body"] = $body;
1424
1425                 $datarray["tag"] = $str_tags;
1426                 if ($provider_display_name != "")
1427                         $datarray["app"] = $provider_display_name;
1428
1429                 $datarray["plink"] = $plink;
1430                 $datarray["private"] = $private;
1431                 $datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert("UTC", "UTC", $created_at);
1432
1433                 // if empty content it might be a photo that hasn't arrived yet. If a photo arrives, we'll make it visible.
1434
1435                 $datarray["visible"] = ((strlen($body)) ? 1 : 0);
1436
1437                 self::fetch_guid($datarray);
1438                 //$message_id = item_store($datarray);
1439                 print_r($datarray);
1440
1441                 logger("Stored item with message id ".$message_id, LOGGER_DEBUG);
1442
1443                 return $message_id;
1444         }
1445 }
1446 ?>