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.
 
 
 
 
 
 

333 lines
8.7 KiB

  1. <?php
  2. $debugging = false;
  3. require_once("boot.php");
  4. $a = new App;
  5. @include(".htconfig.php");
  6. require_once("dba.php");
  7. $db = new dba($db_host, $db_user, $db_pass, $db_data, $install);
  8. unset($db_host, $db_user, $db_pass, $db_data);
  9. require_once("session.php");
  10. require_once("datetime.php");
  11. if($argc < 2)
  12. exit;
  13. $a->set_baseurl(get_config('system',url'));
  14. $baseurl = $argv[1];
  15. $a->set_baseurl($argv[1]);
  16. $cmd = $argv[1];
  17. switch($cmd) {
  18. case 'mail':
  19. default:
  20. $item_id = intval($argv[2]);
  21. if(! $item_id)
  22. killme();
  23. break;
  24. }
  25. $recipients = array();
  26. if($cmd == 'mail') {
  27. $message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1",
  28. intval($item_id)
  29. );
  30. if(! count($message))
  31. killme();
  32. $uid = $message[0]['uid'];
  33. $recipients[] = $message[0]['contact-id'];
  34. $item = $message[0];
  35. }
  36. else {
  37. // find ancestors
  38. $r = q("SELECT `parent`, `uid`, `edited` FROM `item` WHERE `id` = %d LIMIT 1",
  39. intval($item_id)
  40. );
  41. if(! count($r))
  42. killme();
  43. $parent = $r[0]['parent'];
  44. $uid = $r[0]['uid'];
  45. $updated = $r[0]['edited'];
  46. $items = q("SELECT * FROM `item` WHERE `parent` = %d ORDER BY `id` ASC",
  47. intval($parent)
  48. );
  49. if(! count($items))
  50. killme();
  51. }
  52. $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1",
  53. intval($uid)
  54. );
  55. if(count($r))
  56. $owner = $r[0];
  57. else
  58. killme();
  59. if($cmd != 'mail') {
  60. require_once('include/group.php');
  61. $parent = $items[0];
  62. if($parent['type'] == 'remote') {
  63. // local followup to remote post
  64. $followup = true;
  65. $conversant_str = dbesc($parent['contact-id']);
  66. }
  67. else {
  68. $followup = false;
  69. $allow_people = expand_acl($parent['allow_cid']);
  70. $allow_groups = expand_groups(expand_acl($parent['allow_gid']));
  71. $deny_people = expand_acl($parent['deny_cid']);
  72. $deny_groups = expand_groups(expand_acl($parent['deny_gid']));
  73. $conversants = array();
  74. foreach($items as $item) {
  75. $recipients[] = $item['contact-id'];
  76. $conversants[] = $item['contact-id'];
  77. }
  78. $conversants = array_unique($conversants,SORT_NUMERIC);
  79. $recipients = array_unique(array_merge($recipients,$allow_people,$allow_groups),SORT_NUMERIC);
  80. $deny = array_unique(array_merge($deny_people,$deny_groups),SORT_NUMERIC);
  81. $recipients = array_diff($recipients,$deny);
  82. $conversant_str = dbesc(implode(', ',$conversants));
  83. }
  84. $r = q("SELECT * FROM `contact` WHERE `id` IN ( $conversant_str ) AND `blocked` = 0 AND `pending` = 0");
  85. if( ! count($r))
  86. killme();
  87. $contacts = $r;
  88. $tomb_template = file_get_contents('view/atom_tomb.tpl');
  89. $item_template = file_get_contents('view/atom_item.tpl');
  90. $cmnt_template = file_get_contents('view/atom_cmnt.tpl');
  91. }
  92. $feed_template = file_get_contents('view/atom_feed.tpl');
  93. $mail_template = file_get_contents('view/atom_mail.tpl');
  94. $atom = '';
  95. $atom .= replace_macros($feed_template, array(
  96. '$feed_id' => xmlify($a->get_baseurl()),
  97. '$feed_title' => xmlify($owner['name']),
  98. '$feed_updated' => xmlify(datetime_convert('UTC', 'UTC',
  99. $updated . '+00:00' , 'Y-m-d\TH:i:s\Z')) ,
  100. '$name' => xmlify($owner['name']),
  101. '$profile_page' => xmlify($owner['url']),
  102. '$photo' => xmlify($owner['photo']),
  103. '$thumb' => xmlify($owner['thumb']),
  104. '$picdate' => xmlify(datetime_convert('UTC','UTC',$owner['avatar-date'] . '+00:00' , 'Y-m-d\TH:i:s\Z')) ,
  105. '$uridate' => xmlify(datetime_convert('UTC','UTC',$owner['uri-date'] . '+00:00' , 'Y-m-d\TH:i:s\Z')) ,
  106. '$namdate' => xmlify(datetime_convert('UTC','UTC',$owner['name-date'] . '+00:00' , 'Y-m-d\TH:i:s\Z'))
  107. ));
  108. if($cmd == 'mail') {
  109. $atom .= replace_macros($mail_template, array(
  110. '$name' => xmlify($owner['name']),
  111. '$profile_page' => xmlify($owner['url']),
  112. '$thumb' => xmlify($owner['thumb']),
  113. '$item_id' => xmlify($item['uri']),
  114. '$subject' => xmlify($item['title']),
  115. '$created' => xmlify(datetime_convert('UTC', 'UTC',
  116. $item['created'] . '+00:00' , 'Y-m-d\TH:i:s\Z')),
  117. '$content' =>xmlify($item['body']),
  118. '$parent_id' => xmlify($item['parent-uri'])
  119. ));
  120. }
  121. else {
  122. if($followup) {
  123. foreach($items as $item) {
  124. if($item['id'] == $item_id) {
  125. $atom .= replace_macros($cmnt_template, array(
  126. '$name' => xmlify($owner['name']),
  127. '$profile_page' => xmlify($owner['url']),
  128. '$thumb' => xmlify($owner['thumb']),
  129. '$item_id' => xmlify($item['uri']),
  130. '$title' => xmlify($item['title']),
  131. '$published' => xmlify(datetime_convert('UTC', 'UTC',
  132. $item['created'] . '+00:00' , 'Y-m-d\TH:i:s\Z')),
  133. '$updated' => xmlify(datetime_convert('UTC', 'UTC',
  134. $item['edited'] . '+00:00' , 'Y-m-d\TH:i:s\Z')),
  135. '$content' =>xmlify($item['body']),
  136. '$parent_id' => xmlify($item['parent-uri']),
  137. '$comment_allow' => 0
  138. ));
  139. }
  140. }
  141. }
  142. else {
  143. foreach($items as $item) {
  144. if($item['deleted']) {
  145. $atom .= replace_macros($tomb_template, array(
  146. '$id' => xmlify($item['uri']),
  147. '$updated' => xmlify(datetime_convert('UTC', 'UTC',
  148. $item['edited'] . '+00:00' , 'Y-m-d\TH:i:s\Z'))
  149. ));
  150. }
  151. else {
  152. foreach($contacts as $contact) {
  153. if($item['contact-id'] == $contact['id']) {
  154. if($item['parent'] == $item['id']) {
  155. $atom .= replace_macros($item_template, array(
  156. '$name' => xmlify($contact['name']),
  157. '$profile_page' => xmlify($contact['url']),
  158. '$thumb' => xmlify($contact['thumb']),
  159. '$owner_name' => xmlify($item['owner-name']),
  160. '$owner_profile_page' => xmlify($item['owner-link']),
  161. '$owner_thumb' => xmlify($item['owner-avatar']),
  162. '$item_id' => xmlify($item['uri']),
  163. '$title' => xmlify($item['title']),
  164. '$published' => xmlify(datetime_convert('UTC', 'UTC',
  165. $item['created'] . '+00:00' , 'Y-m-d\TH:i:s\Z')),
  166. '$updated' => xmlify(datetime_convert('UTC', 'UTC',
  167. $item['edited'] . '+00:00' , 'Y-m-d\TH:i:s\Z')),
  168. '$content' =>xmlify($item['body']),
  169. '$comment_allow' => (($item['last-child'] && strlen($contact['dfrn-id'])) ? 1 : 0)
  170. ));
  171. }
  172. else {
  173. $atom .= replace_macros($cmnt_template, array(
  174. '$name' => xmlify($contact['name']),
  175. '$profile_page' => xmlify($contact['url']),
  176. '$thumb' => xmlify($contact['thumb']),
  177. '$item_id' => xmlify($item['uri']),
  178. '$title' => xmlify($item['title']),
  179. '$published' => xmlify(datetime_convert('UTC', 'UTC',
  180. $item['created'] . '+00:00' , 'Y-m-d\TH:i:s\Z')),
  181. '$updated' => xmlify(datetime_convert('UTC', 'UTC',
  182. $item['edited'] . '+00:00' , 'Y-m-d\TH:i:s\Z')),
  183. '$content' =>xmlify($item['body']),
  184. '$parent_id' => xmlify($item['parent-uri']),
  185. '$comment_allow' => (($item['last-child']) ? 1 : 0)
  186. ));
  187. }
  188. }
  189. }
  190. }
  191. }
  192. }
  193. }
  194. $atom .= "</feed>\r\n";
  195. if($debugging)
  196. echo $atom;
  197. // create a clone of this feed but with comments disabled to send to those who can't respond.
  198. $atom_nowrite = str_replace('<dfrn:comment-allow>1','<dfrn:comment-allow>0',$atom);
  199. if($followup)
  200. $recip_str = $parent['contact-id'];
  201. else
  202. $recip_str = implode(', ', $recipients);
  203. $r = q("SELECT * FROM `contact` WHERE `id` IN ( %s ) ",
  204. dbesc($recip_str)
  205. );
  206. if(! count($r))
  207. killme();
  208. // delivery loop
  209. foreach($r as $rr) {
  210. if($rr['self'])
  211. continue;
  212. if(! strlen($rr['dfrn-id']))
  213. continue;
  214. $url = $rr['notify'] . '?dfrn_id=' . $rr['dfrn-id'];
  215. $xml = fetch_url($url);
  216. if($debugging)
  217. echo $xml;
  218. if(! $xml)
  219. continue;
  220. $res = simplexml_load_string($xml);
  221. if((intval($res->status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id)))
  222. continue;
  223. $postvars = array();
  224. $sent_dfrn_id = hex2bin($res->dfrn_id);
  225. $final_dfrn_id = '';
  226. openssl_public_decrypt($sent_dfrn_id,$final_dfrn_id,$rr['pubkey']);
  227. $final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.'));
  228. if($final_dfrn_id != $rr['dfrn-id']) {
  229. // did not decode properly - cannot trust this site
  230. continue;
  231. }
  232. $postvars['dfrn_id'] = $rr['dfrn-id'];
  233. $challenge = hex2bin($res->challenge);
  234. openssl_public_decrypt($challenge,$postvars['challenge'],$rr['pubkey']);
  235. if($cmd == 'mail') {
  236. $postvars['data'] = $atom;
  237. }
  238. elseif(strlen($rr['dfrn-id']) && (! ($rr['blocked']) || ($rr['readonly']))) {
  239. $postvars['data'] = $atom;
  240. }
  241. else {
  242. $postvars['data'] = $atom_nowrite;
  243. }
  244. $xml = post_url($rr['notify'],$postvars);
  245. if($debugging)
  246. echo $xml;
  247. $res = simplexml_load_string($xml);
  248. // Currently there is no retry attempt for failed mail delivery.
  249. // We need to handle this in the UI, report the non-deliverables and try again
  250. if(($cmd == 'mail') && (intval($res->status) == 0)) {
  251. $r = q("UPDATE `mail` SET `delivered` = 1 WHERE `id` = %d LIMIT 1",
  252. intval($item_id)
  253. );
  254. }
  255. }
  256. killme();