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.

857 lines
26KB

  1. <?php
  2. use Friendica\App;
  3. // Included here for completeness, but this is a very dangerous operation.
  4. // It is the caller's responsibility to confirm the requestor's intent and
  5. // authorisation to do this.
  6. function user_remove($uid) {
  7. if(! $uid)
  8. return;
  9. logger('Removing user: ' . $uid);
  10. $r = q("select * from user where uid = %d limit 1", intval($uid));
  11. call_hooks('remove_user',$r[0]);
  12. // save username (actually the nickname as it is guaranteed
  13. // unique), so it cannot be re-registered in the future.
  14. q("insert into userd ( username ) values ( '%s' )",
  15. $r[0]['nickname']
  16. );
  17. /// @todo Should be done in a background job since this likely will run into a time out
  18. // don't delete yet, will be done later when contacts have deleted my stuff
  19. // q("DELETE FROM `contact` WHERE `uid` = %d", intval($uid));
  20. q("DELETE FROM `gcign` WHERE `uid` = %d", intval($uid));
  21. q("DELETE FROM `group` WHERE `uid` = %d", intval($uid));
  22. q("DELETE FROM `group_member` WHERE `uid` = %d", intval($uid));
  23. q("DELETE FROM `intro` WHERE `uid` = %d", intval($uid));
  24. q("DELETE FROM `event` WHERE `uid` = %d", intval($uid));
  25. q("DELETE FROM `item` WHERE `uid` = %d", intval($uid));
  26. q("DELETE FROM `item_id` WHERE `uid` = %d", intval($uid));
  27. q("DELETE FROM `mail` WHERE `uid` = %d", intval($uid));
  28. q("DELETE FROM `mailacct` WHERE `uid` = %d", intval($uid));
  29. q("DELETE FROM `manage` WHERE `uid` = %d", intval($uid));
  30. q("DELETE FROM `notify` WHERE `uid` = %d", intval($uid));
  31. q("DELETE FROM `photo` WHERE `uid` = %d", intval($uid));
  32. q("DELETE FROM `attach` WHERE `uid` = %d", intval($uid));
  33. q("DELETE FROM `profile` WHERE `uid` = %d", intval($uid));
  34. q("DELETE FROM `profile_check` WHERE `uid` = %d", intval($uid));
  35. q("DELETE FROM `pconfig` WHERE `uid` = %d", intval($uid));
  36. q("DELETE FROM `search` WHERE `uid` = %d", intval($uid));
  37. q("DELETE FROM `spam` WHERE `uid` = %d", intval($uid));
  38. // don't delete yet, will be done later when contacts have deleted my stuff
  39. // q("DELETE FROM `user` WHERE `uid` = %d", intval($uid));
  40. q("UPDATE `user` SET `account_removed` = 1, `account_expires_on` = UTC_TIMESTAMP() WHERE `uid` = %d", intval($uid));
  41. proc_run(PRIORITY_HIGH, "include/notifier.php", "removeme", $uid);
  42. // Send an update to the directory
  43. proc_run(PRIORITY_LOW, "include/directory.php", $r[0]['url']);
  44. if($uid == local_user()) {
  45. unset($_SESSION['authenticated']);
  46. unset($_SESSION['uid']);
  47. goaway(App::get_baseurl());
  48. }
  49. }
  50. function contact_remove($id) {
  51. // We want just to make sure that we don't delete our "self" contact
  52. $r = q("SELECT `uid` FROM `contact` WHERE `id` = %d AND NOT `self` LIMIT 1",
  53. intval($id)
  54. );
  55. if (!dbm::is_result($r) || !intval($r[0]['uid'])) {
  56. return;
  57. }
  58. $archive = get_pconfig($r[0]['uid'], 'system','archive_removed_contacts');
  59. if ($archive) {
  60. q("update contact set `archive` = 1, `network` = 'none', `writable` = 0 where id = %d",
  61. intval($id)
  62. );
  63. return;
  64. }
  65. q("DELETE FROM `contact` WHERE `id` = %d", intval($id));
  66. // Delete the rest in the background
  67. proc_run(PRIORITY_LOW, 'include/remove_contact.php', $id);
  68. }
  69. // sends an unfriend message. Does not remove the contact
  70. function terminate_friendship($user,$self,$contact) {
  71. /// @TODO Get rid of this, include/datetime.php should care about it by itself
  72. $a = get_app();
  73. require_once('include/datetime.php');
  74. if ($contact['network'] === NETWORK_OSTATUS) {
  75. require_once('include/ostatus.php');
  76. // create an unfollow slap
  77. $item = array();
  78. $item['verb'] = NAMESPACE_OSTATUS."/unfollow";
  79. $item['follow'] = $contact["url"];
  80. $slap = ostatus::salmon($item, $user);
  81. if ((x($contact,'notify')) && (strlen($contact['notify']))) {
  82. require_once('include/salmon.php');
  83. slapper($user,$contact['notify'],$slap);
  84. }
  85. } elseif ($contact['network'] === NETWORK_DIASPORA) {
  86. require_once('include/diaspora.php');
  87. Diaspora::send_unshare($user,$contact);
  88. } elseif ($contact['network'] === NETWORK_DFRN) {
  89. require_once('include/dfrn.php');
  90. dfrn::deliver($user,$contact,'placeholder', 1);
  91. }
  92. }
  93. // Contact has refused to recognise us as a friend. We will start a countdown.
  94. // If they still don't recognise us in 32 days, the relationship is over,
  95. // and we won't waste any more time trying to communicate with them.
  96. // This provides for the possibility that their database is temporarily messed
  97. // up or some other transient event and that there's a possibility we could recover from it.
  98. function mark_for_death($contact) {
  99. if($contact['archive'])
  100. return;
  101. if ($contact['term-date'] <= NULL_DATE) {
  102. q("UPDATE `contact` SET `term-date` = '%s' WHERE `id` = %d",
  103. dbesc(datetime_convert()),
  104. intval($contact['id'])
  105. );
  106. if ($contact['url'] != '') {
  107. q("UPDATE `contact` SET `term-date` = '%s'
  108. WHERE `nurl` = '%s' AND `term-date` <= '1000-00-00'",
  109. dbesc(datetime_convert()),
  110. dbesc(normalise_link($contact['url']))
  111. );
  112. }
  113. } else {
  114. /// @todo
  115. /// We really should send a notification to the owner after 2-3 weeks
  116. /// so they won't be surprised when the contact vanishes and can take
  117. /// remedial action if this was a serious mistake or glitch
  118. /// @todo
  119. /// Check for contact vitality via probing
  120. $expiry = $contact['term-date'] . ' + 32 days ';
  121. if(datetime_convert() > datetime_convert('UTC','UTC',$expiry)) {
  122. // relationship is really truly dead.
  123. // archive them rather than delete
  124. // though if the owner tries to unarchive them we'll start the whole process over again
  125. q("UPDATE `contact` SET `archive` = 1 WHERE `id` = %d",
  126. intval($contact['id'])
  127. );
  128. if ($contact['url'] != '') {
  129. q("UPDATE `contact` SET `archive` = 1 WHERE `nurl` = '%s'",
  130. dbesc(normalise_link($contact['url']))
  131. );
  132. }
  133. }
  134. }
  135. }
  136. function unmark_for_death($contact) {
  137. $r = q("SELECT `term-date` FROM `contact` WHERE `id` = %d AND `term-date` > '%s'",
  138. intval($contact['id']),
  139. dbesc('1000-00-00 00:00:00')
  140. );
  141. // We don't need to update, we never marked this contact as dead
  142. if (!dbm::is_result($r)) {
  143. return;
  144. }
  145. // It's a miracle. Our dead contact has inexplicably come back to life.
  146. q("UPDATE `contact` SET `term-date` = '%s' WHERE `id` = %d",
  147. dbesc(NULL_DATE),
  148. intval($contact['id'])
  149. );
  150. if ($contact['url'] != '') {
  151. q("UPDATE `contact` SET `term-date` = '%s' WHERE `nurl` = '%s'",
  152. dbesc(NULL_DATE),
  153. dbesc(normalise_link($contact['url']))
  154. );
  155. }
  156. }
  157. /**
  158. * @brief Get contact data for a given profile link
  159. *
  160. * The function looks at several places (contact table and gcontact table) for the contact
  161. * It caches its result for the same script execution to prevent duplicate calls
  162. *
  163. * @param string $url The profile link
  164. * @param int $uid User id
  165. * @param array $default If not data was found take this data as default value
  166. *
  167. * @return array Contact data
  168. */
  169. function get_contact_details_by_url($url, $uid = -1, $default = array()) {
  170. static $cache = array();
  171. if ($url == '') {
  172. return $default;
  173. }
  174. if ($uid == -1) {
  175. $uid = local_user();
  176. }
  177. if (isset($cache[$url][$uid])) {
  178. return $cache[$url][$uid];
  179. }
  180. // Fetch contact data from the contact table for the given user
  181. $r = q("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`,
  182. `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self`
  183. FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d",
  184. dbesc(normalise_link($url)), intval($uid));
  185. // Fetch the data from the contact table with "uid=0" (which is filled automatically)
  186. if (!dbm::is_result($r))
  187. $r = q("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`,
  188. `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self`
  189. FROM `contact` WHERE `nurl` = '%s' AND `uid` = 0",
  190. dbesc(normalise_link($url)));
  191. // Fetch the data from the gcontact table
  192. if (!dbm::is_result($r))
  193. $r = q("SELECT 0 AS `id`, 0 AS `cid`, `id` AS `gid`, 0 AS `zid`, 0 AS `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, '' AS `xmpp`,
  194. `keywords`, `gender`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, `community` AS `forum`, 0 AS `prv`, `community`, `contact-type`, `birthday`, 0 AS `self`
  195. FROM `gcontact` WHERE `nurl` = '%s'",
  196. dbesc(normalise_link($url)));
  197. if (dbm::is_result($r)) {
  198. // If there is more than one entry we filter out the connector networks
  199. if (count($r) > 1) {
  200. foreach ($r AS $id => $result) {
  201. if ($result["network"] == NETWORK_STATUSNET) {
  202. unset($r[$id]);
  203. }
  204. }
  205. }
  206. $profile = array_shift($r);
  207. // "bd" always contains the upcoming birthday of a contact.
  208. // "birthday" might contain the birthday including the year of birth.
  209. if ($profile["birthday"] > '0001-01-01') {
  210. $bd_timestamp = strtotime($profile["birthday"]);
  211. $month = date("m", $bd_timestamp);
  212. $day = date("d", $bd_timestamp);
  213. $current_timestamp = time();
  214. $current_year = date("Y", $current_timestamp);
  215. $current_month = date("m", $current_timestamp);
  216. $current_day = date("d", $current_timestamp);
  217. $profile["bd"] = $current_year."-".$month."-".$day;
  218. $current = $current_year."-".$current_month."-".$current_day;
  219. if ($profile["bd"] < $current) {
  220. $profile["bd"] = (++$current_year)."-".$month."-".$day;
  221. }
  222. } else {
  223. $profile["bd"] = '0001-01-01';
  224. }
  225. } else {
  226. $profile = $default;
  227. }
  228. if (($profile["photo"] == "") AND isset($default["photo"])) {
  229. $profile["photo"] = $default["photo"];
  230. }
  231. if (($profile["name"] == "") AND isset($default["name"])) {
  232. $profile["name"] = $default["name"];
  233. }
  234. if (($profile["network"] == "") AND isset($default["network"])) {
  235. $profile["network"] = $default["network"];
  236. }
  237. if (($profile["thumb"] == "") AND isset($profile["photo"])) {
  238. $profile["thumb"] = $profile["photo"];
  239. }
  240. if (($profile["micro"] == "") AND isset($profile["thumb"])) {
  241. $profile["micro"] = $profile["thumb"];
  242. }
  243. if ((($profile["addr"] == "") OR ($profile["name"] == "")) AND ($profile["gid"] != 0) AND
  244. in_array($profile["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS))) {
  245. proc_run(PRIORITY_LOW, "include/update_gcontact.php", $profile["gid"]);
  246. }
  247. // Show contact details of Diaspora contacts only if connected
  248. if (($profile["cid"] == 0) AND ($profile["network"] == NETWORK_DIASPORA)) {
  249. $profile["location"] = "";
  250. $profile["about"] = "";
  251. $profile["gender"] = "";
  252. $profile["birthday"] = '0001-01-01';
  253. }
  254. $cache[$url][$uid] = $profile;
  255. return $profile;
  256. }
  257. /**
  258. * @brief Get contact data for a given address
  259. *
  260. * The function looks at several places (contact table and gcontact table) for the contact
  261. *
  262. * @param string $addr The profile link
  263. * @param int $uid User id
  264. *
  265. * @return array Contact data
  266. */
  267. function get_contact_details_by_addr($addr, $uid = -1) {
  268. static $cache = array();
  269. if ($addr == '') {
  270. return array();
  271. }
  272. if ($uid == -1) {
  273. $uid = local_user();
  274. }
  275. // Fetch contact data from the contact table for the given user
  276. $r = q("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`,
  277. `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self`
  278. FROM `contact` WHERE `addr` = '%s' AND `uid` = %d",
  279. dbesc($addr), intval($uid));
  280. // Fetch the data from the contact table with "uid=0" (which is filled automatically)
  281. if (!dbm::is_result($r))
  282. $r = q("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`,
  283. `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self`
  284. FROM `contact` WHERE `addr` = '%s' AND `uid` = 0",
  285. dbesc($addr));
  286. // Fetch the data from the gcontact table
  287. if (!dbm::is_result($r))
  288. $r = q("SELECT 0 AS `id`, 0 AS `cid`, `id` AS `gid`, 0 AS `zid`, 0 AS `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, '' AS `xmpp`,
  289. `keywords`, `gender`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, `community` AS `forum`, 0 AS `prv`, `community`, `contact-type`, `birthday`, 0 AS `self`
  290. FROM `gcontact` WHERE `addr` = '%s'",
  291. dbesc($addr));
  292. if (!dbm::is_result($r)) {
  293. require_once('include/Probe.php');
  294. $data = Probe::uri($addr);
  295. $profile = get_contact_details_by_url($data['url'], $uid);
  296. } else {
  297. $profile = $r[0];
  298. }
  299. return $profile;
  300. }
  301. if (! function_exists('contact_photo_menu')) {
  302. function contact_photo_menu($contact, $uid = 0)
  303. {
  304. $a = get_app();
  305. $contact_url = '';
  306. $pm_url = '';
  307. $status_link = '';
  308. $photos_link = '';
  309. $posts_link = '';
  310. $contact_drop_link = '';
  311. $poke_link = '';
  312. if ($uid == 0) {
  313. $uid = local_user();
  314. }
  315. if ($contact['uid'] != $uid) {
  316. if ($uid == 0) {
  317. $profile_link = zrl($contact['url']);
  318. $menu = Array('profile' => array(t('View Profile'), $profile_link, true));
  319. return $menu;
  320. }
  321. $r = q("SELECT * FROM `contact` WHERE `nurl` = '%s' AND `network` = '%s' AND `uid` = %d",
  322. dbesc($contact['nurl']), dbesc($contact['network']), intval($uid));
  323. if ($r) {
  324. return contact_photo_menu($r[0], $uid);
  325. } else {
  326. $profile_link = zrl($contact['url']);
  327. $connlnk = 'follow/?url='.$contact['url'];
  328. $menu = array(
  329. 'profile' => array(t('View Profile'), $profile_link, true),
  330. 'follow' => array(t('Connect/Follow'), $connlnk, true)
  331. );
  332. return $menu;
  333. }
  334. }
  335. $sparkle = false;
  336. if ($contact['network'] === NETWORK_DFRN) {
  337. $sparkle = true;
  338. $profile_link = App::get_baseurl() . '/redir/' . $contact['id'];
  339. } else {
  340. $profile_link = $contact['url'];
  341. }
  342. if ($profile_link === 'mailbox') {
  343. $profile_link = '';
  344. }
  345. if ($sparkle) {
  346. $status_link = $profile_link . '?url=status';
  347. $photos_link = $profile_link . '?url=photos';
  348. $profile_link = $profile_link . '?url=profile';
  349. }
  350. if (in_array($contact['network'], array(NETWORK_DFRN, NETWORK_DIASPORA))) {
  351. $pm_url = App::get_baseurl() . '/message/new/' . $contact['id'];
  352. }
  353. if ($contact['network'] == NETWORK_DFRN) {
  354. $poke_link = App::get_baseurl() . '/poke/?f=&c=' . $contact['id'];
  355. }
  356. $contact_url = App::get_baseurl() . '/contacts/' . $contact['id'];
  357. $posts_link = App::get_baseurl() . '/contacts/' . $contact['id'] . '/posts';
  358. $contact_drop_link = App::get_baseurl() . '/contacts/' . $contact['id'] . '/drop?confirm=1';
  359. /**
  360. * menu array:
  361. * "name" => [ "Label", "link", (bool)Should the link opened in a new tab? ]
  362. */
  363. $menu = array(
  364. 'status' => array(t("View Status"), $status_link, true),
  365. 'profile' => array(t("View Profile"), $profile_link, true),
  366. 'photos' => array(t("View Photos"), $photos_link, true),
  367. 'network' => array(t("Network Posts"), $posts_link, false),
  368. 'edit' => array(t("View Contact"), $contact_url, false),
  369. 'drop' => array(t("Drop Contact"), $contact_drop_link, false),
  370. 'pm' => array(t("Send PM"), $pm_url, false),
  371. 'poke' => array(t("Poke"), $poke_link, false),
  372. );
  373. $args = array('contact' => $contact, 'menu' => &$menu);
  374. call_hooks('contact_photo_menu', $args);
  375. $menucondensed = array();
  376. foreach ($menu AS $menuname => $menuitem) {
  377. if ($menuitem[1] != '') {
  378. $menucondensed[$menuname] = $menuitem;
  379. }
  380. }
  381. return $menucondensed;
  382. }}
  383. function random_profile() {
  384. $r = q("SELECT `url` FROM `gcontact` WHERE `network` = '%s'
  385. AND `last_contact` >= `last_failure`
  386. AND `updated` > UTC_TIMESTAMP - INTERVAL 1 MONTH
  387. ORDER BY rand() LIMIT 1",
  388. dbesc(NETWORK_DFRN));
  389. if (dbm::is_result($r))
  390. return dirname($r[0]['url']);
  391. return '';
  392. }
  393. function contacts_not_grouped($uid,$start = 0,$count = 0) {
  394. if(! $count) {
  395. $r = q("select count(*) as total from contact where uid = %d and self = 0 and id not in (select distinct(`contact-id`) from group_member where uid = %d) ",
  396. intval($uid),
  397. intval($uid)
  398. );
  399. return $r;
  400. }
  401. $r = q("select * from contact where uid = %d and self = 0 and id not in (select distinct(`contact-id`) from group_member where uid = %d) and blocked = 0 and pending = 0 limit %d, %d",
  402. intval($uid),
  403. intval($uid),
  404. intval($start),
  405. intval($count)
  406. );
  407. return $r;
  408. }
  409. /**
  410. * @brief Fetch the contact id for a given url and user
  411. *
  412. * First lookup in the contact table to find a record matching either `url`, `nurl`,
  413. * `addr` or `alias`.
  414. *
  415. * If there's no record and we aren't looking for a public contact, we quit.
  416. * If there's one, we check that it isn't time to update the picture else we
  417. * directly return the found contact id.
  418. *
  419. * Second, we probe the provided $url wether it's http://server.tld/profile or
  420. * nick@server.tld. We quit if we can't get any info back.
  421. *
  422. * Third, we create the contact record if it doesn't exist
  423. *
  424. * Fourth, we update the existing record with the new data (avatar, alias, nick)
  425. * if there's any updates
  426. *
  427. * @param string $url Contact URL
  428. * @param integer $uid The user id for the contact (0 = public contact)
  429. * @param boolean $no_update Don't update the contact
  430. *
  431. * @return integer Contact ID
  432. */
  433. function get_contact($url, $uid = 0, $no_update = false) {
  434. logger("Get contact data for url ".$url." and user ".$uid." - ".App::callstack(), LOGGER_DEBUG);;
  435. $data = array();
  436. $contact_id = 0;
  437. if ($url == '') {
  438. return 0;
  439. }
  440. // We first try the nurl (http://server.tld/nick), most common case
  441. $contacts = q("SELECT `id`, `avatar-date` FROM `contact`
  442. WHERE `nurl` = '%s'
  443. AND `uid` = %d",
  444. dbesc(normalise_link($url)),
  445. intval($uid));
  446. // Then the addr (nick@server.tld)
  447. if (! dbm::is_result($contacts)) {
  448. $contacts = q("SELECT `id`, `avatar-date` FROM `contact`
  449. WHERE `addr` = '%s'
  450. AND `uid` = %d",
  451. dbesc($url),
  452. intval($uid));
  453. }
  454. // Then the alias (which could be anything)
  455. if (! dbm::is_result($contacts)) {
  456. $contacts = q("SELECT `id`, `avatar-date` FROM `contact`
  457. WHERE `alias` IN ('%s', '%s')
  458. AND `uid` = %d",
  459. dbesc($url),
  460. dbesc(normalise_link($url)),
  461. intval($uid));
  462. }
  463. if (dbm::is_result($contacts)) {
  464. $contact_id = $contacts[0]["id"];
  465. // Update the contact every 7 days
  466. $update_photo = ($contacts[0]['avatar-date'] < datetime_convert('','','now -7 days'));
  467. if (!$update_photo OR $no_update) {
  468. return $contact_id;
  469. }
  470. } elseif ($uid != 0) {
  471. // Non-existing user-specific contact, exiting
  472. return 0;
  473. }
  474. require_once('include/Probe.php');
  475. $data = Probe::uri($url);
  476. // Last try in gcontact for unsupported networks
  477. if (!in_array($data["network"], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA, NETWORK_PUMPIO))) {
  478. if ($uid != 0) {
  479. return 0;
  480. }
  481. // Get data from the gcontact table
  482. $gcontacts = q("SELECT `name`, `nick`, `url`, `photo`, `addr`, `alias`, `network` FROM `gcontact` WHERE `nurl` = '%s'",
  483. dbesc(normalise_link($url)));
  484. if (!$gcontacts) {
  485. return 0;
  486. }
  487. $data = $gcontacts[0];
  488. }
  489. $url = $data["url"];
  490. if (!$contact_id) {
  491. q("INSERT INTO `contact` (`uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`,
  492. `name`, `nick`, `photo`, `network`, `pubkey`, `rel`, `priority`,
  493. `batch`, `request`, `confirm`, `poco`, `name-date`, `uri-date`,
  494. `writable`, `blocked`, `readonly`, `pending`)
  495. VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', 1, 0, 0, 0)",
  496. intval($uid),
  497. dbesc(datetime_convert()),
  498. dbesc($data["url"]),
  499. dbesc(normalise_link($data["url"])),
  500. dbesc($data["addr"]),
  501. dbesc($data["alias"]),
  502. dbesc($data["notify"]),
  503. dbesc($data["poll"]),
  504. dbesc($data["name"]),
  505. dbesc($data["nick"]),
  506. dbesc($data["photo"]),
  507. dbesc($data["network"]),
  508. dbesc($data["pubkey"]),
  509. intval(CONTACT_IS_SHARING),
  510. intval($data["priority"]),
  511. dbesc($data["batch"]),
  512. dbesc($data["request"]),
  513. dbesc($data["confirm"]),
  514. dbesc($data["poco"]),
  515. dbesc(datetime_convert()),
  516. dbesc(datetime_convert())
  517. );
  518. $contacts = q("SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d ORDER BY `id` LIMIT 2",
  519. dbesc(normalise_link($data["url"])),
  520. intval($uid));
  521. if (!dbm::is_result($contacts)) {
  522. return 0;
  523. }
  524. $contact_id = $contacts[0]["id"];
  525. // Update the newly created contact from data in the gcontact table
  526. $gcontacts = q("SELECT `location`, `about`, `keywords`, `gender` FROM `gcontact` WHERE `nurl` = '%s'",
  527. dbesc(normalise_link($data["url"])));
  528. if (dbm::is_result($gcontacts)) {
  529. logger("Update contact " . $data["url"] . ' from gcontact');
  530. q("UPDATE `contact` SET `location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s' WHERE `id` = %d",
  531. dbesc($gcontacts[0]["location"]), dbesc($gcontacts[0]["about"]), dbesc($gcontacts[0]["keywords"]),
  532. dbesc($gcontacts[0]["gender"]), intval($contact_id));
  533. }
  534. }
  535. if (count($contacts) > 1 AND $uid == 0 AND $contact_id != 0 AND $url != "") {
  536. q("DELETE FROM `contact` WHERE `nurl` = '%s' AND `id` != %d AND NOT `self`",
  537. dbesc(normalise_link($url)),
  538. intval($contact_id));
  539. }
  540. require_once "Photo.php";
  541. update_contact_avatar($data["photo"], $uid, $contact_id);
  542. $contacts = q("SELECT `addr`, `alias`, `name`, `nick` FROM `contact` WHERE `id` = %d", intval($contact_id));
  543. // This condition should always be true
  544. if (!dbm::is_result($contacts)) {
  545. return $contact_id;
  546. }
  547. // Only update if there had something been changed
  548. if ($data["addr"] != $contacts[0]["addr"] OR
  549. $data["alias"] != $contacts[0]["alias"] OR
  550. $data["name"] != $contacts[0]["name"] OR
  551. $data["nick"] != $contacts[0]["nick"]) {
  552. q("UPDATE `contact` SET `addr` = '%s', `alias` = '%s', `name` = '%s', `nick` = '%s',
  553. `name-date` = '%s', `uri-date` = '%s' WHERE `id` = %d",
  554. dbesc($data["addr"]),
  555. dbesc($data["alias"]),
  556. dbesc($data["name"]),
  557. dbesc($data["nick"]),
  558. dbesc(datetime_convert()),
  559. dbesc(datetime_convert()),
  560. intval($contact_id)
  561. );
  562. }
  563. return $contact_id;
  564. }
  565. /**
  566. * @brief Returns posts from a given gcontact
  567. *
  568. * @param App $a argv application class
  569. * @param int $gcontact_id Global contact
  570. *
  571. * @return string posts in HTML
  572. */
  573. function posts_from_gcontact(App $a, $gcontact_id) {
  574. require_once('include/conversation.php');
  575. // There are no posts with "uid = 0" with connector networks
  576. // This speeds up the query a lot
  577. $r = q("SELECT `network` FROM `gcontact` WHERE `id` = %d", dbesc($gcontact_id));
  578. if (in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, "")))
  579. $sql = "(`item`.`uid` = 0 OR (`item`.`uid` = %d AND `item`.`private`))";
  580. else
  581. $sql = "`item`.`uid` = %d";
  582. $r = q("SELECT `item`.`uri`, `item`.*, `item`.`id` AS `item_id`,
  583. `author-name` AS `name`, `owner-avatar` AS `photo`,
  584. `owner-link` AS `url`, `owner-avatar` AS `thumb`
  585. FROM `item`
  586. WHERE `gcontact-id` = %d AND $sql AND
  587. NOT `deleted` AND NOT `moderated` AND `visible`
  588. ORDER BY `item`.`created` DESC LIMIT %d, %d",
  589. intval($gcontact_id),
  590. intval(local_user()),
  591. intval($a->pager['start']),
  592. intval($a->pager['itemspage'])
  593. );
  594. $o = conversation($a, $r, 'community', false);
  595. $o .= alt_pager($a, count($r));
  596. return $o;
  597. }
  598. /**
  599. * @brief Returns posts from a given contact url
  600. *
  601. * @param App $a argv application class
  602. * @param string $contact_url Contact URL
  603. *
  604. * @return string posts in HTML
  605. */
  606. function posts_from_contact_url(App $a, $contact_url) {
  607. require_once('include/conversation.php');
  608. // There are no posts with "uid = 0" with connector networks
  609. // This speeds up the query a lot
  610. $r = q("SELECT `network`, `id` AS `author-id` FROM `contact`
  611. WHERE `contact`.`nurl` = '%s' AND `contact`.`uid` = 0",
  612. dbesc(normalise_link($contact_url)));
  613. if (in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""))) {
  614. $sql = "(`item`.`uid` = 0 OR (`item`.`uid` = %d AND `item`.`private`))";
  615. } else {
  616. $sql = "`item`.`uid` = %d";
  617. }
  618. if (!dbm::is_result($r)) {
  619. return '';
  620. }
  621. $author_id = intval($r[0]["author-id"]);
  622. $r = q(item_query()." AND `item`.`author-id` = %d AND ".$sql.
  623. " ORDER BY `item`.`created` DESC LIMIT %d, %d",
  624. intval($author_id),
  625. intval(local_user()),
  626. intval($a->pager['start']),
  627. intval($a->pager['itemspage'])
  628. );
  629. $o = conversation($a, $r, 'community', false);
  630. $o .= alt_pager($a, count($r));
  631. return $o;
  632. }
  633. /**
  634. * @brief Returns a formatted location string from the given profile array
  635. *
  636. * @param array $profile Profile array (Generated from the "profile" table)
  637. *
  638. * @return string Location string
  639. */
  640. function formatted_location($profile) {
  641. $location = '';
  642. if($profile['locality'])
  643. $location .= $profile['locality'];
  644. if($profile['region'] AND ($profile['locality'] != $profile['region'])) {
  645. if($location)
  646. $location .= ', ';
  647. $location .= $profile['region'];
  648. }
  649. if($profile['country-name']) {
  650. if($location)
  651. $location .= ', ';
  652. $location .= $profile['country-name'];
  653. }
  654. return $location;
  655. }
  656. /**
  657. * @brief Returns the account type name
  658. *
  659. * The function can be called with either the user or the contact array
  660. *
  661. * @param array $contact contact or user array
  662. */
  663. function account_type($contact) {
  664. // There are several fields that indicate that the contact or user is a forum
  665. // "page-flags" is a field in the user table,
  666. // "forum" and "prv" are used in the contact table. They stand for PAGE_COMMUNITY and PAGE_PRVGROUP.
  667. // "community" is used in the gcontact table and is true if the contact is PAGE_COMMUNITY or PAGE_PRVGROUP.
  668. if((isset($contact['page-flags']) && (intval($contact['page-flags']) == PAGE_COMMUNITY))
  669. || (isset($contact['page-flags']) && (intval($contact['page-flags']) == PAGE_PRVGROUP))
  670. || (isset($contact['forum']) && intval($contact['forum']))
  671. || (isset($contact['prv']) && intval($contact['prv']))
  672. || (isset($contact['community']) && intval($contact['community'])))
  673. $type = ACCOUNT_TYPE_COMMUNITY;
  674. else
  675. $type = ACCOUNT_TYPE_PERSON;
  676. // The "contact-type" (contact table) and "account-type" (user table) are more general then the chaos from above.
  677. if (isset($contact["contact-type"]))
  678. $type = $contact["contact-type"];
  679. if (isset($contact["account-type"]))
  680. $type = $contact["account-type"];
  681. switch($type) {
  682. case ACCOUNT_TYPE_ORGANISATION:
  683. $account_type = t("Organisation");
  684. break;
  685. case ACCOUNT_TYPE_NEWS:
  686. $account_type = t('News');
  687. break;
  688. case ACCOUNT_TYPE_COMMUNITY:
  689. $account_type = t("Forum");
  690. break;
  691. default:
  692. $account_type = "";
  693. break;
  694. }
  695. return $account_type;
  696. }