3 * @copyright Copyright (C) 2020, Friendica
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 use Friendica\Core\Protocol;
24 use Friendica\Core\Renderer;
26 use Friendica\Model\Contact;
27 use Friendica\Model\Profile;
28 use Friendica\Model\Item;
29 use Friendica\Network\Probe;
30 use Friendica\Database\DBA;
31 use Friendica\Util\Strings;
33 function follow_post(App $a)
36 throw new \Friendica\Network\HTTPException\ForbiddenException(DI::l10n()->t('Access denied.'));
39 if (isset($_REQUEST['cancel'])) {
40 DI::baseUrl()->redirect('contact');
44 $url = Probe::cleanURI($_REQUEST['url']);
45 $return_path = 'follow?url=' . urlencode($url);
47 // Makes the connection request for friendica contacts easier
48 // This is just a precaution if maybe this page is called somewhere directly via POST
49 $_SESSION['fastlane'] = $url;
51 $result = Contact::createFromProbe($uid, $url, true);
53 if ($result['success'] == false) {
54 // Possibly it is a remote item and not an account
55 follow_remote_item($url);
57 if ($result['message']) {
58 notice($result['message']);
60 DI::baseUrl()->redirect($return_path);
61 } elseif ($result['cid']) {
62 DI::baseUrl()->redirect('contact/' . $result['cid']);
65 info(DI::l10n()->t('The contact could not be added.'));
67 DI::baseUrl()->redirect($return_path);
71 function follow_content(App $a)
73 $return_path = 'contact';
76 notice(DI::l10n()->t('Permission denied.'));
77 DI::baseUrl()->redirect($return_path);
83 // Issue 4815: Silently removing a prefixing @
84 $url = ltrim(Strings::escapeTags(trim($_REQUEST['url'] ?? '')), '@!');
86 // Issue 6874: Allow remote following from Peertube
87 if (strpos($url, 'acct:') === 0) {
88 $url = str_replace('acct:', '', $url);
92 DI::baseUrl()->redirect($return_path);
95 $submit = DI::l10n()->t('Submit Request');
97 // Don't try to add a pending contact
98 $r = q("SELECT `pending` FROM `contact` WHERE `uid` = %d AND ((`rel` != %d) OR (`network` = '%s')) AND
99 (`nurl` = '%s' OR `alias` = '%s' OR `alias` = '%s') AND
100 `network` != '%s' LIMIT 1",
101 intval(local_user()), DBA::escape(Contact::FOLLOWER), DBA::escape(Protocol::DFRN), DBA::escape(Strings::normaliseLink($url)),
102 DBA::escape(Strings::normaliseLink($url)), DBA::escape($url), DBA::escape(Protocol::STATUSNET));
105 if ($r[0]['pending']) {
106 notice(DI::l10n()->t('You already added this contact.'));
108 //$a->internalRedirect($_SESSION['return_path']);
113 $ret = Probe::uri($url);
115 $protocol = Contact::getProtocol($ret['url'], $ret['network']);
117 if (($protocol == Protocol::DIASPORA) && !DI::config()->get('system', 'diaspora_enabled')) {
118 notice(DI::l10n()->t("Diaspora support isn't enabled. Contact can't be added."));
120 //$a->internalRedirect($_SESSION['return_path']);
124 if (($protocol == Protocol::OSTATUS) && DI::config()->get('system', 'ostatus_disabled')) {
125 notice(DI::l10n()->t("OStatus support is disabled. Contact can't be added."));
127 //$a->internalRedirect($_SESSION['return_path']);
131 if ($protocol == Protocol::PHANTOM) {
132 // Possibly it is a remote item and not an account
133 follow_remote_item($url);
135 notice(DI::l10n()->t("The network type couldn't be detected. Contact can't be added."));
137 //$a->internalRedirect($_SESSION['return_path']);
141 if ($protocol == Protocol::MAIL) {
142 $ret['url'] = $ret['addr'];
145 if (($protocol === Protocol::DFRN) && !DBA::isResult($r)) {
146 $request = $ret['request'];
147 $tpl = Renderer::getMarkupTemplate('dfrn_request.tpl');
149 $request = DI::baseUrl() . '/follow';
150 $tpl = Renderer::getMarkupTemplate('auto_request.tpl');
153 $r = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1", intval($uid));
156 notice(DI::l10n()->t('Permission denied.'));
157 DI::baseUrl()->redirect($return_path);
161 $myaddr = $r[0]['url'];
164 // Makes the connection request for friendica contacts easier
165 $_SESSION['fastlane'] = $ret['url'];
167 $r = q("SELECT `id`, `location`, `about`, `keywords` FROM `gcontact` WHERE `nurl` = '%s'",
168 Strings::normaliseLink($ret['url']));
171 $r = [['location' => '', 'about' => '', 'keywords' => '']];
173 $gcontact_id = $r[0]['id'];
176 if ($protocol === Protocol::DIASPORA) {
177 $r[0]['location'] = '';
181 $o = Renderer::replaceMacros($tpl, [
182 '$header' => DI::l10n()->t('Connect/Follow'),
183 '$pls_answer' => DI::l10n()->t('Please answer the following:'),
184 '$your_address' => DI::l10n()->t('Your Identity Address:'),
185 '$url_label' => DI::l10n()->t('Profile URL'),
186 '$keywords_label'=> DI::l10n()->t('Tags:'),
187 '$submit' => $submit,
188 '$cancel' => DI::l10n()->t('Cancel'),
190 '$request' => $request,
191 '$name' => $ret['name'],
192 '$url' => $ret['url'],
193 '$zrl' => Profile::zrl($ret['url']),
194 '$myaddr' => $myaddr,
195 '$keywords' => $r[0]['keywords'],
197 '$does_know_you' => ['knowyou', DI::l10n()->t('%s knows you', $ret['name'])],
198 '$addnote_field' => ['dfrn-request-message', DI::l10n()->t('Add a personal note:')],
201 DI::page()['aside'] = '';
203 $profiledata = Contact::getDetailsByURL($ret['url']);
205 Profile::load($a, '', $profiledata, false);
208 if ($gcontact_id <> 0) {
209 $o .= Renderer::replaceMacros(Renderer::getMarkupTemplate('section_title.tpl'),
210 ['$title' => DI::l10n()->t('Status Messages and Posts')]
213 // Show last public posts
214 $o .= Contact::getPostsFromUrl($ret['url']);
220 function follow_remote_item($url)
222 $item_id = Item::fetchByLink($url, local_user());
224 // If the user-specific search failed, we search and probe a public post
225 $item_id = Item::fetchByLink($url);
228 if (!empty($item_id)) {
229 $item = Item::selectFirst(['guid'], ['id' => $item_id]);
230 if (DBA::isResult($item)) {
231 DI::baseUrl()->redirect('display/' . $item['guid']);