3 namespace Friendica\Module;
5 use Friendica\BaseModule;
6 use Friendica\Core\Hook;
7 use Friendica\Core\L10n;
8 use Friendica\Core\Renderer;
9 use Friendica\Core\System;
10 use Friendica\Model\User;
11 use Friendica\Network\Probe;
12 use Friendica\Protocol\Salmon;
13 use Friendica\Util\Strings;
16 * Prints information about people
17 * @see https://tools.ietf.org/html/rfc7033
19 class WebFinger extends BaseModule
21 public static function content()
29 "title" => L10n::t("Public access denied."),
30 "description" => L10n::t("Only logged in users are permitted to perform a probing.")
36 $output = '<div class="generic-page-wrapper">';
37 $output .= '<h3>Webfinger Diagnostic</h3>';
39 $output .= '<form action="webfinger" method="get">';
40 $output .= 'Lookup address: <input type="text" style="width: 250px;" name="addr" value="' . defaults($_GET, 'addr', '') . '" />';
41 $output .= '<input type="submit" name="submit" value="Submit" /></form>';
43 $output .= '<br /><br />';
45 if (!empty($_GET['addr'])) {
46 $addr = trim($_GET['addr']);
47 $res = Probe::lrdd($addr);
49 $output .= str_replace("\n", '<br />', print_r($res, true));
57 public static function rawContent()
61 $app = self::getApp();
63 // @TODO: Replace with parameter from router
64 if ($app->argv[0] == 'xrd') {
65 if (empty($_GET['uri'])) {
69 $uri = urldecode(Strings::escapeTags(trim($_GET['uri'])));
70 if (defaults($_SERVER, 'HTTP_ACCEPT', '') == 'application/jrd+json') {
76 if (empty($_GET['resource'])) {
80 $uri = urldecode(Strings::escapeTags(trim($_GET['resource'])));
81 if (defaults($_SERVER, 'HTTP_ACCEPT', '') == 'application/xrd+xml') {
88 if (substr($uri, 0, 4) === 'http') {
89 $name = ltrim(basename($uri), '~');
91 $local = str_replace('acct:', '', $uri);
92 if (substr($local, 0, 2) == '//') {
93 $local = substr($local, 2);
96 $name = substr($local, 0, strpos($local, '@'));
99 $user = User::getByNickname($name);
102 System::httpExit(404);
105 $profileURL = $app->getBaseURL() . '/profile/' . $user['nickname'];
106 $alias = str_replace('/profile/', '/~', $profileURL);
108 $addr = 'acct:' . $user['nickname'] . '@' . $app->getHostName();
109 if ($app->getURLPath()) {
110 $addr .= '/' . $app->getURLPath();
113 if ($mode == 'xml') {
114 self::printXML($addr, $alias, $profileURL, $app->getBaseURL(), $user);
116 self::printJSON($addr, $alias, $profileURL, $app->getBaseURL(), $user);
120 private static function printJSON($uri, $alias, $orofileURL, $baseURL, $user)
122 $salmon_key = Salmon::salmonKey($user['spubkey']);
124 header('Access-Control-Allow-Origin: *');
125 header("Content-type: application/json; charset=utf-8");
127 $json = ['subject' => $uri,
134 'rel' => NAMESPACE_DFRN,
135 'href' => $orofileURL,
138 'rel' => NAMESPACE_FEED,
139 'type' => 'application/atom+xml',
140 'href' => $baseURL . '/dfrn_poll/' . $user['nickname'],
143 'rel' => 'http://webfinger.net/rel/profile-page',
144 'type' => 'text/html',
145 'href' => $orofileURL,
149 'type' => 'application/activity+json',
150 'href' => $orofileURL,
153 'rel' => 'http://microformats.org/profile/hcard',
154 'type' => 'text/html',
155 'href' => $baseURL . '/hcard/' . $user['nickname'],
158 'rel' => NAMESPACE_POCO,
159 'href' => $baseURL . '/poco/' . $user['nickname'],
162 'rel' => 'http://webfinger.net/rel/avatar',
163 'type' => 'image/jpeg',
164 'href' => $baseURL . '/photo/profile/' . $user['uid'] . '.jpg',
167 'rel' => 'http://joindiaspora.com/seed_location',
168 'type' => 'text/html',
173 'href' => $baseURL . '/salmon/' . $user['nickname'],
176 'rel' => 'http://salmon-protocol.org/ns/salmon-replies',
177 'href' => $baseURL . '/salmon/' . $user['nickname'],
180 'rel' => 'http://salmon-protocol.org/ns/salmon-mention',
181 'href' => $baseURL . '/salmon/' . $user['nickname'] . '/mention',
184 'rel' => 'http://ostatus.org/schema/1.0/subscribe',
185 'template' => $baseURL . '/follow?url={uri}',
188 'rel' => 'magic-public-key',
189 'href' => 'data:application/magic-public-key,' . $salmon_key,
192 'rel' => 'http://purl.org/openwebauth/v1',
193 'type' => 'application/x-zot+json',
194 'href' => $baseURL . '/owa',
199 echo json_encode($json);
203 private static function printXML($uri, $alias, $profileURL, $baseURL, $user)
205 $salmon_key = Salmon::salmonKey($user['spubkey']);
207 header('Access-Control-Allow-Origin: *');
208 header("Content-type: text/xml");
210 $tpl = Renderer::getMarkupTemplate('xrd_person.tpl');
212 $o = Renderer::replaceMacros($tpl, [
213 '$nick' => $user['nickname'],
216 '$profile_url' => $profileURL,
217 '$hcard_url' => $baseURL . '/hcard/' . $user['nickname'],
218 '$atom' => $baseURL . '/dfrn_poll/' . $user['nickname'],
219 '$poco_url' => $baseURL . '/poco/' . $user['nickname'],
220 '$photo' => $baseURL . '/photo/profile/' . $user['uid'] . '.jpg',
221 '$baseurl' => $baseURL,
222 '$salmon' => $baseURL . '/salmon/' . $user['nickname'],
223 '$salmen' => $baseURL . '/salmon/' . $user['nickname'] . '/mention',
224 '$subscribe' => $baseURL . '/follow?url={uri}',
225 '$openwebauth' => $baseURL . '/owa',
226 '$modexp' => 'data:application/magic-public-key,' . $salmon_key]
229 $arr = ['user' => $user, 'xml' => $o];
230 Hook::callAll('personal_xrd', $arr);