3 namespace Friendica\Module;
5 use Friendica\BaseModule;
6 use Friendica\Core\Hook;
7 use Friendica\Core\Renderer;
8 use Friendica\Database\DBA;
10 use Friendica\Model\Photo;
11 use Friendica\Model\User;
12 use Friendica\Protocol\ActivityNamespace;
13 use Friendica\Protocol\Salmon;
14 use Friendica\Util\Strings;
17 * Prints responses to /.well-known/webfinger or /xrd requests
19 class Xrd extends BaseModule
21 public static function rawContent(array $parameters = [])
25 // @TODO: Replace with parameter from router
26 if ($app->argv[0] == 'xrd') {
27 if (empty($_GET['uri'])) {
31 $uri = urldecode(Strings::escapeTags(trim($_GET['uri'])));
32 if (($_SERVER['HTTP_ACCEPT'] ?? '') == 'application/jrd+json') {
38 if (empty($_GET['resource'])) {
42 $uri = urldecode(Strings::escapeTags(trim($_GET['resource'])));
43 if (($_SERVER['HTTP_ACCEPT'] ?? '') == 'application/xrd+xml') {
50 if (substr($uri, 0, 4) === 'http') {
51 $name = ltrim(basename($uri), '~');
53 $local = str_replace('acct:', '', $uri);
54 if (substr($local, 0, 2) == '//') {
55 $local = substr($local, 2);
58 $name = substr($local, 0, strpos($local, '@'));
61 $user = User::getByNickname($name);
64 throw new \Friendica\Network\HTTPException\NotFoundException();
67 $owner = User::getOwnerDataById($user['uid']);
69 $alias = str_replace('/profile/', '/~', $owner['url']);
71 $avatar = Photo::selectFirst(['type'], ['uid' => $owner['uid'], 'profile' => true]);
73 if (!DBA::isResult($avatar)) {
74 $avatar = ['type' => 'image/jpeg'];
78 self::printXML($alias, DI::baseUrl()->get(), $user, $owner, $avatar);
80 self::printJSON($alias, DI::baseUrl()->get(), $owner, $avatar);
84 private static function printJSON($alias, $baseURL, $owner, $avatar)
86 $salmon_key = Salmon::salmonKey($owner['spubkey']);
88 header('Access-Control-Allow-Origin: *');
89 header('Content-type: application/json; charset=utf-8');
92 'subject' => 'acct:' . $owner['addr'],
99 'rel' => ActivityNamespace::DFRN ,
100 'href' => $owner['url'],
103 'rel' => ActivityNamespace::FEED,
104 'type' => 'application/atom+xml',
105 'href' => $owner['poll'],
108 'rel' => 'http://webfinger.net/rel/profile-page',
109 'type' => 'text/html',
110 'href' => $owner['url'],
114 'type' => 'application/activity+json',
115 'href' => $owner['url'],
118 'rel' => 'http://microformats.org/profile/hcard',
119 'type' => 'text/html',
120 'href' => $baseURL . '/hcard/' . $owner['nickname'],
123 'rel' => ActivityNamespace::POCO,
124 'href' => $owner['poco'],
127 'rel' => 'http://webfinger.net/rel/avatar',
128 'type' => $avatar['type'],
129 'href' => $owner['photo'],
132 'rel' => 'http://joindiaspora.com/seed_location',
133 'type' => 'text/html',
138 'href' => $baseURL . '/salmon/' . $owner['nickname'],
141 'rel' => 'http://salmon-protocol.org/ns/salmon-replies',
142 'href' => $baseURL . '/salmon/' . $owner['nickname'],
145 'rel' => 'http://salmon-protocol.org/ns/salmon-mention',
146 'href' => $baseURL . '/salmon/' . $owner['nickname'] . '/mention',
149 'rel' => 'http://ostatus.org/schema/1.0/subscribe',
150 'template' => $baseURL . '/follow?url={uri}',
153 'rel' => 'magic-public-key',
154 'href' => 'data:application/magic-public-key,' . $salmon_key,
157 'rel' => 'http://purl.org/openwebauth/v1',
158 'type' => 'application/x-zot+json',
159 'href' => $baseURL . '/owa',
164 echo json_encode($json);
168 private static function printXML($alias, $baseURL, $user, $owner, $avatar)
170 $salmon_key = Salmon::salmonKey($owner['spubkey']);
172 header('Access-Control-Allow-Origin: *');
173 header('Content-type: text/xml');
175 $tpl = Renderer::getMarkupTemplate('xrd_person.tpl');
177 $o = Renderer::replaceMacros($tpl, [
178 '$nick' => $owner['nickname'],
179 '$accturi' => 'acct:' . $owner['addr'],
181 '$profile_url' => $owner['url'],
182 '$hcard_url' => $baseURL . '/hcard/' . $owner['nickname'],
183 '$atom' => $owner['poll'],
184 '$poco_url' => $owner['poco'],
185 '$photo' => $owner['photo'],
186 '$type' => $avatar['type'],
187 '$salmon' => $baseURL . '/salmon/' . $owner['nickname'],
188 '$salmen' => $baseURL . '/salmon/' . $owner['nickname'] . '/mention',
189 '$subscribe' => $baseURL . '/follow?url={uri}',
190 '$openwebauth' => $baseURL . '/owa',
191 '$modexp' => 'data:application/magic-public-key,' . $salmon_key
194 $arr = ['user' => $user, 'xml' => $o];
195 Hook::callAll('personal_xrd', $arr);