PluginProbe
ActivityPub / trunk
ActivityPub vtrunk
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-url.php

functions-url.php in ActivityPub trunk, at includes/functions-url.php

210 lines 5.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * URL functions.
4 *
5 * Functions for URL manipulation.
6 *
7 * @package Activitypub
8 */
9
10 namespace Activitypub;
11
12 /**
13 * Get the REST URL relative to this plugin's namespace.
14 *
15 * @param string $path Optional. REST route path. Default ''.
16 *
17 * @return string REST URL relative to this plugin's namespace.
18 */
19 function get_rest_url_by_path( $path = '' ) {
20 // We'll handle the leading slash.
21 $path = \ltrim( $path, '/' );
22 $namespaced_path = \sprintf( '/%s/%s', ACTIVITYPUB_REST_NAMESPACE, $path );
23 return \get_rest_url( null, $namespaced_path );
24 }
25
26 /**
27 * Normalize a URL.
28 *
29 * @param string $url The URL.
30 *
31 * @return string The normalized URL.
32 */
33 function normalize_url( $url ) {
34 // Remove ActivityPub-specific query parameters.
35 $url = \remove_query_arg( array( 'activitypub', 'preview' ), $url );
36 $url = \untrailingslashit( $url );
37 $url = \preg_replace( '/^https?:\/\/(www\.)?/', '', $url );
38
39 return $url;
40 }
41
42 /**
43 * Normalize a host.
44 *
45 * @param string $host The host.
46 *
47 * @return string The normalized host.
48 */
49 function normalize_host( $host ) {
50 return \preg_replace( '/^www\./', '', $host );
51 }
52
53 /**
54 * Fold a host to its canonical spelling for comparison.
55 *
56 * Hosts are case-insensitive, IPv6 literals are bracketed in a URI but not in a stored host,
57 * and a trailing dot is the same fully qualified name. Two spellings that differ only in those
58 * ways address the same host, so anything comparing hosts has to fold them first.
59 *
60 * Unlike {@see normalize_host()} this is lossless: it does not strip `www.`, which is a
61 * different host rather than a different spelling of one.
62 *
63 * @since 9.3.0
64 *
65 * @param string $host The host.
66 *
67 * @return string The folded host.
68 */
69 function fold_host( $host ) {
70 return \rtrim( \trim( \strtolower( (string) $host ), '[]' ), '.' );
71 }
72
73 /**
74 * Fold an authority to the host it names.
75 *
76 * An authority is what a `Host` header carries: a host, plus a port whenever it is not the
77 * default one, with an IPv6 literal in brackets. {@see fold_host()} expects a bare host and
78 * strips brackets without understanding a port, so `[::1]:443` would fold to `::1]:443` and
79 * `example.org:8080` would never match the `example.org` that {@see home_host()} returns.
80 * Use this wherever an authority has to be compared against a host.
81 *
82 * @since 9.3.1
83 *
84 * @param string $authority A host, optionally bracketed and optionally with a port.
85 *
86 * @return string The folded host, or an empty string when the value names none.
87 */
88 function fold_authority( $authority ) {
89 // Parsed as a scheme-relative URL, which is the shape an authority already has.
90 $host = \wp_parse_url( '//' . \ltrim( (string) $authority, '/' ), \PHP_URL_HOST );
91
92 return fold_host( (string) $host );
93 }
94
95 /**
96 * Check if a URL is from the same domain as the site.
97 *
98 * @param string $url The URL to check.
99 *
100 * @return boolean True if the URL is from the same domain, false otherwise.
101 */
102 function is_same_domain( $url ) {
103 $remote = \wp_parse_url( $url, PHP_URL_HOST );
104
105 if ( ! $remote ) {
106 return false;
107 }
108
109 $remote = normalize_host( $remote );
110 $self = normalize_host( home_host() );
111
112 return $remote === $self;
113 }
114
115 /**
116 * Retrieves the Host for the current site where the front end is accessible.
117 *
118 * @return string The host for the current site.
119 */
120 function home_host() {
121 return \wp_parse_url( \home_url(), PHP_URL_HOST );
122 }
123
124 /**
125 * Get the base URL for uploads.
126 *
127 * @return string The upload base URL.
128 */
129 function get_upload_baseurl() {
130 /**
131 * Early filter to allow plugins to set the upload base URL.
132 *
133 * @param string|false $maybe_upload_dir The upload base URL or false if not set.
134 */
135 $maybe_upload_dir = \apply_filters( 'pre_activitypub_get_upload_baseurl', false );
136 if ( false !== $maybe_upload_dir ) {
137 return $maybe_upload_dir;
138 }
139
140 $upload_dir = \wp_get_upload_dir();
141
142 /**
143 * Filters the upload base URL.
144 *
145 * @param string $upload_dir The upload base URL. Default \wp_get_upload_dir()['baseurl']
146 */
147 return \apply_filters( 'activitypub_get_upload_baseurl', $upload_dir['baseurl'] );
148 }
149
150 /**
151 * Get the authority (scheme + host) from a URL.
152 *
153 * @param string $url The URL to parse.
154 *
155 * @return string|false The authority, or false on failure.
156 */
157 function get_url_authority( $url ) {
158 $parsed = \wp_parse_url( $url );
159
160 if ( ! $parsed || empty( $parsed['scheme'] ) || empty( $parsed['host'] ) ) {
161 return false;
162 }
163
164 return $parsed['scheme'] . '://' . $parsed['host'];
165 }
166
167 /**
168 * Infer a shortname from the Actor ID or URL. Used only for fallbacks,
169 * we will try to use what's supplied.
170 *
171 * @param string $uri The URI.
172 *
173 * @return string Hopefully the name of the Follower.
174 */
175 function extract_name_from_uri( $uri ) {
176 $name = $uri;
177
178 if ( \filter_var( $name, FILTER_VALIDATE_URL ) ) {
179 $name = \rtrim( $name, '/' );
180 $path = \wp_parse_url( $name, PHP_URL_PATH );
181 if ( $path && '/' !== $path ) {
182 if ( \strpos( $name, '@' ) !== false ) {
183 // Expected: https://example.com/@user (default URL pattern).
184 $name = \preg_replace( '|^/@?|', '', $path );
185 } else {
186 // Expected: https://example.com/users/user (default ID pattern).
187 $parts = \explode( '/', $path );
188 $name = \array_pop( $parts );
189 }
190 } else {
191 $name = \wp_parse_url( $name, PHP_URL_HOST );
192 $name = \str_replace( 'www.', '', $name );
193 }
194 } elseif (
195 \is_email( $name ) ||
196 \strpos( $name, 'acct' ) === 0 ||
197 \strpos( $name, '@' ) === 0
198 ) {
199 // Expected: user@example.com or acct:user@example (WebFinger).
200 $name = \ltrim( $name, '@' );
201 if ( \str_starts_with( $name, 'acct:' ) ) {
202 $name = \substr( $name, 5 );
203 }
204 $parts = \explode( '@', $name );
205 $name = $parts[0];
206 }
207
208 return $name;
209 }
210