PluginProbe
ActivityPub / 0.9.0
ActivityPub v0.9.0
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
activitypub / includes / functions.php

functions.php in ActivityPub 0.9.0, at includes/functions.php

268 lines 7.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Activitypub;
3
4 /**
5 * Returns the ActivityPub default JSON-context
6 *
7 * @return array the activitypub context
8 */
9 function get_context() {
10 $context = array(
11 'https://www.w3.org/ns/activitystreams',
12 'https://w3id.org/security/v1',
13 array(
14 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
15 'PropertyValue' => 'schema:PropertyValue',
16 'schema' => 'http://schema.org#',
17 'value' => 'schema:value',
18 ),
19 );
20
21 return \apply_filters( 'activitypub_json_context', $context );
22 }
23
24 function safe_remote_post( $url, $body, $user_id ) {
25 $date = \gmdate( 'D, d M Y H:i:s T' );
26 $signature = \Activitypub\Signature::generate_signature( $user_id, $url, $date );
27
28 $wp_version = \get_bloginfo( 'version' );
29 $user_agent = \apply_filters( 'http_headers_useragent', 'WordPress/' . $wp_version . '; ' . \get_bloginfo( 'url' ) );
30 $args = array(
31 'timeout' => 100,
32 'limit_response_size' => 1048576,
33 'redirection' => 3,
34 'user-agent' => "$user_agent; ActivityPub",
35 'headers' => array(
36 'Accept' => 'application/activity+json',
37 'Content-Type' => 'application/activity+json',
38 'Signature' => $signature,
39 'Date' => $date,
40 ),
41 'body' => $body,
42 );
43
44 $response = \wp_safe_remote_post( $url, $args );
45
46 \do_action( 'activitypub_safe_remote_post_response', $response, $url, $body, $user_id );
47
48 return $response;
49 }
50
51 /**
52 * Returns a users WebFinger "resource"
53 *
54 * @param int $user_id
55 *
56 * @return string The user-resource
57 */
58 function get_webfinger_resource( $user_id ) {
59 // use WebFinger plugin if installed
60 if ( \function_exists( '\get_webfinger_resource' ) ) {
61 return \get_webfinger_resource( $user_id, false );
62 }
63
64 $user = \get_user_by( 'id', $user_id );
65
66 return $user->user_login . '@' . \wp_parse_url( \home_url(), PHP_URL_HOST );
67 }
68
69 /**
70 * [get_metadata_by_actor description]
71 *
72 * @param sting $actor
73 *
74 * @return array
75 */
76 function get_remote_metadata_by_actor( $actor ) {
77 $metadata = \get_transient( 'activitypub_' . $actor );
78
79 if ( $metadata ) {
80 return $metadata;
81 }
82
83 if ( ! \wp_http_validate_url( $actor ) ) {
84 return new \WP_Error( 'activitypub_no_valid_actor_url', \__( 'The "actor" is no valid URL', 'activitypub' ), $actor );
85 }
86
87 $wp_version = \get_bloginfo( 'version' );
88
89 $user_agent = \apply_filters( 'http_headers_useragent', 'WordPress/' . $wp_version . '; ' . \get_bloginfo( 'url' ) );
90 $args = array(
91 'timeout' => 100,
92 'limit_response_size' => 1048576,
93 'redirection' => 3,
94 'user-agent' => "$user_agent; ActivityPub",
95 'headers' => array(
96 'accept' => 'application/activity+json, application/ld+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
97 ),
98 );
99
100 $response = \wp_safe_remote_get( $actor, $args );
101
102 if ( \is_wp_error( $response ) ) {
103 return $response;
104 }
105
106 $metadata = \wp_remote_retrieve_body( $response );
107 $metadata = \json_decode( $metadata, true );
108
109 if ( ! $metadata ) {
110 return new \WP_Error( 'activitypub_invalid_json', \__( 'No valid JSON data', 'activitypub' ), $actor );
111 }
112
113 \set_transient( 'activitypub_' . $actor, $metadata, WEEK_IN_SECONDS );
114
115 return $metadata;
116 }
117
118 /**
119 * [get_inbox_by_actor description]
120 * @param [type] $actor [description]
121 * @return [type] [description]
122 */
123 function get_inbox_by_actor( $actor ) {
124 $metadata = \Activitypub\get_remote_metadata_by_actor( $actor );
125
126 if ( \is_wp_error( $metadata ) ) {
127 return $metadata;
128 }
129
130 if ( isset( $metadata['endpoints'] ) && isset( $metadata['endpoints']['sharedInbox'] ) ) {
131 return $metadata['endpoints']['sharedInbox'];
132 }
133
134 if ( \array_key_exists( 'inbox', $metadata ) ) {
135 return $metadata['inbox'];
136 }
137
138 return new \WP_Error( 'activitypub_no_inbox', __( 'No "Inbox" found', 'activitypub' ), $metadata );
139 }
140
141 /**
142 * [get_inbox_by_actor description]
143 * @param [type] $actor [description]
144 * @return [type] [description]
145 */
146 function get_publickey_by_actor( $actor, $key_id ) {
147 $metadata = \Activitypub\get_remote_metadata_by_actor( $actor );
148
149 if ( \is_wp_error( $metadata ) ) {
150 return $metadata;
151 }
152
153 if (
154 isset( $metadata['publicKey'] ) &&
155 isset( $metadata['publicKey']['id'] ) &&
156 isset( $metadata['publicKey']['owner'] ) &&
157 isset( $metadata['publicKey']['publicKeyPem'] ) &&
158 $key_id === $metadata['publicKey']['id'] &&
159 $actor === $metadata['publicKey']['owner']
160 ) {
161 return $metadata['publicKey']['publicKeyPem'];
162 }
163
164 return new \WP_Error( 'activitypub_no_public_key', \__( 'No "Public-Key" found', 'activitypub' ), $metadata );
165 }
166
167 function get_follower_inboxes( $user_id ) {
168 $followers = \Activitypub\Peer\Followers::get_followers( $user_id );
169 $inboxes = array();
170
171 foreach ( $followers as $follower ) {
172 $inbox = \Activitypub\get_inbox_by_actor( $follower );
173 if ( ! $inbox || \is_wp_error( $inbox ) ) {
174 continue;
175 }
176 // init array if empty
177 if ( ! isset( $inboxes[ $inbox ] ) ) {
178 $inboxes[ $inbox ] = array();
179 }
180 $inboxes[ $inbox ][] = $follower;
181 }
182
183 return $inboxes;
184 }
185
186 function get_identifier_settings( $user_id ) {
187 ?>
188 <table class="form-table">
189 <tbody>
190 <tr>
191 <th scope="row">
192 <label><?php \esc_html_e( 'Profile identifier', 'activitypub' ); ?></label>
193 </th>
194 <td>
195 <p><code><?php echo \esc_html( \Activitypub\get_webfinger_resource( $user_id ) ); ?></code> or <code><?php echo \esc_url( \get_author_posts_url( $user_id ) ); ?></code></p>
196 <?php // translators: the webfinger resource ?>
197 <p class="description"><?php printf( \esc_html__( 'Try to follow "@%s" in the Mastodon/Friendica search field.', 'activitypub' ), \esc_html( \Activitypub\get_webfinger_resource( $user_id ) ) ); ?></p>
198 </td>
199 </tr>
200 </tbody>
201 </table>
202 <?php
203 }
204
205 function get_followers( $user_id ) {
206 $followers = \Activitypub\Peer\Followers::get_followers( $user_id );
207
208 if ( ! $followers ) {
209 return array();
210 }
211
212 return $followers;
213 }
214
215 function count_followers( $user_id ) {
216 $followers = \Activitypub\get_followers( $user_id );
217
218 return \count( $followers );
219 }
220
221 /**
222 * Examine a url and try to determine the author ID it represents.
223 *
224 * Checks are supposedly from the hosted site blog.
225 *
226 * @param string $url Permalink to check.
227 *
228 * @return int User ID, or 0 on failure.
229 */
230 function url_to_authorid( $url ) {
231 global $wp_rewrite;
232
233 // check if url hase the same host
234 if ( wp_parse_url( site_url(), PHP_URL_HOST ) !== wp_parse_url( $url, PHP_URL_HOST ) ) {
235 return 0;
236 }
237
238 // first, check to see if there is a 'author=N' to match against
239 if ( preg_match( '/[?&]author=(\d+)/i', $url, $values ) ) {
240 $id = absint( $values[1] );
241 if ( $id ) {
242 return $id;
243 }
244 }
245
246 // check to see if we are using rewrite rules
247 $rewrite = $wp_rewrite->wp_rewrite_rules();
248
249 // not using rewrite rules, and 'author=N' method failed, so we're out of options
250 if ( empty( $rewrite ) ) {
251 return 0;
252 }
253
254 // generate rewrite rule for the author url
255 $author_rewrite = $wp_rewrite->get_author_permastruct();
256 $author_regexp = str_replace( '%author%', '', $author_rewrite );
257
258 // match the rewrite rule with the passed url
259 if ( preg_match( '/https?:\/\/(.+)' . preg_quote( $author_regexp, '/' ) . '([^\/]+)/i', $url, $match ) ) {
260 $user = get_user_by( 'slug', $match[2] );
261 if ( $user ) {
262 return $user->ID;
263 }
264 }
265
266 return 0;
267 }
268