PluginProbe
ActivityPub / 5.3.1
ActivityPub v5.3.1
9.3.1 9.3.0 9.2.2 9.2.1 9.2.0 9.1.0 9.0.2 9.0.1 9.0.0 8.3.0 8.2.1 8.2.0 8.1.1 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.1.0 2.1.1 All 160 releases
← All changes | includes/class-webfinger.php +97 -41 2.0.0 → 5.3.1 View file →
@@ -1,12 +1,18 @@
1 1 <?php
2 +/**
3 + * WebFinger class file.
4 + *
5 + * @package Activitypub
6 + */
7 +
2 8 namespace Activitypub;
3 9
4 10 use WP_Error;
5 -use Activitypub\Collection\Users;
11 +use Activitypub\Collection\Actors;
6 12
7 13 /**
8 - * ActivityPub WebFinger Class
14 + * ActivityPub WebFinger Class.
9 15 *
10 16 * @author Matthias Pfefferle
11 17 *
12 18 * @see https://webfinger.net/
@@ -12,21 +18,16 @@
12 18 * @see https://webfinger.net/
13 19 */
14 20 class Webfinger {
15 21 /**
16 - * Returns a users WebFinger "resource"
22 + * Returns a users WebFinger "resource".
17 23 *
18 - * @param int $user_id The WordPress user id
24 + * @param int $user_id The WordPress user id.
19 25 *
20 - * @return string The user-resource
26 + * @return string The user-resource.
21 27 */
22 28 public static function get_user_resource( $user_id ) {
23 - // use WebFinger plugin if installed
24 - if ( \function_exists( '\get_webfinger_resource' ) ) {
25 - return \get_webfinger_resource( $user_id, false );
26 - }
27 -
28 - $user = Users::get_by_id( $user_id );
29 + $user = Actors::get_by_id( $user_id );
29 30 if ( ! $user || is_wp_error( $user ) ) {
30 31 return '';
31 32 }
32 33
@@ -33,13 +34,13 @@
33 34 return $user->get_webfinger();
34 35 }
35 36
36 37 /**
37 - * Resolve a WebFinger resource
38 + * Resolve a WebFinger resource.
38 39 *
39 - * @param string $uri The WebFinger Resource
40 + * @param string $uri The WebFinger Resource.
40 41 *
41 - * @return string|WP_Error The URL or WP_Error
42 + * @return string|WP_Error The URL or WP_Error.
42 43 */
43 44 public static function resolve( $uri ) {
44 45 $data = self::get_data( $uri );
45 46
@@ -46,26 +47,47 @@
46 47 if ( \is_wp_error( $data ) ) {
47 48 return $data;
48 49 }
49 50
51 + if ( ! is_array( $data ) || empty( $data['links'] ) ) {
52 + return new WP_Error(
53 + 'webfinger_missing_links',
54 + __( 'No valid Link elements found.', 'activitypub' ),
55 + array(
56 + 'status' => 400,
57 + 'data' => $data,
58 + )
59 + );
60 + }
61 +
50 62 foreach ( $data['links'] as $link ) {
51 63 if (
52 64 'self' === $link['rel'] &&
53 - 'application/activity+json' === $link['type']
65 + (
66 + 'application/activity+json' === $link['type'] ||
67 + 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' === $link['type']
68 + )
54 69 ) {
55 70 return $link['href'];
56 71 }
57 72 }
58 73
59 - return new WP_Error( 'webfinger_url_no_activitypub', null, $data );
74 + return new WP_Error(
75 + 'webfinger_url_no_activitypub',
76 + __( 'The Site supports WebFinger but not ActivityPub', 'activitypub' ),
77 + array(
78 + 'status' => 400,
79 + 'data' => $data,
80 + )
81 + );
60 82 }
61 83
62 84 /**
63 - * Transform a URI to an acct <identifier>@<host>
85 + * Transform a URI to an acct <identifier>@<host>.
64 86 *
65 - * @param string $uri The URI (acct:, mailto:, http:, https:)
87 + * @param string $uri The URI (acct:, mailto:, http:, https:).
66 88 *
67 - * @return string|WP_Error Error or acct URI
89 + * @return string|WP_Error Error or acct URI.
68 90 */
69 91 public static function uri_to_acct( $uri ) {
70 92 $data = self::get_data( $uri );
71 93
@@ -72,9 +94,9 @@
72 94 if ( is_wp_error( $data ) ) {
73 95 return $data;
74 96 }
75 97
76 - // check if subject is an acct URI
98 + // Check if subject is an acct URI.
77 99 if (
78 100 isset( $data['subject'] ) &&
79 101 \str_starts_with( $data['subject'], 'acct:' )
80 102 ) {
@@ -80,9 +102,9 @@
80 102 ) {
81 103 return $data['subject'];
82 104 }
83 105
84 - // search for an acct URI in the aliases
106 + // Search for an acct URI in the aliases.
85 107 if ( isset( $data['aliases'] ) ) {
86 108 foreach ( $data['aliases'] as $alias ) {
87 109 if ( \str_starts_with( $alias, 'acct:' ) ) {
88 110 return $alias;
@@ -92,9 +114,12 @@
92 114
93 115 return new WP_Error(
94 116 'webfinger_url_no_acct',
95 117 __( 'No acct URI found.', 'activitypub' ),
96 - $data
118 + array(
119 + 'status' => 400,
120 + 'data' => $data,
121 + )
97 122 );
98 123 }
99 124
100 125 /**
@@ -100,23 +125,33 @@
100 125 /**
101 126 * Convert a URI string to an identifier and its host.
102 127 * Automatically adds acct: if it's missing.
103 128 *
104 - * @param string $url The URI (acct:, mailto:, http:, https:)
129 + * @param string $url The URI (acct:, mailto:, http:, https:).
105 130 *
106 - * @return WP_Error|array Error reaction or array with
107 - * identifier and host as values
131 + * @return WP_Error|array Error reaction or array with identifier and host as values.
108 132 */
109 133 public static function get_identifier_and_host( $url ) {
110 - // remove leading @
134 + if ( ! $url ) {
135 + return new WP_Error(
136 + 'webfinger_invalid_identifier',
137 + __( 'Invalid Identifier', 'activitypub' ),
138 + array(
139 + 'status' => 400,
140 + 'data' => $url,
141 + )
142 + );
143 + }
144 +
145 + // Remove leading @.
111 146 $url = ltrim( $url, '@' );
112 147
113 148 if ( ! preg_match( '/^([a-zA-Z+]+):/', $url, $match ) ) {
114 149 $identifier = 'acct:' . $url;
115 - $scheme = 'acct';
150 + $scheme = 'acct';
116 151 } else {
117 152 $identifier = $url;
118 - $scheme = $match[1];
153 + $scheme = $match[1];
119 154 }
120 155
121 156 $host = null;
122 157
@@ -133,9 +168,16 @@
133 168 break;
134 169 }
135 170
136 171 if ( empty( $host ) ) {
137 - return new WP_Error( 'webfinger_invalid_identifier', __( 'Invalid Identifier', 'activitypub' ) );
172 + return new WP_Error(
173 + 'webfinger_invalid_identifier',
174 + __( 'Invalid Identifier', 'activitypub' ),
175 + array(
176 + 'status' => 400,
177 + 'data' => $url,
178 + )
179 + );
138 180 }
139 181
140 182 return array( $identifier, $host );
141 183 }
@@ -140,14 +182,13 @@
140 182 return array( $identifier, $host );
141 183 }
142 184
143 185 /**
144 - * Get the WebFinger data for a given URI
186 + * Get the WebFinger data for a given URI.
145 187 *
146 - * @param string $uri The Identifier: <identifier>@<host> or URI
188 + * @param string $uri The Identifier: <identifier>@<host> or URI.
147 189 *
148 - * @return WP_Error|array Error reaction or array with
149 - * identifier and host as values
190 + * @return WP_Error|array Error reaction or array with identifier and host as values.
150 191 */
151 192 public static function get_data( $uri ) {
152 193 $identifier_and_host = self::get_identifier_and_host( $uri );
153 194
@@ -163,9 +204,13 @@
163 204 if ( $data ) {
164 205 return $data;
165 206 }
166 207
167 - $webfinger_url = 'https://' . $host . '/.well-known/webfinger?resource=' . rawurlencode( $identifier );
208 + $webfinger_url = sprintf(
209 + 'https://%s/.well-known/webfinger?resource=%s',
210 + $host,
211 + rawurlencode( $identifier )
212 + );
168 213
169 214 $response = wp_safe_remote_get(
170 215 $webfinger_url,
171 216 array(
@@ -176,9 +221,12 @@
176 221 if ( is_wp_error( $response ) ) {
177 222 return new WP_Error(
178 223 'webfinger_url_not_accessible',
179 224 __( 'The WebFinger Resource is not accessible.', 'activitypub' ),
180 - $webfinger_url
225 + array(
226 + 'status' => 400,
227 + 'data' => $webfinger_url,
228 + )
181 229 );
182 230 }
183 231
184 232 $body = wp_remote_retrieve_body( $response );
@@ -189,10 +237,12 @@
189 237 return $data;
190 238 }
191 239
192 240 /**
193 - * Get the Remote-Follow endpoint for a given URI
241 + * Get the Remote-Follow endpoint for a given URI.
194 242 *
243 + * @param string $uri The WebFinger Resource URI.
244 + *
195 245 * @return string|WP_Error Error or the Remote-Follow endpoint URI.
196 246 */
197 247 public static function get_remote_follow_endpoint( $uri ) {
198 248 $data = self::get_data( $uri );
@@ -204,9 +254,12 @@
204 254 if ( empty( $data['links'] ) ) {
205 255 return new WP_Error(
206 256 'webfinger_missing_links',
207 257 __( 'No valid Link elements found.', 'activitypub' ),
208 - $data
258 + array(
259 + 'status' => 400,
260 + 'data' => $data,
261 + )
209 262 );
210 263 }
211 264
212 265 foreach ( $data['links'] as $link ) {
@@ -217,18 +270,21 @@
217 270
218 271 return new WP_Error(
219 272 'webfinger_missing_remote_follow_endpoint',
220 273 __( 'No valid Remote-Follow endpoint found.', 'activitypub' ),
221 - $data
274 + array(
275 + 'status' => 400,
276 + 'data' => $data,
277 + )
222 278 );
223 279 }
224 280
225 281 /**
226 - * Generate a cache key for a given URI
282 + * Generate a cache key for a given URI.
227 283 *
228 - * @param string $uri A WebFinger Resource URI
284 + * @param string $uri A WebFinger Resource URI.
229 285 *
230 - * @return string The cache key
286 + * @return string The cache key.
231 287 */
232 288 public static function generate_cache_key( $uri ) {
233 289 $uri = ltrim( $uri, '@' );
234 290