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.
 
 
 
 
 
 

1284 lines
40 KiB

  1. <?php
  2. /**
  3. *
  4. * This is the POST destination for most all locally posted
  5. * text stuff. This function handles status, wall-to-wall status,
  6. * local comments, and remote coments that are posted on this site
  7. * (as opposed to being delivered in a feed).
  8. * Also processed here are posts and comments coming through the
  9. * statusnet/twitter API.
  10. * All of these become an "item" which is our basic unit of
  11. * information.
  12. * Posts that originate externally or do not fall into the above
  13. * posting categories go through item_store() instead of this function.
  14. *
  15. */
  16. require_once('include/crypto.php');
  17. require_once('include/enotify.php');
  18. require_once('include/email.php');
  19. require_once('include/tags.php');
  20. require_once('include/files.php');
  21. require_once('include/threads.php');
  22. require_once('include/text.php');
  23. require_once('include/items.php');
  24. require_once('include/Scrape.php');
  25. function item_post(&$a) {
  26. if((! local_user()) && (! remote_user()) && (! x($_REQUEST,'commenter')))
  27. return;
  28. require_once('include/security.php');
  29. $uid = local_user();
  30. if(x($_REQUEST,'dropitems')) {
  31. $arr_drop = explode(',',$_REQUEST['dropitems']);
  32. drop_items($arr_drop);
  33. $json = array('success' => 1);
  34. echo json_encode($json);
  35. killme();
  36. }
  37. call_hooks('post_local_start', $_REQUEST);
  38. // logger('postinput ' . file_get_contents('php://input'));
  39. logger('postvars ' . print_r($_REQUEST,true), LOGGER_DATA);
  40. $api_source = ((x($_REQUEST,'api_source') && $_REQUEST['api_source']) ? true : false);
  41. $message_id = ((x($_REQUEST,'message_id') && $api_source) ? strip_tags($_REQUEST['message_id']) : '');
  42. $return_path = ((x($_REQUEST,'return')) ? $_REQUEST['return'] : '');
  43. $preview = ((x($_REQUEST,'preview')) ? intval($_REQUEST['preview']) : 0);
  44. // Check for doubly-submitted posts, and reject duplicates
  45. // Note that we have to ignore previews, otherwise nothing will post
  46. // after it's been previewed
  47. if(!$preview && x($_REQUEST['post_id_random'])) {
  48. if(x($_SESSION['post-random']) && $_SESSION['post-random'] == $_REQUEST['post_id_random']) {
  49. logger("item post: duplicate post", LOGGER_DEBUG);
  50. item_post_return($a->get_baseurl(), $api_source, $return_path);
  51. }
  52. else
  53. $_SESSION['post-random'] = $_REQUEST['post_id_random'];
  54. }
  55. /**
  56. * Is this a reply to something?
  57. */
  58. $parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0);
  59. $parent_uri = ((x($_REQUEST,'parent_uri')) ? trim($_REQUEST['parent_uri']) : '');
  60. $parent_item = null;
  61. $parent_contact = null;
  62. $thr_parent = '';
  63. $parid = 0;
  64. $r = false;
  65. $objecttype = null;
  66. if($parent || $parent_uri) {
  67. $objecttype = ACTIVITY_OBJ_COMMENT;
  68. if(! x($_REQUEST,'type'))
  69. $_REQUEST['type'] = 'net-comment';
  70. if($parent) {
  71. $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1",
  72. intval($parent)
  73. );
  74. } elseif($parent_uri && local_user()) {
  75. // This is coming from an API source, and we are logged in
  76. $r = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
  77. dbesc($parent_uri),
  78. intval(local_user())
  79. );
  80. }
  81. // if this isn't the real parent of the conversation, find it
  82. if($r !== false && count($r)) {
  83. $parid = $r[0]['parent'];
  84. $parent_uri = $r[0]['uri'];
  85. if($r[0]['id'] != $r[0]['parent']) {
  86. $r = q("SELECT * FROM `item` WHERE `id` = `parent` AND `parent` = %d LIMIT 1",
  87. intval($parid)
  88. );
  89. }
  90. }
  91. if(($r === false) || (! count($r))) {
  92. notice( t('Unable to locate original post.') . EOL);
  93. if(x($_REQUEST,'return'))
  94. goaway($a->get_baseurl() . "/" . $return_path );
  95. killme();
  96. }
  97. $parent_item = $r[0];
  98. $parent = $r[0]['id'];
  99. // multi-level threading - preserve the info but re-parent to our single level threading
  100. //if(($parid) && ($parid != $parent))
  101. $thr_parent = $parent_uri;
  102. if($parent_item['contact-id'] && $uid) {
  103. $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
  104. intval($parent_item['contact-id']),
  105. intval($uid)
  106. );
  107. if(count($r))
  108. $parent_contact = $r[0];
  109. // If the contact id doesn't fit with the contact, then set the contact to null
  110. $thrparent = q("SELECT `author-link`, `network` FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($thr_parent));
  111. if (count($thrparent) AND ($thrparent[0]["network"] === NETWORK_OSTATUS)
  112. AND (normalise_link($parent_contact["url"]) != normalise_link($thrparent[0]["author-link"]))) {
  113. $parent_contact = null;
  114. require_once("include/Scrape.php");
  115. $probed_contact = probe_url($thrparent[0]["author-link"]);
  116. if ($probed_contact["network"] != NETWORK_FEED) {
  117. $parent_contact = $probed_contact;
  118. $parent_contact["nurl"] = normalise_link($probed_contact["url"]);
  119. $parent_contact["thumb"] = $probed_contact["photo"];
  120. $parent_contact["micro"] = $probed_contact["photo"];
  121. $parent_contact["addr"] = $probed_contact["addr"];
  122. }
  123. logger('no contact found: '.print_r($thrparent, true), LOGGER_DEBUG);
  124. } else
  125. logger('parent contact: '.print_r($parent_contact, true), LOGGER_DEBUG);
  126. }
  127. }
  128. if($parent) logger('mod_item: item_post parent=' . $parent);
  129. $profile_uid = ((x($_REQUEST,'profile_uid')) ? intval($_REQUEST['profile_uid']) : 0);
  130. $post_id = ((x($_REQUEST,'post_id')) ? intval($_REQUEST['post_id']) : 0);
  131. $app = ((x($_REQUEST,'source')) ? strip_tags($_REQUEST['source']) : '');
  132. $extid = ((x($_REQUEST,'extid')) ? strip_tags($_REQUEST['extid']) : '');
  133. $allow_moderated = false;
  134. // here is where we are going to check for permission to post a moderated comment.
  135. // First check that the parent exists and it is a wall item.
  136. if((x($_REQUEST,'commenter')) && ((! $parent) || (! $parent_item['wall']))) {
  137. notice( t('Permission denied.') . EOL) ;
  138. if(x($_REQUEST,'return'))
  139. goaway($a->get_baseurl() . "/" . $return_path );
  140. killme();
  141. }
  142. // Now check that it is a page_type of PAGE_BLOG, and that valid personal details
  143. // have been provided, and run any anti-spam plugins
  144. // TODO
  145. if((! can_write_wall($a,$profile_uid)) && (! $allow_moderated)) {
  146. notice( t('Permission denied.') . EOL) ;
  147. if(x($_REQUEST,'return'))
  148. goaway($a->get_baseurl() . "/" . $return_path );
  149. killme();
  150. }
  151. // is this an edited post?
  152. $orig_post = null;
  153. if($post_id) {
  154. $i = q("SELECT * FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1",
  155. intval($profile_uid),
  156. intval($post_id)
  157. );
  158. if(! count($i))
  159. killme();
  160. $orig_post = $i[0];
  161. }
  162. $user = null;
  163. $r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1",
  164. intval($profile_uid)
  165. );
  166. if(count($r))
  167. $user = $r[0];
  168. if($orig_post) {
  169. $str_group_allow = $orig_post['allow_gid'];
  170. $str_contact_allow = $orig_post['allow_cid'];
  171. $str_group_deny = $orig_post['deny_gid'];
  172. $str_contact_deny = $orig_post['deny_cid'];
  173. $location = $orig_post['location'];
  174. $coord = $orig_post['coord'];
  175. $verb = $orig_post['verb'];
  176. $objecttype = $orig_post['object-type'];
  177. $emailcc = $orig_post['emailcc'];
  178. $app = $orig_post['app'];
  179. $categories = $orig_post['file'];
  180. $title = notags(trim($_REQUEST['title']));
  181. $body = escape_tags(trim($_REQUEST['body']));
  182. $private = $orig_post['private'];
  183. $pubmail_enable = $orig_post['pubmail'];
  184. $network = $orig_post['network'];
  185. $guid = $orig_post['guid'];
  186. $extid = $orig_post['extid'];
  187. } else {
  188. // if coming from the API and no privacy settings are set,
  189. // use the user default permissions - as they won't have
  190. // been supplied via a form.
  191. if(($api_source)
  192. && (! array_key_exists('contact_allow',$_REQUEST))
  193. && (! array_key_exists('group_allow',$_REQUEST))
  194. && (! array_key_exists('contact_deny',$_REQUEST))
  195. && (! array_key_exists('group_deny',$_REQUEST))) {
  196. $str_group_allow = $user['allow_gid'];
  197. $str_contact_allow = $user['allow_cid'];
  198. $str_group_deny = $user['deny_gid'];
  199. $str_contact_deny = $user['deny_cid'];
  200. }
  201. else {
  202. // use the posted permissions
  203. $str_group_allow = perms2str($_REQUEST['group_allow']);
  204. $str_contact_allow = perms2str($_REQUEST['contact_allow']);
  205. $str_group_deny = perms2str($_REQUEST['group_deny']);
  206. $str_contact_deny = perms2str($_REQUEST['contact_deny']);
  207. }
  208. $title = notags(trim($_REQUEST['title']));
  209. $location = notags(trim($_REQUEST['location']));
  210. $coord = notags(trim($_REQUEST['coord']));
  211. $verb = notags(trim($_REQUEST['verb']));
  212. $emailcc = notags(trim($_REQUEST['emailcc']));
  213. $body = escape_tags(trim($_REQUEST['body']));
  214. $network = notags(trim($_REQUEST['network']));
  215. $guid = get_guid(32);
  216. item_add_language_opt($_REQUEST);
  217. $postopts = $_REQUEST['postopts'] ? $_REQUEST['postopts'] : "";
  218. $private = ((strlen($str_group_allow) || strlen($str_contact_allow) || strlen($str_group_deny) || strlen($str_contact_deny)) ? 1 : 0);
  219. if($user['hidewall'])
  220. $private = 2;
  221. // If this is a comment, set the permissions from the parent.
  222. if($parent_item) {
  223. $private = 0;
  224. // for non native networks use the network of the original post as network of the item
  225. if (($parent_item['network'] != NETWORK_DIASPORA)
  226. AND ($parent_item['network'] != NETWORK_OSTATUS)
  227. AND ($network == ""))
  228. $network = $parent_item['network'];
  229. if(($parent_item['private'])
  230. || strlen($parent_item['allow_cid'])
  231. || strlen($parent_item['allow_gid'])
  232. || strlen($parent_item['deny_cid'])
  233. || strlen($parent_item['deny_gid'])) {
  234. $private = (($parent_item['private']) ? $parent_item['private'] : 1);
  235. }
  236. $str_contact_allow = $parent_item['allow_cid'];
  237. $str_group_allow = $parent_item['allow_gid'];
  238. $str_contact_deny = $parent_item['deny_cid'];
  239. $str_group_deny = $parent_item['deny_gid'];
  240. }
  241. $pubmail_enable = ((x($_REQUEST,'pubmail_enable') && intval($_REQUEST['pubmail_enable']) && (! $private)) ? 1 : 0);
  242. // if using the API, we won't see pubmail_enable - figure out if it should be set
  243. if($api_source && $profile_uid && $profile_uid == local_user() && (! $private)) {
  244. $mail_disabled = ((function_exists('imap_open') && (! get_config('system','imap_disabled'))) ? 0 : 1);
  245. if(! $mail_disabled) {
  246. $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1",
  247. intval(local_user())
  248. );
  249. if(count($r) && intval($r[0]['pubmail']))
  250. $pubmail_enabled = true;
  251. }
  252. }
  253. if(! strlen($body)) {
  254. if($preview)
  255. killme();
  256. info( t('Empty post discarded.') . EOL );
  257. if(x($_REQUEST,'return'))
  258. goaway($a->get_baseurl() . "/" . $return_path );
  259. killme();
  260. }
  261. }
  262. if(strlen($categories)) {
  263. // get the "fileas" tags for this post
  264. $filedas = file_tag_file_to_list($categories, 'file');
  265. }
  266. // save old and new categories, so we can determine what needs to be deleted from pconfig
  267. $categories_old = $categories;
  268. $categories = file_tag_list_to_file(trim($_REQUEST['category']), 'category');
  269. $categories_new = $categories;
  270. if(strlen($filedas)) {
  271. // append the fileas stuff to the new categories list
  272. $categories .= file_tag_list_to_file($filedas, 'file');
  273. }
  274. // Work around doubled linefeeds in Tinymce 3.5b2
  275. // First figure out if it's a status post that would've been
  276. // created using tinymce. Otherwise leave it alone.
  277. /* $plaintext = (local_user() ? intval(get_pconfig(local_user(),'system','plaintext')) || !feature_enabled($profile_uid,'richtext') : 0);
  278. if((! $parent) && (! $api_source) && (! $plaintext)) {
  279. $body = fix_mce_lf($body);
  280. }*/
  281. $plaintext = (local_user() ? !feature_enabled($profile_uid,'richtext') : 0);
  282. if((! $parent) && (! $api_source) && (! $plaintext)) {
  283. $body = fix_mce_lf($body);
  284. }
  285. // get contact info for poster
  286. $author = null;
  287. $self = false;
  288. $contact_id = 0;
  289. if((local_user()) && (local_user() == $profile_uid)) {
  290. $self = true;
  291. $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1",
  292. intval($_SESSION['uid']));
  293. }
  294. elseif(remote_user()) {
  295. if(is_array($_SESSION['remote'])) {
  296. foreach($_SESSION['remote'] as $v) {
  297. if($v['uid'] == $profile_uid) {
  298. $contact_id = $v['cid'];
  299. break;
  300. }
  301. }
  302. }
  303. if($contact_id) {
  304. $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1",
  305. intval($contact_id)
  306. );
  307. }
  308. }
  309. if(count($r)) {
  310. $author = $r[0];
  311. $contact_id = $author['id'];
  312. }
  313. // get contact info for owner
  314. if($profile_uid == local_user()) {
  315. $contact_record = $author;
  316. }
  317. else {
  318. $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1",
  319. intval($profile_uid)
  320. );
  321. if(count($r))
  322. $contact_record = $r[0];
  323. }
  324. $post_type = notags(trim($_REQUEST['type']));
  325. if($post_type === 'net-comment') {
  326. if($parent_item !== null) {
  327. if($parent_item['wall'] == 1)
  328. $post_type = 'wall-comment';
  329. else
  330. $post_type = 'remote-comment';
  331. }
  332. }
  333. /**
  334. *
  335. * When a photo was uploaded into the message using the (profile wall) ajax
  336. * uploader, The permissions are initially set to disallow anybody but the
  337. * owner from seeing it. This is because the permissions may not yet have been
  338. * set for the post. If it's private, the photo permissions should be set
  339. * appropriately. But we didn't know the final permissions on the post until
  340. * now. So now we'll look for links of uploaded messages that are in the
  341. * post and set them to the same permissions as the post itself.
  342. *
  343. */
  344. $match = null;
  345. if((! $preview) && preg_match_all("/\[img([\=0-9x]*?)\](.*?)\[\/img\]/",$body,$match)) {
  346. $images = $match[2];
  347. if(count($images)) {
  348. $objecttype = ACTIVITY_OBJ_IMAGE;
  349. foreach($images as $image) {
  350. if(! stristr($image,$a->get_baseurl() . '/photo/'))
  351. continue;
  352. $image_uri = substr($image,strrpos($image,'/') + 1);
  353. $image_uri = substr($image_uri,0, strpos($image_uri,'-'));
  354. if(! strlen($image_uri))
  355. continue;
  356. $srch = '<' . intval($contact_id) . '>';
  357. $r = q("SELECT `id` FROM `photo` WHERE `allow_cid` = '%s' AND `allow_gid` = '' AND `deny_cid` = '' AND `deny_gid` = ''
  358. AND `resource-id` = '%s' AND `uid` = %d LIMIT 1",
  359. dbesc($srch),
  360. dbesc($image_uri),
  361. intval($profile_uid)
  362. );
  363. if(! count($r))
  364. continue;
  365. $r = q("UPDATE `photo` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s'
  366. WHERE `resource-id` = '%s' AND `uid` = %d AND `album` = '%s' ",
  367. dbesc($str_contact_allow),
  368. dbesc($str_group_allow),
  369. dbesc($str_contact_deny),
  370. dbesc($str_group_deny),
  371. dbesc($image_uri),
  372. intval($profile_uid),
  373. dbesc( t('Wall Photos'))
  374. );
  375. }
  376. }
  377. }
  378. /**
  379. * Next link in any attachment references we find in the post.
  380. */
  381. $match = false;
  382. if((! $preview) && preg_match_all("/\[attachment\](.*?)\[\/attachment\]/",$body,$match)) {
  383. $attaches = $match[1];
  384. if(count($attaches)) {
  385. foreach($attaches as $attach) {
  386. $r = q("SELECT * FROM `attach` WHERE `uid` = %d AND `id` = %d LIMIT 1",
  387. intval($profile_uid),
  388. intval($attach)
  389. );
  390. if(count($r)) {
  391. $r = q("UPDATE `attach` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s'
  392. WHERE `uid` = %d AND `id` = %d",
  393. dbesc($str_contact_allow),
  394. dbesc($str_group_allow),
  395. dbesc($str_contact_deny),
  396. dbesc($str_group_deny),
  397. intval($profile_uid),
  398. intval($attach)
  399. );
  400. }
  401. }
  402. }
  403. }
  404. // embedded bookmark in post? set bookmark flag
  405. $bookmark = 0;
  406. if(preg_match_all("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism",$body,$match,PREG_SET_ORDER)) {
  407. $objecttype = ACTIVITY_OBJ_BOOKMARK;
  408. $bookmark = 1;
  409. }
  410. $body = bb_translate_video($body);
  411. /**
  412. * Fold multi-line [code] sequences
  413. */
  414. $body = preg_replace('/\[\/code\]\s*\[code\]/ism',"\n",$body);
  415. $body = scale_external_images($body,false);
  416. // Setting the object type if not defined before
  417. if (!$objecttype) {
  418. $objecttype = ACTIVITY_OBJ_NOTE; // Default value
  419. require_once("include/plaintext.php");
  420. $objectdata = get_attached_data($body);
  421. if ($post["type"] == "link")
  422. $objecttype = ACTIVITY_OBJ_BOOKMARK;
  423. elseif ($post["type"] == "video")
  424. $objecttype = ACTIVITY_OBJ_VIDEO;
  425. elseif ($post["type"] == "photo")
  426. $objecttype = ACTIVITY_OBJ_IMAGE;
  427. }
  428. /**
  429. * Look for any tags and linkify them
  430. */
  431. $str_tags = '';
  432. $inform = '';
  433. $tags = get_tags($body);
  434. /**
  435. * add a statusnet style reply tag if the original post was from there
  436. * and we are replying, and there isn't one already
  437. */
  438. if($parent AND ($parent_contact['network'] === NETWORK_OSTATUS)) {
  439. if ($parent_contact['id'] != "")
  440. $contact = '@'.$parent_contact['nick'].'+'.$parent_contact['id'];
  441. else
  442. $contact = '@[url='.$parent_contact['url'].']'.$parent_contact['nick'].'[/url]';
  443. if (!in_array($contact,$tags)) {
  444. $body = $contact.' '.$body;
  445. $tags[] = $contact;
  446. }
  447. $toplevel_contact = "";
  448. $toplevel_parent = q("SELECT `contact`.* FROM `contact`
  449. INNER JOIN `item` ON `item`.`contact-id` = `contact`.`id` AND `contact`.`url` = `item`.`author-link`
  450. WHERE `item`.`id` = `item`.`parent` AND `item`.`parent` = %d", intval($parent));
  451. if ($toplevel_parent)
  452. $toplevel_contact = '@'.$toplevel_parent[0]['nick'].'+'.$toplevel_parent[0]['id'];
  453. else {
  454. $toplevel_parent = q("SELECT `author-link`, `author-name` FROM `item` WHERE `id` = `parent` AND `parent` = %d", intval($parent));
  455. $toplevel_contact = '@[url='.$toplevel_parent[0]['author-link'].']'.$toplevel_parent[0]['author-name'].'[/url]';
  456. }
  457. if (!in_array($toplevel_contact,$tags))
  458. $tags[] = $toplevel_contact;
  459. }
  460. $tagged = array();
  461. $private_forum = false;
  462. if(count($tags)) {
  463. foreach($tags as $tag) {
  464. if(strpos($tag,'#') === 0)
  465. continue;
  466. // If we already tagged 'Robert Johnson', don't try and tag 'Robert'.
  467. // Robert Johnson should be first in the $tags array
  468. $fullnametagged = false;
  469. for($x = 0; $x < count($tagged); $x ++) {
  470. if(stristr($tagged[$x],$tag . ' ')) {
  471. $fullnametagged = true;
  472. break;
  473. }
  474. }
  475. if($fullnametagged)
  476. continue;
  477. $success = handle_tag($a, $body, $inform, $str_tags, (local_user()) ? local_user() : $profile_uid , $tag, $network);
  478. if($success['replaced'])
  479. $tagged[] = $tag;
  480. if(is_array($success['contact']) && intval($success['contact']['prv'])) {
  481. $private_forum = true;
  482. $private_id = $success['contact']['id'];
  483. }
  484. }
  485. }
  486. if(($private_forum) && (! $parent) && (! $private)) {
  487. // we tagged a private forum in a top level post and the message was public.
  488. // Restrict it.
  489. $private = 1;
  490. $str_contact_allow = '<' . $private_id . '>';
  491. }
  492. $attachments = '';
  493. $match = false;
  494. if(preg_match_all('/(\[attachment\]([0-9]+)\[\/attachment\])/',$body,$match)) {
  495. foreach($match[2] as $mtch) {
  496. $r = q("SELECT `id`,`filename`,`filesize`,`filetype` FROM `attach` WHERE `uid` = %d AND `id` = %d LIMIT 1",
  497. intval($profile_uid),
  498. intval($mtch)
  499. );
  500. if(count($r)) {
  501. if(strlen($attachments))
  502. $attachments .= ',';
  503. $attachments .= '[attach]href="' . $a->get_baseurl() . '/attach/' . $r[0]['id'] . '" length="' . $r[0]['filesize'] . '" type="' . $r[0]['filetype'] . '" title="' . (($r[0]['filename']) ? $r[0]['filename'] : '') . '"[/attach]';
  504. }
  505. $body = str_replace($match[1],'',$body);
  506. }
  507. }
  508. $wall = 0;
  509. if($post_type === 'wall' || $post_type === 'wall-comment')
  510. $wall = 1;
  511. if(! strlen($verb))
  512. $verb = ACTIVITY_POST ;
  513. if ($network == "")
  514. $network = NETWORK_DFRN;
  515. $gravity = (($parent) ? 6 : 0 );
  516. // even if the post arrived via API we are considering that it
  517. // originated on this site by default for determining relayability.
  518. $origin = ((x($_REQUEST,'origin')) ? intval($_REQUEST['origin']) : 1);
  519. $notify_type = (($parent) ? 'comment-new' : 'wall-new' );
  520. $uri = (($message_id) ? $message_id : item_new_uri($a->get_hostname(),$profile_uid, $guid));
  521. // Fallback so that we alway have a thr-parent
  522. if(!$thr_parent)
  523. $thr_parent = $uri;
  524. $datarray = array();
  525. $datarray['uid'] = $profile_uid;
  526. $datarray['type'] = $post_type;
  527. $datarray['wall'] = $wall;
  528. $datarray['gravity'] = $gravity;
  529. $datarray['network'] = $network;
  530. $datarray['contact-id'] = $contact_id;
  531. $datarray['owner-name'] = $contact_record['name'];
  532. $datarray['owner-link'] = $contact_record['url'];
  533. $datarray['owner-avatar'] = $contact_record['thumb'];
  534. $datarray['author-name'] = $author['name'];
  535. $datarray['author-link'] = $author['url'];
  536. $datarray['author-avatar'] = $author['thumb'];
  537. $datarray['created'] = datetime_convert();
  538. $datarray['edited'] = datetime_convert();
  539. $datarray['commented'] = datetime_convert();
  540. $datarray['received'] = datetime_convert();
  541. $datarray['changed'] = datetime_convert();
  542. $datarray['extid'] = $extid;
  543. $datarray['guid'] = $guid;
  544. $datarray['uri'] = $uri;
  545. $datarray['title'] = $title;
  546. $datarray['body'] = $body;
  547. $datarray['app'] = $app;
  548. $datarray['location'] = $location;
  549. $datarray['coord'] = $coord;
  550. $datarray['tag'] = $str_tags;
  551. $datarray['file'] = $categories;
  552. $datarray['inform'] = $inform;
  553. $datarray['verb'] = $verb;
  554. $datarray['object-type'] = $objecttype;
  555. $datarray['allow_cid'] = $str_contact_allow;
  556. $datarray['allow_gid'] = $str_group_allow;
  557. $datarray['deny_cid'] = $str_contact_deny;
  558. $datarray['deny_gid'] = $str_group_deny;
  559. $datarray['private'] = $private;
  560. $datarray['pubmail'] = $pubmail_enable;
  561. $datarray['attach'] = $attachments;
  562. $datarray['bookmark'] = intval($bookmark);
  563. $datarray['thr-parent'] = $thr_parent;
  564. $datarray['postopts'] = $postopts;
  565. $datarray['origin'] = $origin;
  566. $datarray['moderated'] = $allow_moderated;
  567. /**
  568. * These fields are for the convenience of plugins...
  569. * 'self' if true indicates the owner is posting on their own wall
  570. * If parent is 0 it is a top-level post.
  571. */
  572. $datarray['parent'] = $parent;
  573. $datarray['self'] = $self;
  574. // $datarray['prvnets'] = $user['prvnets'];
  575. if($orig_post)
  576. $datarray['edit'] = true;
  577. // Search for hashtags
  578. item_body_set_hashtags($datarray);
  579. // preview mode - prepare the body for display and send it via json
  580. if($preview) {
  581. require_once('include/conversation.php');
  582. $o = conversation($a,array(array_merge($contact_record,$datarray)),'search', false, true);
  583. logger('preview: ' . $o);
  584. echo json_encode(array('preview' => $o));
  585. killme();
  586. }
  587. call_hooks('post_local',$datarray);
  588. if(x($datarray,'cancel')) {
  589. logger('mod_item: post cancelled by plugin.');
  590. if($return_path) {
  591. goaway($a->get_baseurl() . "/" . $return_path);
  592. }
  593. $json = array('cancel' => 1);
  594. if(x($_REQUEST,'jsreload') && strlen($_REQUEST['jsreload']))
  595. $json['reload'] = $a->get_baseurl() . '/' . $_REQUEST['jsreload'];
  596. echo json_encode($json);
  597. killme();
  598. }
  599. // Fill the cache field
  600. put_item_in_cache($datarray);
  601. if($orig_post) {
  602. $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `attach` = '%s', `file` = '%s', `rendered-html` = '%s', `rendered-hash` = '%s', `edited` = '%s', `changed` = '%s' WHERE `id` = %d AND `uid` = %d",
  603. dbesc($datarray['title']),
  604. dbesc($datarray['body']),
  605. dbesc($datarray['tag']),
  606. dbesc($datarray['attach']),
  607. dbesc($datarray['file']),
  608. dbesc($datarray['rendered-html']),
  609. dbesc($datarray['rendered-hash']),
  610. dbesc(datetime_convert()),
  611. dbesc(datetime_convert()),
  612. intval($post_id),
  613. intval($profile_uid)
  614. );
  615. create_tags_from_item($post_id);
  616. create_files_from_item($post_id);
  617. update_thread($post_id);
  618. // update filetags in pconfig
  619. file_tag_update_pconfig($uid,$categories_old,$categories_new,'category');
  620. proc_run('php', "include/notifier.php", 'edit_post', "$post_id");
  621. if((x($_REQUEST,'return')) && strlen($return_path)) {
  622. logger('return: ' . $return_path);
  623. goaway($a->get_baseurl() . "/" . $return_path );
  624. }
  625. killme();
  626. }
  627. else
  628. $post_id = 0;
  629. $r = q("INSERT INTO `item` (`guid`, `extid`, `uid`,`type`,`wall`,`gravity`, `network`, `contact-id`,`owner-name`,`owner-link`,`owner-avatar`, `author-name`, `author-link`, `author-avatar`,
  630. `created`, `edited`, `commented`, `received`, `changed`, `uri`, `thr-parent`, `title`, `body`, `app`, `location`, `coord`, `tag`, `inform`, `verb`, `object-type`, `postopts`,
  631. `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid`, `private`, `pubmail`, `attach`, `bookmark`,`origin`, `moderated`, `file`, `rendered-html`, `rendered-hash`)
  632. VALUES( '%s', '%s', %d, '%s', %d, %d, '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, '%s', '%s', '%s')",
  633. dbesc($datarray['guid']),
  634. dbesc($datarray['extid']),
  635. intval($datarray['uid']),
  636. dbesc($datarray['type']),
  637. intval($datarray['wall']),
  638. intval($datarray['gravity']),
  639. dbesc($datarray['network']),
  640. intval($datarray['contact-id']),
  641. dbesc($datarray['owner-name']),
  642. dbesc($datarray['owner-link']),
  643. dbesc($datarray['owner-avatar']),
  644. dbesc($datarray['author-name']),
  645. dbesc($datarray['author-link']),
  646. dbesc($datarray['author-avatar']),
  647. dbesc($datarray['created']),
  648. dbesc($datarray['edited']),
  649. dbesc($datarray['commented']),
  650. dbesc($datarray['received']),
  651. dbesc($datarray['changed']),
  652. dbesc($datarray['uri']),
  653. dbesc($datarray['thr-parent']),
  654. dbesc($datarray['title']),
  655. dbesc($datarray['body']),
  656. dbesc($datarray['app']),
  657. dbesc($datarray['location']),
  658. dbesc($datarray['coord']),
  659. dbesc($datarray['tag']),
  660. dbesc($datarray['inform']),
  661. dbesc($datarray['verb']),
  662. dbesc($datarray['object-type']),
  663. dbesc($datarray['postopts']),
  664. dbesc($datarray['allow_cid']),
  665. dbesc($datarray['allow_gid']),
  666. dbesc($datarray['deny_cid']),
  667. dbesc($datarray['deny_gid']),
  668. intval($datarray['private']),
  669. intval($datarray['pubmail']),
  670. dbesc($datarray['attach']),
  671. intval($datarray['bookmark']),
  672. intval($datarray['origin']),
  673. intval($datarray['moderated']),
  674. dbesc($datarray['file']),
  675. dbesc($datarray['rendered-html']),
  676. dbesc($datarray['rendered-hash'])
  677. );
  678. $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' LIMIT 1",
  679. dbesc($datarray['uri']));
  680. if(!count($r)) {
  681. logger('mod_item: unable to retrieve post that was just stored.');
  682. notice( t('System error. Post not saved.') . EOL);
  683. goaway($a->get_baseurl() . "/" . $return_path );
  684. // NOTREACHED
  685. }
  686. // Store the guid and other relevant data
  687. add_guid($datarray);
  688. $post_id = $r[0]['id'];
  689. logger('mod_item: saved item ' . $post_id);
  690. $datarray["id"] = $post_id;
  691. $datarray["plink"] = $a->get_baseurl().'/display/'.urlencode($datarray["guid"]);
  692. // update filetags in pconfig
  693. file_tag_update_pconfig($uid,$categories_old,$categories_new,'category');
  694. if($parent) {
  695. // This item is the last leaf and gets the comment box, clear any ancestors
  696. $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent` = %d ",
  697. dbesc(datetime_convert()),
  698. intval($parent)
  699. );
  700. update_thread($parent, true);
  701. // Inherit ACLs from the parent item.
  702. $r = q("UPDATE `item` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s', `private` = %d
  703. WHERE `id` = %d",
  704. dbesc($parent_item['allow_cid']),
  705. dbesc($parent_item['allow_gid']),
  706. dbesc($parent_item['deny_cid']),
  707. dbesc($parent_item['deny_gid']),
  708. intval($parent_item['private']),
  709. intval($post_id)
  710. );
  711. if($contact_record != $author) {
  712. notification(array(
  713. 'type' => NOTIFY_COMMENT,
  714. 'notify_flags' => $user['notify-flags'],
  715. 'language' => $user['language'],
  716. 'to_name' => $user['username'],
  717. 'to_email' => $user['email'],
  718. 'uid' => $user['uid'],
  719. 'item' => $datarray,
  720. 'link' => $a->get_baseurl().'/display/'.urlencode($datarray['guid']),
  721. 'source_name' => $datarray['author-name'],
  722. 'source_link' => $datarray['author-link'],
  723. 'source_photo' => $datarray['author-avatar'],
  724. 'verb' => ACTIVITY_POST,
  725. 'otype' => 'item',
  726. 'parent' => $parent,
  727. 'parent_uri' => $parent_item['uri']
  728. ));
  729. }
  730. // Store the comment signature information in case we need to relay to Diaspora
  731. store_diaspora_comment_sig($datarray, $author, ($self ? $a->user['prvkey'] : false), $parent_item, $post_id);
  732. } else {
  733. $parent = $post_id;
  734. if($contact_record != $author) {
  735. notification(array(
  736. 'type' => NOTIFY_WALL,
  737. 'notify_flags' => $user['notify-flags'],
  738. 'language' => $user['language'],
  739. 'to_name' => $user['username'],
  740. 'to_email' => $user['email'],
  741. 'uid' => $user['uid'],
  742. 'item' => $datarray,
  743. 'link' => $a->get_baseurl().'/display/'.urlencode($datarray['guid']),
  744. 'source_name' => $datarray['author-name'],
  745. 'source_link' => $datarray['author-link'],
  746. 'source_photo' => $datarray['author-avatar'],
  747. 'verb' => ACTIVITY_POST,
  748. 'otype' => 'item'
  749. ));
  750. }
  751. }
  752. // fallback so that parent always gets set to non-zero.
  753. if(! $parent)
  754. $parent = $post_id;
  755. $r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s', `plink` = '%s', `changed` = '%s', `last-child` = 1, `visible` = 1
  756. WHERE `id` = %d",
  757. intval($parent),
  758. dbesc(($parent == $post_id) ? $uri : $parent_item['uri']),
  759. dbesc($a->get_baseurl().'/display/'.urlencode($datarray['guid'])),
  760. dbesc(datetime_convert()),
  761. intval($post_id)
  762. );
  763. // photo comments turn the corresponding item visible to the profile wall
  764. // This way we don't see every picture in your new photo album posted to your wall at once.
  765. // They will show up as people comment on them.
  766. if(! $parent_item['visible']) {
  767. $r = q("UPDATE `item` SET `visible` = 1 WHERE `id` = %d",
  768. intval($parent_item['id'])
  769. );
  770. update_thread($parent_item['id']);
  771. }
  772. // update the commented timestamp on the parent
  773. q("UPDATE `item` set `commented` = '%s', `changed` = '%s' WHERE `id` = %d",
  774. dbesc(datetime_convert()),
  775. dbesc(datetime_convert()),
  776. intval($parent)
  777. );
  778. if ($post_id != $parent)
  779. update_thread($parent);
  780. call_hooks('post_local_end', $datarray);
  781. if(strlen($emailcc) && $profile_uid == local_user()) {
  782. $erecips = explode(',', $emailcc);
  783. if(count($erecips)) {
  784. foreach($erecips as $recip) {
  785. $addr = trim($recip);
  786. if(! strlen($addr))
  787. continue;
  788. $disclaimer = '<hr />' . sprintf( t('This message was sent to you by %s, a member of the Friendica social network.'),$a->user['username'])
  789. . '<br />';
  790. $disclaimer .= sprintf( t('You may visit them online at %s'), $a->get_baseurl() . '/profile/' . $a->user['nickname']) . EOL;
  791. $disclaimer .= t('Please contact the sender by replying to this post if you do not wish to receive these messages.') . EOL;
  792. if (!$datarray['title']=='') {
  793. $subject = email_header_encode($datarray['title'],'UTF-8');
  794. } else {
  795. $subject = email_header_encode('[Friendica]' . ' ' . sprintf( t('%s posted an update.'),$a->user['username']),'UTF-8');
  796. }
  797. $link = '<a href="' . $a->get_baseurl() . '/profile/' . $a->user['nickname'] . '"><img src="' . $author['thumb'] . '" alt="' . $a->user['username'] . '" /></a><br /><br />';
  798. $html = prepare_body($datarray);
  799. $message = '<html><body>' . $link . $html . $disclaimer . '</body></html>';
  800. include_once('include/html2plain.php');
  801. $params = array (
  802. 'fromName' => $a->user['username'],
  803. 'fromEmail' => $a->user['email'],
  804. 'toEmail' => $addr,
  805. 'replyTo' => $a->user['email'],
  806. 'messageSubject' => $subject,
  807. 'htmlVersion' => $message,
  808. 'textVersion' => html2plain($html.$disclaimer),
  809. );
  810. Emailer::send($params);
  811. }
  812. }
  813. }
  814. create_tags_from_item($post_id);
  815. create_files_from_item($post_id);
  816. if ($post_id == $parent)
  817. add_thread($post_id);
  818. // This is a real juggling act on shared hosting services which kill your processes
  819. // e.g. dreamhost. We used to start delivery to our native delivery agents in the background
  820. // and then run our plugin delivery from the foreground. We're now doing plugin delivery first,
  821. // because as soon as you start loading up a bunch of remote delivey processes, *this* page is
  822. // likely to get killed off. If you end up looking at an /item URL and a blank page,
  823. // it's very likely the delivery got killed before all your friends could be notified.
  824. // Currently the only realistic fixes are to use a reliable server - which precludes shared hosting,
  825. // or cut back on plugins which do remote deliveries.
  826. proc_run('php', "include/notifier.php", $notify_type, "$post_id");
  827. logger('post_complete');
  828. item_post_return($a->get_baseurl(), $api_source, $return_path);
  829. // NOTREACHED
  830. }
  831. function item_post_return($baseurl, $api_source, $return_path) {
  832. // figure out how to return, depending on from whence we came
  833. if($api_source)
  834. return;
  835. if($return_path) {
  836. goaway($baseurl . "/" . $return_path);
  837. }
  838. $json = array('success' => 1);
  839. if(x($_REQUEST,'jsreload') && strlen($_REQUEST['jsreload']))
  840. $json['reload'] = $baseurl . '/' . $_REQUEST['jsreload'];
  841. logger('post_json: ' . print_r($json,true), LOGGER_DEBUG);
  842. echo json_encode($json);
  843. killme();
  844. }
  845. function item_content(&$a) {
  846. if((! local_user()) && (! remote_user()))
  847. return;
  848. require_once('include/security.php');
  849. $o = '';
  850. if(($a->argc == 3) && ($a->argv[1] === 'drop') && intval($a->argv[2])) {
  851. $o = drop_item($a->argv[2], !is_ajax());
  852. if (is_ajax()){
  853. // ajax return: [<item id>, 0 (no perm) | <owner id>]
  854. echo json_encode(array(intval($a->argv[2]), intval($o)));
  855. killme();
  856. }
  857. }
  858. return $o;
  859. }
  860. /**
  861. * This function removes the tag $tag from the text $body and replaces it with
  862. * the appropiate link.
  863. *
  864. * @param unknown_type $body the text to replace the tag in
  865. * @param unknown_type $inform a comma-seperated string containing everybody to inform
  866. * @param unknown_type $str_tags string to add the tag to
  867. * @param unknown_type $profile_uid
  868. * @param unknown_type $tag the tag to replace
  869. *
  870. * @return boolean true if replaced, false if not replaced
  871. */
  872. function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $network = "") {
  873. $replaced = false;
  874. $r = null;
  875. //is it a person tag?
  876. if(strpos($tag,'@') === 0) {
  877. //is it already replaced?
  878. if(strpos($tag,'[url=')) {
  879. //append tag to str_tags
  880. if(!stristr($str_tags,$tag)) {
  881. if(strlen($str_tags))
  882. $str_tags .= ',';
  883. $str_tags .= $tag;
  884. }
  885. // Checking for the alias that is used for OStatus
  886. $pattern = "/@\[url\=(.*?)\](.*?)\[\/url\]/ism";
  887. if (preg_match($pattern, $tag, $matches)) {
  888. $data = probe_url($matches[1]);
  889. if ($data["alias"] != "") {
  890. $newtag = '@[url='.$data["alias"].']'.$data["name"].'[/url]';
  891. if(!stristr($str_tags,$newtag)) {
  892. if(strlen($str_tags))
  893. $str_tags .= ',';
  894. $str_tags .= $newtag;
  895. }
  896. }
  897. }
  898. return $replaced;
  899. }
  900. $stat = false;
  901. //get the person's name
  902. $name = substr($tag,1);
  903. //is it a link or a full dfrn address?
  904. if((strpos($name,'@')) || (strpos($name,'http://'))) {
  905. $newname = $name;
  906. //get the profile links
  907. $links = @lrdd($name);
  908. if(count($links)) {
  909. //for all links, collect how is to inform and how's profile is to link
  910. foreach($links as $link) {
  911. if($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page')
  912. $profile = $link['@attributes']['href'];
  913. if($link['@attributes']['rel'] === 'salmon') {
  914. if(strlen($inform))
  915. $inform .= ',';
  916. $inform .= 'url:' . str_replace(',','%2c',$link['@attributes']['href']);
  917. }
  918. }
  919. }
  920. } elseif (($network != NETWORK_OSTATUS) AND ($network != NETWORK_TWITTER) AND
  921. ($network != NETWORK_STATUSNET) AND ($network != NETWORK_APPNET)) {
  922. //if it is a name rather than an address
  923. $newname = $name;
  924. $alias = '';
  925. $tagcid = 0;
  926. //is it some generated name?
  927. if(strrpos($newname,'+')) {
  928. //get the id
  929. $tagcid = intval(substr($newname,strrpos($newname,'+') + 1));
  930. //remove the next word from tag's name
  931. if(strpos($name,' ')) {
  932. $name = substr($name,0,strpos($name,' '));
  933. }
  934. }
  935. if($tagcid) { //if there was an id
  936. //select contact with that id from the logged in user's contact list
  937. $r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
  938. intval($tagcid),
  939. intval($profile_uid)
  940. );
  941. }
  942. else {
  943. $newname = str_replace('_',' ',$name);
  944. // At first try to fetch a contact according to the given network
  945. if ($network != "") {
  946. //select someone from this user's contacts by name
  947. $r = q("SELECT * FROM `contact` WHERE `name` = '%s' AND `network` = '%s' AND `uid` = %d LIMIT 1",
  948. dbesc($newname),
  949. dbesc($network),
  950. intval($profile_uid)
  951. );
  952. if(! $r) {
  953. //select someone by attag or nick and the name passed in
  954. $r = q("SELECT * FROM `contact` WHERE `attag` = '%s' OR `nick` = '%s' AND `network` = '%s' AND `uid` = %d ORDER BY `attag` DESC LIMIT 1",
  955. dbesc($name),
  956. dbesc($name),
  957. dbesc($network),
  958. intval($profile_uid)
  959. );
  960. }
  961. } else
  962. $r = false;
  963. if(! $r) {
  964. //select someone from this user's contacts by name
  965. $r = q("SELECT * FROM `contact` WHERE `name` = '%s' AND `uid` = %d LIMIT 1",
  966. dbesc($newname),
  967. intval($profile_uid)
  968. );
  969. }
  970. if(! $r) {
  971. //select someone by attag or nick and the name passed in
  972. $r = q("SELECT * FROM `contact` WHERE `attag` = '%s' OR `nick` = '%s' AND `uid` = %d ORDER BY `attag` DESC LIMIT 1",
  973. dbesc($name),
  974. dbesc($name),
  975. intval($profile_uid)
  976. );
  977. }
  978. }
  979. /* } elseif(strstr($name,'_') || strstr($name,' ')) { //no id
  980. //get the real name
  981. $newname = str_replace('_',' ',$name);
  982. //select someone from this user's contacts by name
  983. $r = q("SELECT * FROM `contact` WHERE `name` = '%s' AND `uid` = %d LIMIT 1",
  984. dbesc($newname),
  985. intval($profile_uid)
  986. );
  987. } else {
  988. //select someone by attag or nick and the name passed in
  989. $r = q("SELECT * FROM `contact` WHERE `attag` = '%s' OR `nick` = '%s' AND `uid` = %d ORDER BY `attag` DESC LIMIT 1",
  990. dbesc($name),
  991. dbesc($name),
  992. intval($profile_uid)
  993. );
  994. }*/
  995. //$r is set, if someone could be selected
  996. if(count($r)) {
  997. $profile = $r[0]['url'];
  998. //set newname to nick, find alias
  999. if(($r[0]['network'] === NETWORK_OSTATUS) OR ($r[0]['network'] === NETWORK_TWITTER)
  1000. OR ($r[0]['network'] === NETWORK_STATUSNET) OR ($r[0]['network'] === NETWORK_APPNET)) {
  1001. $newname = $r[0]['nick'];
  1002. $stat = true;
  1003. if($r[0]['alias'])
  1004. $alias = $r[0]['alias'];
  1005. }
  1006. else
  1007. $newname = $r[0]['name'];
  1008. //add person's id to $inform
  1009. if(strlen($inform))
  1010. $inform .= ',';
  1011. $inform .= 'cid:' . $r[0]['id'];
  1012. }
  1013. }
  1014. //if there is an url for this persons profile
  1015. if(isset($profile)) {
  1016. $replaced = true;
  1017. //create profile link
  1018. $profile = str_replace(',','%2c',$profile);
  1019. $newtag = '@[url=' . $profile . ']' . $newname . '[/url]';
  1020. $body = str_replace('@' . $name, $newtag, $body);
  1021. //append tag to str_tags
  1022. if(! stristr($str_tags,$newtag)) {
  1023. if(strlen($str_tags))
  1024. $str_tags .= ',';
  1025. $str_tags .= $newtag;
  1026. }
  1027. // Status.Net seems to require the numeric ID URL in a mention if the person isn't
  1028. // subscribed to you. But the nickname URL is OK if they are. Grrr. We'll tag both.
  1029. if(strlen($alias)) {
  1030. $newtag = '@[url=' . $alias . ']' . $newname . '[/url]';
  1031. if(! stristr($str_tags,$newtag)) {
  1032. if(strlen($str_tags))
  1033. $str_tags .= ',';
  1034. $str_tags .= $newtag;
  1035. }
  1036. }
  1037. }
  1038. }
  1039. return array('replaced' => $replaced, 'contact' => $r[0]);
  1040. }
  1041. function store_diaspora_comment_sig($datarray, $author, $uprvkey, $parent_item, $post_id) {
  1042. // We won't be able to sign Diaspora comments for authenticated visitors - we don't have their private key
  1043. $enabled = intval(get_config('system','diaspora_enabled'));
  1044. if(! $enabled) {
  1045. logger('mod_item: diaspora support disabled, not storing comment signature', LOGGER_DEBUG);
  1046. return;
  1047. }
  1048. logger('mod_item: storing diaspora comment signature');
  1049. require_once('include/bb2diaspora.php');
  1050. $signed_body = html_entity_decode(bb2diaspora($datarray['body']));
  1051. // Only works for NETWORK_DFRN
  1052. $contact_baseurl_start = strpos($author['url'],'://') + 3;
  1053. $contact_baseurl_length = strpos($author['url'],'/profile') - $contact_baseurl_start;
  1054. $contact_baseurl = substr($author['url'], $contact_baseurl_start, $contact_baseurl_length);
  1055. $diaspora_handle = $author['nick'] . '@' . $contact_baseurl;
  1056. $signed_text = $datarray['guid'] . ';' . $parent_item['guid'] . ';' . $signed_body . ';' . $diaspora_handle;
  1057. if( $uprvkey !== false )
  1058. $authorsig = base64_encode(rsa_sign($signed_text,$uprvkey,'sha256'));
  1059. else
  1060. $authorsig = '';
  1061. q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
  1062. intval($post_id),
  1063. dbesc($signed_text),
  1064. dbesc(base64_encode($authorsig)),
  1065. dbesc($diaspora_handle)
  1066. );
  1067. return;
  1068. }