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.

666 lines
22KB

  1. <?php
  2. /**
  3. * @file mod/dfrn_request.php
  4. * @brief Module: dfrn_request
  5. *
  6. * Purpose: Handles communication associated with the issuance of
  7. * friend requests.
  8. *
  9. * @see PDF with dfrn specs: https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf
  10. * You also find a graphic which describes the confirmation process at
  11. * https://github.com/friendica/friendica/blob/master/spec/dfrn2_contact_request.png
  12. */
  13. use Friendica\App;
  14. use Friendica\Core\Config;
  15. use Friendica\Core\L10n;
  16. use Friendica\Core\Logger;
  17. use Friendica\Core\Protocol;
  18. use Friendica\Core\Renderer;
  19. use Friendica\Core\System;
  20. use Friendica\Database\DBA;
  21. use Friendica\Model\Contact;
  22. use Friendica\Model\Group;
  23. use Friendica\Model\Profile;
  24. use Friendica\Model\User;
  25. use Friendica\Module\Login;
  26. use Friendica\Network\Probe;
  27. use Friendica\Util\DateTimeFormat;
  28. use Friendica\Util\Network;
  29. use Friendica\Util\Strings;
  30. function dfrn_request_init(App $a)
  31. {
  32. if ($a->argc > 1) {
  33. $which = $a->argv[1];
  34. }
  35. Profile::load($a, $which);
  36. return;
  37. }
  38. /**
  39. * Function: dfrn_request_post
  40. *
  41. * Purpose:
  42. * Handles multiple scenarios.
  43. *
  44. * Scenario 1:
  45. * Clicking 'submit' on a friend request page.
  46. *
  47. * Scenario 2:
  48. * Following Scenario 1, we are brought back to our home site
  49. * in order to link our friend request with our own server cell.
  50. * After logging in, we click 'submit' to approve the linkage.
  51. *
  52. */
  53. function dfrn_request_post(App $a)
  54. {
  55. if (($a->argc != 2) || (!count($a->profile))) {
  56. Logger::log('Wrong count of argc or profiles: argc=' . $a->argc . ',profile()=' . count($a->profile));
  57. return;
  58. }
  59. if (!empty($_POST['cancel'])) {
  60. $a->internalRedirect();
  61. }
  62. /*
  63. * Scenario 2: We've introduced ourself to another cell, then have been returned to our own cell
  64. * to confirm the request, and then we've clicked submit (perhaps after logging in).
  65. * That brings us here:
  66. */
  67. if (!empty($_POST['localconfirm']) && ($_POST['localconfirm'] == 1)) {
  68. // Ensure this is a valid request
  69. if (local_user() && ($a->user['nickname'] == $a->argv[1]) && !empty($_POST['dfrn_url'])) {
  70. $dfrn_url = Strings::escapeTags(trim($_POST['dfrn_url']));
  71. $aes_allow = !empty($_POST['aes_allow']);
  72. $confirm_key = defaults($_POST, 'confirm_key', "");
  73. $hidden = (!empty($_POST['hidden-contact']) ? intval($_POST['hidden-contact']) : 0);
  74. $contact_record = null;
  75. $blocked = 1;
  76. $pending = 1;
  77. if (!empty($dfrn_url)) {
  78. // Lookup the contact based on their URL (which is the only unique thing we have at the moment)
  79. $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND NOT `self` LIMIT 1",
  80. intval(local_user()),
  81. DBA::escape(Strings::normaliseLink($dfrn_url))
  82. );
  83. if (DBA::isResult($r)) {
  84. if (strlen($r[0]['dfrn-id'])) {
  85. // We don't need to be here. It has already happened.
  86. notice(L10n::t("This introduction has already been accepted.") . EOL);
  87. return;
  88. } else {
  89. $contact_record = $r[0];
  90. }
  91. }
  92. if (is_array($contact_record)) {
  93. $r = q("UPDATE `contact` SET `ret-aes` = %d, hidden = %d WHERE `id` = %d",
  94. intval($aes_allow),
  95. intval($hidden),
  96. intval($contact_record['id'])
  97. );
  98. } else {
  99. // Scrape the other site's profile page to pick up the dfrn links, key, fn, and photo
  100. $parms = Probe::profile($dfrn_url);
  101. if (!count($parms)) {
  102. notice(L10n::t('Profile location is not valid or does not contain profile information.') . EOL);
  103. return;
  104. } else {
  105. if (empty($parms['fn'])) {
  106. notice(L10n::t('Warning: profile location has no identifiable owner name.') . EOL);
  107. }
  108. if (empty($parms['photo'])) {
  109. notice(L10n::t('Warning: profile location has no profile photo.') . EOL);
  110. }
  111. $invalid = Probe::validDfrn($parms);
  112. if ($invalid) {
  113. notice(L10n::tt("%d required parameter was not found at the given location", "%d required parameters were not found at the given location", $invalid) . EOL);
  114. return;
  115. }
  116. }
  117. $dfrn_request = $parms['dfrn-request'];
  118. $photo = $parms["photo"];
  119. // Escape the entire array
  120. DBA::escapeArray($parms);
  121. // Create a contact record on our site for the other person
  122. $r = q("INSERT INTO `contact` ( `uid`, `created`,`url`, `nurl`, `addr`, `name`, `nick`, `photo`, `site-pubkey`,
  123. `request`, `confirm`, `notify`, `poll`, `network`, `aes_allow`, `hidden`, `blocked`, `pending`)
  124. VALUES ( %d, '%s', '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d)",
  125. intval(local_user()),
  126. DateTimeFormat::utcNow(),
  127. DBA::escape($dfrn_url),
  128. DBA::escape(Strings::normaliseLink($dfrn_url)),
  129. $parms['addr'],
  130. $parms['fn'],
  131. $parms['nick'],
  132. $parms['photo'],
  133. $parms['key'],
  134. $parms['dfrn-request'],
  135. $parms['dfrn-confirm'],
  136. $parms['dfrn-notify'],
  137. $parms['dfrn-poll'],
  138. DBA::escape(Protocol::DFRN),
  139. intval($aes_allow),
  140. intval($hidden),
  141. intval($blocked),
  142. intval($pending)
  143. );
  144. }
  145. if ($r) {
  146. info(L10n::t("Introduction complete.") . EOL);
  147. }
  148. $r = q("SELECT `id`, `network` FROM `contact` WHERE `uid` = %d AND `url` = '%s' AND `site-pubkey` = '%s' LIMIT 1",
  149. intval(local_user()),
  150. DBA::escape($dfrn_url),
  151. $parms['key'] // this was already escaped
  152. );
  153. if (DBA::isResult($r)) {
  154. Group::addMember(User::getDefaultGroup(local_user(), $r[0]["network"]), $r[0]['id']);
  155. if (isset($photo)) {
  156. Contact::updateAvatar($photo, local_user(), $r[0]["id"], true);
  157. }
  158. $forward_path = "contact/" . $r[0]['id'];
  159. } else {
  160. $forward_path = "contact";
  161. }
  162. // Allow the blocked remote notification to complete
  163. if (is_array($contact_record)) {
  164. $dfrn_request = $contact_record['request'];
  165. }
  166. if (strlen($dfrn_request) && strlen($confirm_key)) {
  167. $s = Network::fetchUrl($dfrn_request . '?confirm_key=' . $confirm_key);
  168. }
  169. // (ignore reply, nothing we can do it failed)
  170. $a->internalRedirect($forward_path);
  171. return; // NOTREACHED
  172. }
  173. }
  174. // invalid/bogus request
  175. notice(L10n::t('Unrecoverable protocol error.') . EOL);
  176. $a->internalRedirect();
  177. return; // NOTREACHED
  178. }
  179. /*
  180. * Otherwise:
  181. *
  182. * Scenario 1:
  183. * We are the requestee. A person from a remote cell has made an introduction
  184. * on our profile web page and clicked submit. We will use their DFRN-URL to
  185. * figure out how to contact their cell.
  186. *
  187. * Scrape the originating DFRN-URL for everything we need. Create a contact record
  188. * and an introduction to show our user next time he/she logs in.
  189. * Finally redirect back to the requestor so that their site can record the request.
  190. * If our user (the requestee) later confirms this request, a record of it will need
  191. * to exist on the requestor's cell in order for the confirmation process to complete..
  192. *
  193. * It's possible that neither the requestor or the requestee are logged in at the moment,
  194. * and the requestor does not yet have any credentials to the requestee profile.
  195. *
  196. * Who is the requestee? We've already loaded their profile which means their nickname should be
  197. * in $a->argv[1] and we should have their complete info in $a->profile.
  198. *
  199. */
  200. if (!(is_array($a->profile) && count($a->profile))) {
  201. notice(L10n::t('Profile unavailable.') . EOL);
  202. return;
  203. }
  204. $nickname = $a->profile['nickname'];
  205. $notify_flags = $a->profile['notify-flags'];
  206. $uid = $a->profile['uid'];
  207. $maxreq = intval($a->profile['maxreq']);
  208. $contact_record = null;
  209. $failed = false;
  210. $parms = null;
  211. $blocked = 1;
  212. $pending = 1;
  213. if (!empty($_POST['dfrn_url'])) {
  214. // Block friend request spam
  215. if ($maxreq) {
  216. $r = q("SELECT * FROM `intro` WHERE `datetime` > '%s' AND `uid` = %d",
  217. DBA::escape(DateTimeFormat::utc('now - 24 hours')),
  218. intval($uid)
  219. );
  220. if (DBA::isResult($r) && count($r) > $maxreq) {
  221. notice(L10n::t('%s has received too many connection requests today.', $a->profile['name']) . EOL);
  222. notice(L10n::t('Spam protection measures have been invoked.') . EOL);
  223. notice(L10n::t('Friends are advised to please try again in 24 hours.') . EOL);
  224. return;
  225. }
  226. }
  227. /* Cleanup old introductions that remain blocked.
  228. * Also remove the contact record, but only if there is no existing relationship
  229. */
  230. $r = q("SELECT `intro`.*, `intro`.`id` AS `iid`, `contact`.`id` AS `cid`, `contact`.`rel`
  231. FROM `intro` LEFT JOIN `contact` on `intro`.`contact-id` = `contact`.`id`
  232. WHERE `intro`.`blocked` = 1 AND `contact`.`self` = 0
  233. AND `intro`.`datetime` < UTC_TIMESTAMP() - INTERVAL 30 MINUTE "
  234. );
  235. if (DBA::isResult($r)) {
  236. foreach ($r as $rr) {
  237. if (!$rr['rel']) {
  238. DBA::delete('contact', ['id' => $rr['cid'], 'self' => false]);
  239. }
  240. DBA::delete('intro', ['id' => $rr['iid']]);
  241. }
  242. }
  243. $real_name = !empty($_POST['realname']) ? Strings::escapeTags(trim($_POST['realname'])) : '';
  244. $url = trim($_POST['dfrn_url']);
  245. if (!strlen($url)) {
  246. notice(L10n::t("Invalid locator") . EOL);
  247. return;
  248. }
  249. $hcard = '';
  250. // Detect the network
  251. $data = Probe::uri($url);
  252. $network = $data["network"];
  253. // Canonicalise email-style profile locator
  254. $url = Probe::webfingerDfrn($url, $hcard);
  255. if (substr($url, 0, 5) === 'stat:') {
  256. // Every time we detect the remote subscription we define this as OStatus.
  257. // We do this even if it is not OStatus.
  258. // we only need to pass this through another section of the code.
  259. if ($network != Protocol::DIASPORA) {
  260. $network = Protocol::OSTATUS;
  261. }
  262. $url = substr($url, 5);
  263. } else {
  264. $network = Protocol::DFRN;
  265. }
  266. Logger::log('dfrn_request: url: ' . $url . ',network=' . $network, Logger::DEBUG);
  267. if ($network === Protocol::DFRN) {
  268. $ret = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' AND `self` = 0 LIMIT 1",
  269. intval($uid),
  270. DBA::escape($url)
  271. );
  272. if (DBA::isResult($ret)) {
  273. if (strlen($ret[0]['issued-id'])) {
  274. notice(L10n::t('You have already introduced yourself here.') . EOL);
  275. return;
  276. } elseif ($ret[0]['rel'] == Contact::FRIEND) {
  277. notice(L10n::t('Apparently you are already friends with %s.', $a->profile['name']) . EOL);
  278. return;
  279. } else {
  280. $contact_record = $ret[0];
  281. $parms = ['dfrn-request' => $ret[0]['request']];
  282. }
  283. }
  284. $issued_id = Strings::getRandomHex();
  285. if (is_array($contact_record)) {
  286. // There is a contact record but no issued-id, so this
  287. // is a reciprocal introduction from a known contact
  288. $r = q("UPDATE `contact` SET `issued-id` = '%s' WHERE `id` = %d",
  289. DBA::escape($issued_id),
  290. intval($contact_record['id'])
  291. );
  292. } else {
  293. $url = Network::isUrlValid($url);
  294. if (!$url) {
  295. notice(L10n::t('Invalid profile URL.') . EOL);
  296. $a->internalRedirect($a->cmd);
  297. return; // NOTREACHED
  298. }
  299. if (!Network::isUrlAllowed($url)) {
  300. notice(L10n::t('Disallowed profile URL.') . EOL);
  301. $a->internalRedirect($a->cmd);
  302. return; // NOTREACHED
  303. }
  304. if (Network::isUrlBlocked($url)) {
  305. notice(L10n::t('Blocked domain') . EOL);
  306. $a->internalRedirect($a->cmd);
  307. return; // NOTREACHED
  308. }
  309. $parms = Probe::profile(($hcard) ? $hcard : $url);
  310. if (!count($parms)) {
  311. notice(L10n::t('Profile location is not valid or does not contain profile information.') . EOL);
  312. $a->internalRedirect($a->cmd);
  313. } else {
  314. if (empty($parms['fn'])) {
  315. notice(L10n::t('Warning: profile location has no identifiable owner name.') . EOL);
  316. }
  317. if (empty($parms['photo'])) {
  318. notice(L10n::t('Warning: profile location has no profile photo.') . EOL);
  319. }
  320. $invalid = Probe::validDfrn($parms);
  321. if ($invalid) {
  322. notice(L10n::tt("%d required parameter was not found at the given location", "%d required parameters were not found at the given location", $invalid) . EOL);
  323. return;
  324. }
  325. }
  326. $parms['url'] = $url;
  327. $parms['issued-id'] = $issued_id;
  328. $photo = $parms["photo"];
  329. DBA::escapeArray($parms);
  330. $r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `name`, `nick`, `issued-id`, `photo`, `site-pubkey`,
  331. `request`, `confirm`, `notify`, `poll`, `network`, `blocked`, `pending` )
  332. VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d )",
  333. intval($uid),
  334. DBA::escape(DateTimeFormat::utcNow()),
  335. $parms['url'],
  336. DBA::escape(Strings::normaliseLink($url)),
  337. $parms['addr'],
  338. $parms['fn'],
  339. $parms['nick'],
  340. $parms['issued-id'],
  341. $parms['photo'],
  342. $parms['key'],
  343. $parms['dfrn-request'],
  344. $parms['dfrn-confirm'],
  345. $parms['dfrn-notify'],
  346. $parms['dfrn-poll'],
  347. DBA::escape(Protocol::DFRN),
  348. intval($blocked),
  349. intval($pending)
  350. );
  351. // find the contact record we just created
  352. if ($r) {
  353. $r = q("SELECT `id` FROM `contact`
  354. WHERE `uid` = %d AND `url` = '%s' AND `issued-id` = '%s' LIMIT 1",
  355. intval($uid),
  356. $parms['url'],
  357. $parms['issued-id']
  358. );
  359. if (DBA::isResult($r)) {
  360. $contact_record = $r[0];
  361. Contact::updateAvatar($photo, $uid, $contact_record["id"], true);
  362. }
  363. }
  364. }
  365. if ($r === false) {
  366. notice(L10n::t('Failed to update contact record.') . EOL);
  367. return;
  368. }
  369. $hash = Strings::getRandomHex() . (string) time(); // Generate a confirm_key
  370. if (is_array($contact_record)) {
  371. $ret = q("INSERT INTO `intro` ( `uid`, `contact-id`, `blocked`, `knowyou`, `note`, `hash`, `datetime`)
  372. VALUES ( %d, %d, 1, %d, '%s', '%s', '%s' )",
  373. intval($uid),
  374. intval($contact_record['id']),
  375. intval(!empty($_POST['knowyou'])),
  376. DBA::escape(Strings::escapeTags(trim(defaults($_POST, 'dfrn-request-message', '')))),
  377. DBA::escape($hash),
  378. DBA::escape(DateTimeFormat::utcNow())
  379. );
  380. }
  381. // This notice will only be seen by the requestor if the requestor and requestee are on the same server.
  382. if (!$failed) {
  383. info(L10n::t('Your introduction has been sent.') . EOL);
  384. }
  385. // "Homecoming" - send the requestor back to their site to record the introduction.
  386. $dfrn_url = bin2hex($a->getBaseURL() . '/profile/' . $nickname);
  387. $aes_allow = ((function_exists('openssl_encrypt')) ? 1 : 0);
  388. System::externalRedirect($parms['dfrn-request'] . "?dfrn_url=$dfrn_url"
  389. . '&dfrn_version=' . DFRN_PROTOCOL_VERSION
  390. . '&confirm_key=' . $hash
  391. . (($aes_allow) ? "&aes_allow=1" : "")
  392. );
  393. // NOTREACHED
  394. // END $network === Protocol::DFRN
  395. } elseif (($network != Protocol::PHANTOM) && ($url != "")) {
  396. /* Substitute our user's feed URL into $url template
  397. * Send the subscriber home to subscribe
  398. */
  399. // Diaspora needs the uri in the format user@domain.tld
  400. // Diaspora will support the remote subscription in a future version
  401. if ($network == Protocol::DIASPORA) {
  402. $uri = $nickname . '@' . $a->getHostName();
  403. if ($a->getURLPath()) {
  404. $uri .= '/' . $a->getURLPath();
  405. }
  406. $uri = urlencode($uri);
  407. } else {
  408. $uri = 'profile/' . $nickname;
  409. }
  410. $url = str_replace('{uri}', $uri, $url);
  411. System::externalRedirect($url);
  412. // NOTREACHED
  413. // END $network != Protocol::PHANTOM
  414. } else {
  415. notice(L10n::t("Remote subscription can't be done for your network. Please subscribe directly on your system.") . EOL);
  416. return;
  417. }
  418. } return;
  419. }
  420. function dfrn_request_content(App $a)
  421. {
  422. if (($a->argc != 2) || (!count($a->profile))) {
  423. return "";
  424. }
  425. // "Homecoming". Make sure we're logged in to this site as the correct user. Then offer a confirm button
  426. // to send us to the post section to record the introduction.
  427. if (!empty($_GET['dfrn_url'])) {
  428. if (!local_user()) {
  429. info(L10n::t("Please login to confirm introduction.") . EOL);
  430. /* setup the return URL to come back to this page if they use openid */
  431. return Login::form();
  432. }
  433. // Edge case, but can easily happen in the wild. This person is authenticated,
  434. // but not as the person who needs to deal with this request.
  435. if ($a->user['nickname'] != $a->argv[1]) {
  436. notice(L10n::t("Incorrect identity currently logged in. Please login to <strong>this</strong> profile.") . EOL);
  437. return Login::form();
  438. }
  439. $dfrn_url = Strings::escapeTags(trim(hex2bin($_GET['dfrn_url'])));
  440. $aes_allow = !empty($_GET['aes_allow']);
  441. $confirm_key = defaults($_GET, 'confirm_key', "");
  442. // Checking fastlane for validity
  443. if (!empty($_SESSION['fastlane']) && (Strings::normaliseLink($_SESSION["fastlane"]) == Strings::normaliseLink($dfrn_url))) {
  444. $_POST["dfrn_url"] = $dfrn_url;
  445. $_POST["confirm_key"] = $confirm_key;
  446. $_POST["localconfirm"] = 1;
  447. $_POST["hidden-contact"] = 0;
  448. $_POST["submit"] = L10n::t('Confirm');
  449. dfrn_request_post($a);
  450. killme();
  451. return; // NOTREACHED
  452. }
  453. $tpl = Renderer::getMarkupTemplate("dfrn_req_confirm.tpl");
  454. $o = Renderer::replaceMacros($tpl, [
  455. '$dfrn_url' => $dfrn_url,
  456. '$aes_allow' => (($aes_allow) ? '<input type="hidden" name="aes_allow" value="1" />' : "" ),
  457. '$hidethem' => L10n::t('Hide this contact'),
  458. '$hidechecked' => '',
  459. '$confirm_key' => $confirm_key,
  460. '$welcome' => L10n::t('Welcome home %s.', $a->user['username']),
  461. '$please' => L10n::t('Please confirm your introduction/connection request to %s.', $dfrn_url),
  462. '$submit' => L10n::t('Confirm'),
  463. '$uid' => $_SESSION['uid'],
  464. '$nickname' => $a->user['nickname'],
  465. 'dfrn_rawurl' => $_GET['dfrn_url']
  466. ]);
  467. return $o;
  468. } elseif (!empty($_GET['confirm_key'])) {
  469. // we are the requestee and it is now safe to send our user their introduction,
  470. // We could just unblock it, but first we have to jump through a few hoops to
  471. // send an email, or even to find out if we need to send an email.
  472. $intro = q("SELECT * FROM `intro` WHERE `hash` = '%s' LIMIT 1",
  473. DBA::escape($_GET['confirm_key'])
  474. );
  475. if (DBA::isResult($intro)) {
  476. $r = q("SELECT `contact`.*, `user`.* FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
  477. WHERE `contact`.`id` = %d LIMIT 1",
  478. intval($intro[0]['contact-id'])
  479. );
  480. $auto_confirm = false;
  481. if (DBA::isResult($r)) {
  482. if ($r[0]['page-flags'] != Contact::PAGE_NORMAL && $r[0]['page-flags'] != Contact::PAGE_PRVGROUP) {
  483. $auto_confirm = true;
  484. }
  485. if (!$auto_confirm) {
  486. notification([
  487. 'type' => NOTIFY_INTRO,
  488. 'notify_flags' => $r[0]['notify-flags'],
  489. 'language' => $r[0]['language'],
  490. 'to_name' => $r[0]['username'],
  491. 'to_email' => $r[0]['email'],
  492. 'uid' => $r[0]['uid'],
  493. 'link' => System::baseUrl() . '/notifications/intros',
  494. 'source_name' => ((strlen(stripslashes($r[0]['name']))) ? stripslashes($r[0]['name']) : L10n::t('[Name Withheld]')),
  495. 'source_link' => $r[0]['url'],
  496. 'source_photo' => $r[0]['photo'],
  497. 'verb' => ACTIVITY_REQ_FRIEND,
  498. 'otype' => 'intro'
  499. ]);
  500. }
  501. if ($auto_confirm) {
  502. require_once 'mod/dfrn_confirm.php';
  503. $handsfree = [
  504. 'uid' => $r[0]['uid'],
  505. 'node' => $r[0]['nickname'],
  506. 'dfrn_id' => $r[0]['issued-id'],
  507. 'intro_id' => $intro[0]['id'],
  508. 'duplex' => (($r[0]['page-flags'] == Contact::PAGE_FREELOVE) ? 1 : 0),
  509. ];
  510. dfrn_confirm_post($a, $handsfree);
  511. }
  512. }
  513. if (!$auto_confirm) {
  514. // If we are auto_confirming, this record will have already been nuked
  515. // in dfrn_confirm_post()
  516. $r = q("UPDATE `intro` SET `blocked` = 0 WHERE `hash` = '%s'",
  517. DBA::escape($_GET['confirm_key'])
  518. );
  519. }
  520. }
  521. killme();
  522. return; // NOTREACHED
  523. } else {
  524. // Normal web request. Display our user's introduction form.
  525. if ((Config::get('system', 'block_public')) && (!local_user()) && (!remote_user())) {
  526. if (!Config::get('system', 'local_block')) {
  527. notice(L10n::t('Public access denied.') . EOL);
  528. return;
  529. }
  530. }
  531. // Try to auto-fill the profile address
  532. // At first look if an address was provided
  533. // Otherwise take the local address
  534. if (!empty($_GET['addr'])) {
  535. $myaddr = hex2bin($_GET['addr']);
  536. } elseif (!empty($_GET['address'])) {
  537. $myaddr = $_GET['address'];
  538. } elseif (local_user()) {
  539. if (strlen($a->getURLPath())) {
  540. $myaddr = System::baseUrl() . '/profile/' . $a->user['nickname'];
  541. } else {
  542. $myaddr = $a->user['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3);
  543. }
  544. } else {
  545. // last, try a zrl
  546. $myaddr = Profile::getMyURL();
  547. }
  548. $target_addr = $a->profile['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3);
  549. /* The auto_request form only has the profile address
  550. * because nobody is going to read the comments and
  551. * it doesn't matter if they know you or not.
  552. */
  553. if ($a->profile['page-flags'] == Contact::PAGE_NORMAL) {
  554. $tpl = Renderer::getMarkupTemplate('dfrn_request.tpl');
  555. } else {
  556. $tpl = Renderer::getMarkupTemplate('auto_request.tpl');
  557. }
  558. $page_desc = L10n::t("Please enter your 'Identity Address' from one of the following supported communications networks:");
  559. $invite_desc = sprintf(
  560. L10n::t('If you are not yet a member of the free social web, <a href="%s">follow this link to find a public Friendica site and join us today</a>.'),
  561. get_server() . '/servers'
  562. );
  563. $o = Renderer::replaceMacros($tpl, [
  564. '$header' => L10n::t('Friend/Connection Request'),
  565. '$desc' => L10n::t('Examples: jojo@demo.friendica.com, http://demo.friendica.com/profile/jojo, testuser@gnusocial.de'),
  566. '$pls_answer' => L10n::t('Please answer the following:'),
  567. '$does_know_you' => ['knowyou', L10n::t('Does %s know you?', $a->profile['name']), false, '', [L10n::t('No'), L10n::t('Yes')]],
  568. '$add_note' => L10n::t('Add a personal note:'),
  569. '$page_desc' => $page_desc,
  570. '$friendica' => L10n::t('Friendica'),
  571. '$statusnet' => L10n::t("GNU Social \x28Pleroma, Mastodon\x29"),
  572. '$diaspora' => L10n::t("Diaspora \x28Socialhome, Hubzilla\x29"),
  573. '$diasnote' => L10n::t(' - please do not use this form. Instead, enter %s into your Diaspora search bar.', $target_addr),
  574. '$your_address' => L10n::t('Your Identity Address:'),
  575. '$invite_desc' => $invite_desc,
  576. '$submit' => L10n::t('Submit Request'),
  577. '$cancel' => L10n::t('Cancel'),
  578. '$nickname' => $a->argv[1],
  579. '$name' => $a->profile['name'],
  580. '$myaddr' => $myaddr
  581. ]);
  582. return $o;
  583. }
  584. return; // Somebody is fishing.
  585. }