@@ -62,7 +62,7 @@ public static function resolve( $resource ) {
6262 $ response = \wp_remote_get (
6363 $ url ,
6464 array (
65- 'headers ' => array ( 'Accept ' => 'application/activity +json ' ),
65+ 'headers ' => array ( 'Accept ' => 'application/jrd +json ' ),
6666 'redirection ' => 0 ,
6767 'timeout ' => 2 ,
6868 )
@@ -94,4 +94,110 @@ public static function resolve( $resource ) {
9494 \set_transient ( $ transient_key , $ link , HOUR_IN_SECONDS ); // Cache the error for a shorter period.
9595 return $ link ;
9696 }
97+
98+ /**
99+ * Convert a URI string to an identifier and its host.
100+ * Automatically adds acct: if it's missing.
101+ *
102+ * @param string $url The URI (acct:, mailto:, http:, https:)
103+ *
104+ * @return WP_Error|array Error reaction or array with
105+ * identifier and host as values
106+ */
107+ public static function get_identifier_and_host ( $ url ) {
108+ // remove leading @
109+ $ url = ltrim ( $ url , '@ ' );
110+
111+ if ( ! preg_match ( '/^([a-zA-Z+]+):/ ' , $ url , $ match ) ) {
112+ $ identifier = 'acct: ' . $ url ;
113+ $ scheme = 'acct ' ;
114+ } else {
115+ $ identifier = $ url ;
116+ $ scheme = $ match [1 ];
117+ }
118+
119+ $ host = null ;
120+
121+ switch ( $ scheme ) {
122+ case 'acct ' :
123+ case 'mailto ' :
124+ case 'xmpp ' :
125+ if ( strpos ( $ identifier , '@ ' ) !== false ) {
126+ $ host = substr ( $ identifier , strpos ( $ identifier , '@ ' ) + 1 );
127+ }
128+ break ;
129+ default :
130+ $ host = wp_parse_url ( $ identifier , PHP_URL_HOST );
131+ break ;
132+ }
133+
134+ if ( empty ( $ host ) ) {
135+ return new WP_Error ( 'invalid_identifier ' , __ ( 'Invalid Identifier ' , 'activitypub ' ) );
136+ }
137+
138+ return array ( $ identifier , $ host );
139+ }
140+
141+ /**
142+ * Get the WebFinger data for a given URI
143+ *
144+ * @param string $identifier The Identifier: <identifier>@<host>
145+ * @param string $host The Host: <identifier>@<host>
146+ *
147+ * @return WP_Error|array Error reaction or array with
148+ * identifier and host as values
149+ */
150+ public static function get_data ( $ identifier , $ host ) {
151+ $ webfinger_url = 'https:// ' . $ host . '/.well-known/webfinger?resource= ' . rawurlencode ( $ identifier );
152+
153+ $ response = wp_safe_remote_get (
154+ $ webfinger_url ,
155+ array (
156+ 'headers ' => array ( 'Accept ' => 'application/jrd+json ' ),
157+ 'redirection ' => 0 ,
158+ 'timeout ' => 2 ,
159+ )
160+ );
161+
162+ if ( is_wp_error ( $ response ) ) {
163+ return new WP_Error ( 'webfinger_url_not_accessible ' , null , $ webfinger_url );
164+ }
165+
166+ $ body = wp_remote_retrieve_body ( $ response );
167+
168+ return json_decode ( $ body , true );
169+ }
170+
171+ /**
172+ * Undocumented function
173+ *
174+ * @return void
175+ */
176+ public static function get_remote_follow_endpoint ( $ uri ) {
177+ $ identifier_and_host = self ::get_identifier_and_host ( $ uri );
178+
179+ if ( is_wp_error ( $ identifier_and_host ) ) {
180+ return $ identifier_and_host ;
181+ }
182+
183+ list ( $ identifier , $ host ) = $ identifier_and_host ;
184+
185+ $ data = self ::get_data ( $ identifier , $ host );
186+
187+ if ( is_wp_error ( $ data ) ) {
188+ return $ data ;
189+ }
190+
191+ if ( empty ( $ data ['links ' ] ) ) {
192+ return new WP_Error ( 'webfinger_url_invalid_response ' , null , $ data );
193+ }
194+
195+ foreach ( $ data ['links ' ] as $ link ) {
196+ if ( 'http://ostatus.org/schema/1.0/subscribe ' === $ link ['rel ' ] ) {
197+ return $ link ['template ' ];
198+ }
199+ }
200+
201+ return new WP_Error ( 'webfinger_remote_follow_endpoint_invalid ' , null , $ data );
202+ }
97203}
0 commit comments