Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3438 lines
112 KiB

11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
9 years ago
9 years ago
10 years ago
9 years ago
  1. <?php
  2. require_once('include/bbcode.php');
  3. require_once('include/oembed.php');
  4. require_once('include/salmon.php');
  5. require_once('include/crypto.php');
  6. function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0) {
  7. $sitefeed = ((strlen($owner_nick)) ? false : true); // not yet implemented, need to rewrite huge chunks of following logic
  8. $public_feed = (($dfrn_id) ? false : true);
  9. $starred = false; // not yet implemented, possible security issues
  10. $converse = false;
  11. if($public_feed && $a->argc > 2) {
  12. for($x = 2; $x < $a->argc; $x++) {
  13. if($a->argv[$x] == 'converse')
  14. $converse = true;
  15. if($a->argv[$x] == 'starred')
  16. $starred = true;
  17. if($a->argv[$x] === 'category' && $a->argc > ($x + 1) && strlen($a->argv[$x+1]))
  18. $category = $a->argv[$x+1];
  19. }
  20. }
  21. // default permissions - anonymous user
  22. $sql_extra = " AND `allow_cid` = '' AND `allow_gid` = '' AND `deny_cid` = '' AND `deny_gid` = '' ";
  23. $r = q("SELECT `contact`.*, `user`.`uid` AS `user_uid`, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags`
  24. FROM `contact` LEFT JOIN `user` ON `user`.`uid` = `contact`.`uid`
  25. WHERE `contact`.`self` = 1 AND `user`.`nickname` = '%s' LIMIT 1",
  26. dbesc($owner_nick)
  27. );
  28. if(! count($r))
  29. killme();
  30. $owner = $r[0];
  31. $owner_id = $owner['user_uid'];
  32. $owner_nick = $owner['nickname'];
  33. $birthday = feed_birthday($owner_id,$owner['timezone']);
  34. if(! $public_feed) {
  35. $sql_extra = '';
  36. switch($direction) {
  37. case (-1):
  38. $sql_extra = sprintf(" AND `issued-id` = '%s' ", dbesc($dfrn_id));
  39. $my_id = $dfrn_id;
  40. break;
  41. case 0:
  42. $sql_extra = sprintf(" AND `issued-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
  43. $my_id = '1:' . $dfrn_id;
  44. break;
  45. case 1:
  46. $sql_extra = sprintf(" AND `dfrn-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id));
  47. $my_id = '0:' . $dfrn_id;
  48. break;
  49. default:
  50. return false;
  51. break; // NOTREACHED
  52. }
  53. $r = q("SELECT * FROM `contact` WHERE `blocked` = 0 AND `pending` = 0 AND `contact`.`uid` = %d $sql_extra LIMIT 1",
  54. intval($owner_id)
  55. );
  56. if(! count($r))
  57. killme();
  58. $contact = $r[0];
  59. $groups = init_groups_visitor($contact['id']);
  60. if(count($groups)) {
  61. for($x = 0; $x < count($groups); $x ++)
  62. $groups[$x] = '<' . intval($groups[$x]) . '>' ;
  63. $gs = implode('|', $groups);
  64. }
  65. else
  66. $gs = '<<>>' ; // Impossible to match
  67. $sql_extra = sprintf("
  68. AND ( `allow_cid` = '' OR `allow_cid` REGEXP '<%d>' )
  69. AND ( `deny_cid` = '' OR NOT `deny_cid` REGEXP '<%d>' )
  70. AND ( `allow_gid` = '' OR `allow_gid` REGEXP '%s' )
  71. AND ( `deny_gid` = '' OR NOT `deny_gid` REGEXP '%s')
  72. ",
  73. intval($contact['id']),
  74. intval($contact['id']),
  75. dbesc($gs),
  76. dbesc($gs)
  77. );
  78. }
  79. if($public_feed)
  80. $sort = 'DESC';
  81. else
  82. $sort = 'ASC';
  83. if(! strlen($last_update))
  84. $last_update = 'now -30 days';
  85. if(isset($category)) {
  86. $sql_extra .= file_tag_file_query('item',$category,'category');
  87. }
  88. if($public_feed) {
  89. if(! $converse)
  90. $sql_extra .= " AND `contact`.`self` = 1 ";
  91. }
  92. $check_date = datetime_convert('UTC','UTC',$last_update,'Y-m-d H:i:s');
  93. $r = q("SELECT `item`.*, `item`.`id` AS `item_id`,
  94. `contact`.`name`, `contact`.`network`, `contact`.`photo`, `contact`.`url`,
  95. `contact`.`name-date`, `contact`.`uri-date`, `contact`.`avatar-date`,
  96. `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
  97. `contact`.`id` AS `contact-id`, `contact`.`uid` AS `contact-uid`,
  98. `sign`.`signed_text`, `sign`.`signature`, `sign`.`signer`
  99. FROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
  100. LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id`
  101. WHERE `item`.`uid` = %d AND `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`parent` != 0
  102. AND `item`.`wall` = 1 AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
  103. AND ( `item`.`edited` > '%s' OR `item`.`changed` > '%s' )
  104. $sql_extra
  105. ORDER BY `parent` %s, `created` ASC LIMIT 0, 300",
  106. intval($owner_id),
  107. dbesc($check_date),
  108. dbesc($check_date),
  109. dbesc($sort)
  110. );
  111. // Will check further below if this actually returned results.
  112. // We will provide an empty feed if that is the case.
  113. $items = $r;
  114. $feed_template = get_markup_template(($dfrn_id) ? 'atom_feed_dfrn.tpl' : 'atom_feed.tpl');
  115. $atom = '';
  116. $hubxml = feed_hublinks();
  117. $salmon = feed_salmonlinks($owner_nick);
  118. $atom .= replace_macros($feed_template, array(
  119. '$version' => xmlify(FRIENDICA_VERSION),
  120. '$feed_id' => xmlify($a->get_baseurl() . '/profile/' . $owner_nick),
  121. '$feed_title' => xmlify($owner['name']),
  122. '$feed_updated' => xmlify(datetime_convert('UTC', 'UTC', 'now' , ATOM_TIME)) ,
  123. '$hub' => $hubxml,
  124. '$salmon' => $salmon,
  125. '$name' => xmlify($owner['name']),
  126. '$profile_page' => xmlify($owner['url']),
  127. '$photo' => xmlify($owner['photo']),
  128. '$thumb' => xmlify($owner['thumb']),
  129. '$picdate' => xmlify(datetime_convert('UTC','UTC',$owner['avatar-date'] . '+00:00' , ATOM_TIME)) ,
  130. '$uridate' => xmlify(datetime_convert('UTC','UTC',$owner['uri-date'] . '+00:00' , ATOM_TIME)) ,
  131. '$namdate' => xmlify(datetime_convert('UTC','UTC',$owner['name-date'] . '+00:00' , ATOM_TIME)) ,
  132. '$birthday' => ((strlen($birthday)) ? '<dfrn:birthday>' . xmlify($birthday) . '</dfrn:birthday>' : ''),
  133. '$community' => (($owner['page-flags'] == PAGE_COMMUNITY) ? '<dfrn:community>1</dfrn:community>' : '')
  134. ));
  135. call_hooks('atom_feed', $atom);
  136. if(! count($items)) {
  137. call_hooks('atom_feed_end', $atom);
  138. $atom .= '</feed>' . "\r\n";
  139. return $atom;
  140. }
  141. foreach($items as $item) {
  142. // prevent private email from leaking.
  143. if($item['network'] === NETWORK_MAIL)
  144. continue;
  145. // public feeds get html, our own nodes use bbcode
  146. if($public_feed) {
  147. $type = 'html';
  148. // catch any email that's in a public conversation and make sure it doesn't leak
  149. if($item['private'])
  150. continue;
  151. }
  152. else {
  153. $type = 'text';
  154. }
  155. $atom .= atom_entry($item,$type,null,$owner,true);
  156. }
  157. call_hooks('atom_feed_end', $atom);
  158. $atom .= '</feed>' . "\r\n";
  159. return $atom;
  160. }
  161. function construct_verb($item) {
  162. if($item['verb'])
  163. return $item['verb'];
  164. return ACTIVITY_POST;
  165. }
  166. function construct_activity_object($item) {
  167. if($item['object']) {
  168. $o = '<as:object>' . "\r\n";
  169. $r = parse_xml_string($item['object'],false);
  170. if(! $r)
  171. return '';
  172. if($r->type)
  173. $o .= '<as:object-type>' . xmlify($r->type) . '</as:object-type>' . "\r\n";
  174. if($r->id)
  175. $o .= '<id>' . xmlify($r->id) . '</id>' . "\r\n";
  176. if($r->title)
  177. $o .= '<title>' . xmlify($r->title) . '</title>' . "\r\n";
  178. if($r->link) {
  179. if(substr($r->link,0,1) === '<') {
  180. // patch up some facebook "like" activity objects that got stored incorrectly
  181. // for a couple of months prior to 9-Jun-2011 and generated bad XML.
  182. // we can probably remove this hack here and in the following function in a few months time.
  183. if(strstr($r->link,'&') && (! strstr($r->link,'&amp;')))
  184. $r->link = str_replace('&','&amp;', $r->link);
  185. $r->link = preg_replace('/\<link(.*?)\"\>/','<link$1"/>',$r->link);
  186. $o .= $r->link;
  187. }
  188. else
  189. $o .= '<link rel="alternate" type="text/html" href="' . xmlify($r->link) . '" />' . "\r\n";
  190. }
  191. if($r->content)
  192. $o .= '<content type="html" >' . xmlify(bbcode($r->content)) . '</content>' . "\r\n";
  193. $o .= '</as:object>' . "\r\n";
  194. return $o;
  195. }
  196. return '';
  197. }
  198. function construct_activity_target($item) {
  199. if($item['target']) {
  200. $o = '<as:target>' . "\r\n";
  201. $r = parse_xml_string($item['target'],false);
  202. if(! $r)
  203. return '';
  204. if($r->type)
  205. $o .= '<as:object-type>' . xmlify($r->type) . '</as:object-type>' . "\r\n";
  206. if($r->id)
  207. $o .= '<id>' . xmlify($r->id) . '</id>' . "\r\n";
  208. if($r->title)
  209. $o .= '<title>' . xmlify($r->title) . '</title>' . "\r\n";
  210. if($r->link) {
  211. if(substr($r->link,0,1) === '<') {
  212. if(strstr($r->link,'&') && (! strstr($r->link,'&amp;')))
  213. $r->link = str_replace('&','&amp;', $r->link);
  214. $r->link = preg_replace('/\<link(.*?)\"\>/','<link$1"/>',$r->link);
  215. $o .= $r->link;
  216. }
  217. else
  218. $o .= '<link rel="alternate" type="text/html" href="' . xmlify($r->link) . '" />' . "\r\n";
  219. }
  220. if($r->content)
  221. $o .= '<content type="html" >' . xmlify(bbcode($r->content)) . '</content>' . "\r\n";
  222. $o .= '</as:target>' . "\r\n";
  223. return $o;
  224. }
  225. return '';
  226. }
  227. function get_atom_elements($feed,$item) {
  228. require_once('library/HTMLPurifier.auto.php');
  229. require_once('include/html2bbcode.php');
  230. $best_photo = array();
  231. $res = array();
  232. $author = $item->get_author();
  233. if($author) {
  234. $res['author-name'] = unxmlify($author->get_name());
  235. $res['author-link'] = unxmlify($author->get_link());
  236. }
  237. else {
  238. $res['author-name'] = unxmlify($feed->get_title());
  239. $res['author-link'] = unxmlify($feed->get_permalink());
  240. }
  241. $res['uri'] = unxmlify($item->get_id());
  242. $res['title'] = unxmlify($item->get_title());
  243. $res['body'] = unxmlify($item->get_content());
  244. $res['plink'] = unxmlify($item->get_link(0));
  245. if($res['plink'])
  246. $base_url = implode('/', array_slice(explode('/',$res['plink']),0,3));
  247. else
  248. $base_url = '';
  249. // look for a photo. We should check media size and find the best one,
  250. // but for now let's just find any author photo
  251. $rawauthor = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
  252. if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
  253. $base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
  254. foreach($base as $link) {
  255. if(!x($res, 'author-avatar') || !$res['author-avatar']) {
  256. if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
  257. $res['author-avatar'] = unxmlify($link['attribs']['']['href']);
  258. }
  259. }
  260. }
  261. $rawactor = $item->get_item_tags(NAMESPACE_ACTIVITY, 'actor');
  262. if($rawactor && activity_match($rawactor[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data'],ACTIVITY_OBJ_PERSON)) {
  263. $base = $rawactor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
  264. if($base && count($base)) {
  265. foreach($base as $link) {
  266. if($link['attribs']['']['rel'] === 'alternate' && (! $res['author-link']))
  267. $res['author-link'] = unxmlify($link['attribs']['']['href']);
  268. if