3 namespace Friendica\Module;
5 use Friendica\BaseModule;
6 use Friendica\Core\Hook;
7 use Friendica\Core\Renderer;
8 use Friendica\Database\DBA;
9 use Friendica\Model\Photo;
10 use Friendica\Model\User;
11 use Friendica\Protocol\ActivityNamespace;
12 use Friendica\Protocol\Salmon;
13 use Friendica\Util\Strings;
16 * Prints responses to /.well-known/webfinger or /xrd requests
18 class Xrd extends BaseModule
20 public static function rawContent(array $parameters = [])
22 $app = self::getApp();
24 // @TODO: Replace with parameter from router
25 if ($app->argv[0] == 'xrd') {
26 if (empty($_GET['uri'])) {
30 $uri = urldecode(Strings::escapeTags(trim($_GET['uri'])));
31 if (($_SERVER['HTTP_ACCEPT'] ?? '') == 'application/jrd+json') {
37 if (empty($_GET['resource'])) {
41 $uri = urldecode(Strings::escapeTags(trim($_GET['resource'])));
42 if (($_SERVER['HTTP_ACCEPT'] ?? '') == 'application/xrd+xml') {
49 if (substr($uri, 0, 4) === 'http') {
50 $name = ltrim(basename($uri), '~');
52 $local = str_replace('acct:', '', $uri);
53 if (substr($local, 0, 2) == '//') {
54 $local = substr($local, 2);
57 $name = substr($local, 0, strpos($local, '@'));
60 $user = User::getByNickname($name);
63 throw new \Friendica\Network\HTTPException\NotFoundException();
66 $owner = User::getOwnerDataById($user['uid']);
68 $alias = str_replace('/profile/', '/~', $owner['url']);
70 $avatar = Photo::selectFirst(['type'], ['uid' => $owner['uid'], 'profile' => true]);
72 if (!DBA::isResult($avatar)) {
73 $avatar = ['type' => 'image/jpeg'];
77 self::printXML($alias, $app->getBaseURL(), $user, $owner, $avatar);
79 self::printJSON($alias, $app->getBaseURL(), $owner, $avatar);
83 private static function printJSON($alias, $baseURL, $owner, $avatar)
85 $salmon_key = Salmon::salmonKey($owner['spubkey']);
87 header('Access-Control-Allow-Origin: *');
88 header('Content-type: application/json; charset=utf-8');
91 'subject' => 'acct:' . $owner['addr'],
98 'rel' => ActivityNamespace::DFRN ,
99 'href' => $owner['url'],
102 'rel' => ActivityNamespace::FEED,
103 'type' => 'application/atom+xml',
104 'href' => $owner['poll'],
107 'rel' => 'http://webfinger.net/rel/profile-page',
108 'type' => 'text/html',
109 'href' => $owner['url'],
113 'type' => 'application/activity+json',
114 'href' => $owner['url'],
117 'rel' => 'http://microformats.org/profile/hcard',
118 'type' => 'text/html',
119 'href' => $baseURL . '/hcard/' . $owner['nickname'],
122 'rel' => ActivityNamespace::POCO,
123 'href' => $owner['poco'],
126 'rel' => 'http://webfinger.net/rel/avatar',
127 'type' => $avatar['type'],
128 'href' => $owner['photo'],
131 'rel' => 'http://joindiaspora.com/seed_location',
132 'type' => 'text/html',
137 'href' => $baseURL . '/salmon/' . $owner['nickname'],
140 'rel' => 'http://salmon-protocol.org/ns/salmon-replies',
141 'href' => $baseURL . '/salmon/' . $owner['nickname'],
144 'rel' => 'http://salmon-protocol.org/ns/salmon-mention',
145 'href' => $baseURL . '/salmon/' . $owner['nickname'] . '/mention',
148 'rel' => 'http://ostatus.org/schema/1.0/subscribe',
149 'template' => $baseURL . '/follow?url={uri}',
152 'rel' => 'magic-public-key',
153 'href' => 'data:application/magic-public-key,' . $salmon_key,
156 'rel' => 'http://purl.org/openwebauth/v1',
157 'type' => 'application/x-zot+json',
158 'href' => $baseURL . '/owa',
163 echo json_encode($json);
167 private static function printXML($alias, $baseURL, $user, $owner, $avatar)
169 $salmon_key = Salmon::salmonKey($owner['spubkey']);
171 header('Access-Control-Allow-Origin: *');
172 header('Content-type: text/xml');
174 $tpl = Renderer::getMarkupTemplate('xrd_person.tpl');
176 $o = Renderer::replaceMacros($tpl, [
177 '$nick' => $owner['nickname'],
178 '$accturi' => 'acct:' . $owner['addr'],
180 '$profile_url' => $owner['url'],
181 '$hcard_url' => $baseURL . '/hcard/' . $owner['nickname'],
182 '$atom' => $owner['poll'],
183 '$poco_url' => $owner['poco'],
184 '$photo' => $owner['photo'],
185 '$type' => $avatar['type'],
186 '$salmon' => $baseURL . '/salmon/' . $owner['nickname'],
187 '$salmen' => $baseURL . '/salmon/' . $owner['nickname'] . '/mention',
188 '$subscribe' => $baseURL . '/follow?url={uri}',
189 '$openwebauth' => $baseURL . '/owa',
190 '$modexp' => 'data:application/magic-public-key,' . $salmon_key
193 $arr = ['user' => $user, 'xml' => $o];
194 Hook::callAll('personal_xrd', $arr);