PluginProbe
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions / 111206
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions v111206
260917 260913 260909 260829 260814 260805 110710 110731 110812 110815 110912 110913 110915 110926 110927 111002 111003 111011 111017 111029 111105 111206 111216 111220 120213 All 189 releases
s2member / includes / classes / utils-urls.inc.php

utils-urls.inc.php in s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions 111206, at includes/classes/utils-urls.inc.php

359 lines 19.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * URL utilities.
4 *
5 * Copyright: © 2009-2011
6 * {@link http://www.websharks-inc.com/ WebSharks, Inc.}
7 * ( coded in the USA )
8 *
9 * Released under the terms of the GNU General Public License.
10 * You should have received a copy of the GNU General Public License,
11 * along with this software. In the main directory, see: /licensing/
12 * If not, see: {@link http://www.gnu.org/licenses/}.
13 *
14 * @package s2Member\Utilities
15 * @since 3.5
16 */
17 if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18 exit ("Do not access this file directly.");
19 /**/
20 if (!class_exists ("c_ws_plugin__s2member_utils_urls"))
21 {
22 /**
23 * URL utilities.
24 *
25 * @package s2Member\Utilities
26 * @since 3.5
27 */
28 class c_ws_plugin__s2member_utils_urls
29 {
30 /**
31 * Builds a WordPress® signup URL to `/wp-signup.php`.
32 *
33 * @package s2Member\Utilities
34 * @since 3.5
35 *
36 * @return str Full URL to `/wp-signup.php`.
37 */
38 public static function wp_signup_url ()
39 {
40 return apply_filters ("wp_signup_location", site_url ("/wp-signup.php"));
41 }
42 /**
43 * Builds a WordPress® registration URL to `/wp-login.php?action=register`.
44 *
45 * @package s2Member\Utilities
46 * @since 3.5
47 *
48 * @return str Full URL to `/wp-login.php?action=register`.
49 */
50 public static function wp_register_url ()
51 {
52 return apply_filters ("wp_register_location", add_query_arg ("action", urlencode ("register"), wp_login_url ()), get_defined_vars ());
53 }
54 /**
55 * Builds a BuddyPress registration URL to `/register`.
56 *
57 * @package s2Member\Utilities
58 * @since 111009
59 *
60 * @return str|bool Full URL to `/register`, if BuddyPress is installed; else false.
61 */
62 public static function bp_register_url ()
63 {
64 if ( /* If BuddyPress is installed. */c_ws_plugin__s2member_utils_conds::bp_is_installed ())
65 return site_url (((function_exists ("bp_get_signup_slug")) ? bp_get_signup_slug () . "/" : BP_REGISTER_SLUG . "/"));
66 /**/
67 return false; /* Default return false. */
68 }
69 /**
70 * Filters content redirection status *( uses 302s for browsers )*.
71 *
72 * @package s2Member\Utilities
73 * @since 3.5
74 *
75 * @attaches-to ``add_filter("ws_plugin__s2member_content_redirect_status");``
76 *
77 * @param int|str $status A numeric redirection status code.
78 * @return int|str A numeric status redirection code, possibly modified to a value of `302`.
79 *
80 * @see http://en.wikipedia.org/wiki/Web_browser_engine
81 */
82 public static function redirect_browsers_using_302_status ($status = FALSE)
83 {
84 $engines = "msie|trident|gecko|webkit|presto|konqueror|playstation";
85 /**/
86 if ( /* Default `301` status? */(int)$status === 301 && /* Have User-Agent? */ !empty ($_SERVER["HTTP_USER_AGENT"]))
87 if (($is_browser = preg_match ("/(" . $engines . ")[\/ ]([0-9\.]+)/i", $_SERVER["HTTP_USER_AGENT"])))
88 return /* Use 302 status. */ ($status = 302);
89 /**/
90 return /* Else use existing status. */ $status;
91 }
92 /**
93 * Encodes all types of amperands to `amp;`, for use in XHTML code.
94 *
95 * Note however, this is usually NOT necessary. Just use WordPress® ``esc_html()`` or ``esc_attr()``.
96 *
97 * @package s2Member\Utilities
98 * @since 111106
99 *
100 * @param str $url_uri_query A full URL, a partial URI, or just the query string.
101 * @return str A full URL, a partial URI, or just the query string; after having been encoded by this routine.
102 */
103 public static function e_amps ($url_uri_query = FALSE)
104 {
105 return str_replace ("&", "&amp;", c_ws_plugin__s2member_utils_urls::n_amps ((string)$url_uri_query));
106 }
107 /**
108 * Normalizes amperands to `&` when working with URLs, URIs, and/or query strings.
109 *
110 * @package s2Member\Utilities
111 * @since 111106
112 *
113 * @param str $url_uri_query A full URL, a partial URI, or just the query string.
114 * @return str A full URL, a partial URI, or just the query string; after having been normalized by this routine.
115 */
116 public static function n_amps ($url_uri_query = FALSE)
117 {
118 $amps = implode ("|", array_keys /* Keys are regex patterns. */ (c_ws_plugin__s2member_utils_strings::$ampersand_entities));
119 /**/
120 return /* Normalizes amperands to `&`. */ preg_replace ("/(?:" . $amps . ")/", "&", (string)$url_uri_query);
121 }
122 /**
123 * Parses out a full valid URI, from either a full URL, or a partial URI.
124 *
125 * Uses {@link s2Member\Utilities\c_ws_plugin__s2member_utils_urls::parse_url()}.
126 *
127 * @package s2Member\Utilities
128 * @since 3.5
129 *
130 * @param str $url_uri Either a full URL, or a partial URI.
131 * @return str A valid URI, starting with `/` on success, else an empty string.
132 */
133 public static function parse_uri ($url_uri = FALSE)
134 {
135 if (is_string ($url_uri) && is_array ($parse = c_ws_plugin__s2member_utils_urls::parse_url ($url_uri)))
136 {
137 $parse["path"] = (!empty ($parse["path"])) ? ((strpos ($parse["path"], "/") === 0) ? $parse["path"] : "/" . $parse["path"]) : "/";
138 /**/
139 return (!empty ($parse["query"])) ? $parse["path"] . "?" . $parse["query"] : $parse["path"];
140 }
141 else /* Force a string return value here. */
142 return /* Empty string. */ "";
143 }
144 /**
145 * Parses a URL/URI with same args as PHP's ``parse_url()`` function.
146 *
147 * This works around issues with this PHP function in versions prior to 5.3.8.
148 *
149 * @package s2Member\Utilities
150 * @since 111017
151 *
152 * @param str $url_uri Either a full URL, or a partial URI to parse.
153 * @param bool|int $component Optional. See PHP documentation on ``parse_url()`` function.
154 * @param bool $clean_path Defaults to true. s2Member will cleanup any return array `path`.
155 * @return str|array|bool The return value from PHP's ``parse_url()`` function.
156 * However, if ``$component`` is passed, s2Member forces a string return.
157 */
158 public static function parse_url ($url_uri = FALSE, $component = FALSE, $clean_path = TRUE)
159 {
160 $component = ($component === false || $component === -1) ? -1 : $component;
161 /**/
162 if (is_string ($url_uri) && /* And, there is a query string? */ strpos ($url_uri, "?") !== false)
163 {
164 list ($_, $query) = preg_split ("/\?/", $url_uri, 2); /* Split @ query string marker. */
165 $query = /* See: <https://bugs.php.net/bug.php?id=38143>. */ str_replace ("://", urlencode ("://"), $query);
166 $url_uri = /* Put it all back together again, after the above modifications. */ $_ . "?" . $query;
167 unset /* A little housekeeping here. Unset these vars. */ ($_, $query);
168 }
169 $parse = /* Let PHP work its magic via ``parse_url()``. */ @parse_url ($url_uri, $component);
170 /**/
171 if ($clean_path && isset ($parse["path"]) && is_string ($parse["path"]) && !empty ($parse["path"]))
172 $parse["path"] = /* Clean up the path now. */ preg_replace ("/\/+/", "/", $parse["path"]);
173 /**/
174 return ($component !== -1) ? /* Force a string return value? */ (string)$parse : $parse;
175 }
176 /**
177 * Responsible for all remote communications processed by s2Member.
178 *
179 * Uses ``wp_remote_request()`` through the `WP_Http` class.
180 *
181 * @package s2Member\Utilities
182 * @since 3.5
183 *
184 * @param str $url Full URL with possible query string parameters.
185 * @param str|array $post_vars Optional. Either a string of POST vars, or an array.
186 * @param array $args Optional. An array of additional arguments used by ``wp_remote_request()``.
187 * @param bool $return Optional. One of: `body|array`. Defaults to `body`. If `array`, an array with the following elements:
188 * `code` *(http response code)*, `message` *(http response message)*, `headers` *(an array of lowercase headers)*, `body` *(the response body string)*, `response` *(response array)*.
189 * @return str|array|bool Requested response data from the remote location *(see ``$return`` parameter )*, else false on failure.
190 */
191 public static function remote ($url = FALSE, $post_vars = FALSE, $args = FALSE, $return = FALSE)
192 {
193 if ($url && is_string ($url) /* We MUST have a valid full URL (string) before we do anything in this routine. */)
194 {
195 $args = (!is_array ($args)) ? array (): $args; /* Force array, and disable SSL verification. */
196 $args["sslverify"] = (!isset ($args["sslverify"])) ? /* Off. */ false : $args["sslverify"];
197 /**/
198 if ((is_array ($post_vars) || is_string ($post_vars)) && !empty ($post_vars))
199 $args = array_merge ($args, array ("method" => "POST", "body" => $post_vars));
200 /**/
201 $response = wp_remote_request ($url, $args); /* Process the remote request now. */
202 /**/
203 if (strcasecmp ((string)$return, "array") === 0 && !is_wp_error ($response) && is_array ($response))
204 {
205 $a = array ("code" => (int)wp_remote_retrieve_response_code ($response));
206 $a = array_merge ($a, array ("message" => wp_remote_retrieve_response_message ($response)));
207 $a = array_merge ($a, array ("headers" => wp_remote_retrieve_headers ($response)));
208 $a = array_merge ($a, array ("body" => wp_remote_retrieve_body ($response)));
209 $a = array_merge ($a, array ("response" => $response));
210 /**/
211 return /* Return array w/ ``$response`` too. */ $a;
212 }
213 else if (!is_wp_error ($response) && is_array ($response) /* Return body only. */)
214 return /* Return ``$response`` body only. */ wp_remote_retrieve_body ($response);
215 /**/
216 else /* Else this remote request has failed completely. Return false. */
217 return false; /* Remote request failed, return false. */
218 }
219 else /* Else, return false. */
220 return false;
221 }
222 /**
223 * Shortens a long URL, based on s2Member configuration.
224 *
225 * @package s2Member\Utilities
226 * @since 111002
227 *
228 * @param str $url A full/long URL to be shortened.
229 * @param str $api_sp Optional. A specific URL shortening API to use. Defaults to that which is configured in the s2Member Dashboard. Normally `tiny_url`, by default.
230 * @param bool $try_backups Defaults to true. If a failure occurs with the first API, we'll try others until we have success.
231 * @return str|bool The shortened URL on success, else false on failure.
232 */
233 public static function shorten ($url = FALSE, $api_sp = FALSE, $try_backups = TRUE)
234 {
235 $url = /* Force strings, else false. */ ($url && is_string ($url)) ? $url : false;
236 $api_sp = ($api_sp && is_string ($api_sp)) ? strtolower ($api_sp) : false;
237 /**/
238 $default_url_shortener = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["default_url_shortener"];
239 $default_custom_str_url_shortener = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["default_custom_str_url_shortener"];
240 /**/
241 $apis = array ("tiny_url", "goo_gl"); /* The shortening APIs currently pre-integrated in this release of s2Member. */
242 /**/
243 if ($url && ($api = /* If specific, use it. Otherwise, use the default shortening API. */ ($api_sp) ? $api_sp : $default_url_shortener))
244 {
245 if (!$api_sp && ($custom_url = trim (apply_filters ("ws_plugin__s2member_url_shorten", false, get_defined_vars ()))) && stripos ($custom_url, "http") === 0)
246 return ($shorter_url = $custom_url); /* Using whatever other shortener API you prefer, over the ones available by default with s2Member. */
247 /**/
248 else if (!$api_sp && stripos ($default_custom_str_url_shortener, "http") === 0 && ($custom_url = trim (c_ws_plugin__s2member_utils_urls::remote (str_ireplace (array ("%%s2_long_url%%", "%%s2_long_url_md5%%"), array (rawurlencode ($url), urlencode (md5 ($url))), $default_custom_str_url_shortener)))) && stripos ($custom_url, "http") === 0)
249 return ($shorter_url = $custom_url); /* Using whatever other shortener API that a site owner prefers, over the ones available by default with s2Member. */
250 /**/
251 else if ($api === "tiny_url" && ($tiny_url = trim (c_ws_plugin__s2member_utils_urls::remote ("http://tinyurl.com/api-create.php?url=" . rawurlencode ($url)))) && stripos ($tiny_url, "http") === 0)
252 return ($shorter_url = $tiny_url); /* The default tinyURL API: <http://tinyurl.com/api-create.php?url=http://www.example.com/>.
253 /**/
254 else if ($api === "goo_gl" && ($goo_gl = json_decode (trim (c_ws_plugin__s2member_utils_urls::remote ("https://www.googleapis.com/urlshortener/v1/url" . ((($goo_gl_key = apply_filters ("ws_plugin__s2member_url_shorten_api_goo_gl_key", false))) ? "?key=" . urlencode ($goo_gl_key) : ""), json_encode (array ("longUrl" => $url)), array ("headers" => array ("Content-Type" => "application/json")))), true)) && !empty ($goo_gl["id"]) && is_string ($goo_gl_url = $goo_gl["id"]) && stripos ($goo_gl_url, "http") === 0)
255 return ($shorter_url = $goo_gl_url); /* Google® API: <http://code.google.com/apis/urlshortener/v1/getting_started.html>.
256 /**/
257 else if ($try_backups && count ($apis) > 1) /* Try backups? This way we can still shorten the URL with a backup. */
258 /**/
259 foreach /* Try other backup APIs now. */ (array_diff ($apis, array ($api)) as $backup)
260 if (($backup = c_ws_plugin__s2member_utils_urls::shorten ($url, $backup, false)))
261 return /* Success, we can return now. */ ($shorter_url = $backup);
262 }
263 return /* Default return value. */ false;
264 }
265 /**
266 * Removes all s2Member-generated signatures from a full URL, a partial URI, or just a query string.
267 *
268 * @package s2Member\Utilities
269 * @since 111106
270 *
271 * @param str $url_uri_query A full URL, a partial URI, or just the query string; to remove s2Member-generated signatures from.
272 * @param str $sig_var Optional. The name of the s2Member-generated signature variable. Defaults to `_s2member_sig`.
273 * @return str A full URL, a partial URI, or just the query string; without any s2Member-generated signatures.
274 */
275 public static function remove_s2member_sigs ($url_uri_query = FALSE, $sig_var = FALSE)
276 {
277 $url_uri_query = c_ws_plugin__s2member_utils_strings::trim ((string)$url_uri_query, false, "?&=");
278 $sig_var = ($sig_var && is_string ($sig_var)) ? $sig_var : /* Use default. */ "_s2member_sig";
279 $sigs = /* Remove all signatures. */ array_unique (array ($sig_var, "_s2member_sig"));
280 /**/
281 return trim (remove_query_arg ($sigs, $url_uri_query), "?&=");
282 }
283 /**
284 * Adds an s2Member-generated signature onto a full URL, a partial URI, or just a query string.
285 *
286 * @package s2Member\Utilities
287 * @since 111106
288 *
289 * @param str $url_uri_query A full URL, a partial URI, or just a query string; to append the s2Member-generated signature onto.
290 * @param str $sig_var Optional. The name of the s2Member-generated signature variable. Defaults to `_s2member_sig`.
291 * @return str A full URL, a partial URI, or just a query string; with an s2Member-generated signature.
292 */
293 public static function add_s2member_sig ($url_uri_query = FALSE, $sig_var = FALSE)
294 {
295 $url_uri_query = $query = c_ws_plugin__s2member_utils_strings::trim ((string)$url_uri_query, false, "?&=");
296 $sig_var = ($sig_var && is_string ($sig_var)) ? $sig_var : /* Use default. */ "_s2member_sig";
297 /**/
298 $url_uri_query = $query = c_ws_plugin__s2member_utils_urls::remove_s2member_sigs ($url_uri_query, $sig_var);
299 if ( /* Is this a full URL, or a partial URI? */preg_match ("/^(?:[a-z]+\:\/\/|\/)/i", ($url_uri_query)))
300 $query = trim (c_ws_plugin__s2member_utils_urls::parse_url ($url_uri_query, PHP_URL_QUERY), "?&=");
301 /**/
302 $key = /* Obtain the proper encryption/decryption key. */ c_ws_plugin__s2member_utils_encryption::key ();
303 /**/
304 if ($url_uri_query && is_string /* We DO allow empty query strings. So we can sign a URL without one. */ ($query))
305 {
306 wp_parse_str /* Parse the query string into an array of ``$vars``. Then sort & serialize them into a string. */ ($query, $vars);
307 $vars = serialize (c_ws_plugin__s2member_utils_arrays::ksort_deep (c_ws_plugin__s2member_utils_strings::trim_deep ($vars)));
308 /**/
309 $sig = /* The s2Member-generated signature. */ ($time = time ()) . "-" . md5 ($key . $time . $vars);
310 /**/
311 $url_uri_query = add_query_arg ($sig_var, urlencode ($sig), $url_uri_query);
312 }
313 return /* Possibly with a ``$sig_var`` variable. */ $url_uri_query;
314 }
315 /**
316 * Verifies an s2Member-generated signature; in a full URL, a partial URI, or in just a query string.
317 *
318 * @package s2Member\Utilities
319 * @since 111106
320 *
321 * @param str $url_uri_query A full URL, a partial URI, or just a query string. Must have an s2Member-generated signature to validate.
322 * @param bool $check_time Optional. Defaults to false. If true, s2Member will also check if the signature has expired, based on ``$exp_secs``.
323 * @param str|int $exp_secs Optional. Defaults to (int)10. If ``$check_time`` is true, s2Member will check if the signature has expired, based on ``$exp_secs``.
324 * @param str $sig_var Optional. The name of the s2Member-generated signature variable. Defaults to `_s2member_sig`.
325 * @return bool True if the s2Member-generated signature is OK, else false.
326 */
327 public static function s2member_sig_ok ($url_uri_query = FALSE, $check_time = FALSE, $exp_secs = FALSE, $sig_var = FALSE)
328 {
329 $url_uri_query = $query = c_ws_plugin__s2member_utils_strings::trim ((string)$url_uri_query, false, "?&=");
330 if ( /* Is this a full URL, or a partial URI? */preg_match ("/^(?:[a-z]+\:\/\/|\/)/i", ($url_uri_query)))
331 $query = trim (c_ws_plugin__s2member_utils_urls::parse_url ($url_uri_query, PHP_URL_QUERY), "?&=");
332 /**/
333 $check_time = /* Are we checking time? Force a boolean value here. */ ($check_time) ? true : false;
334 $exp_secs = (is_numeric ($exp_secs)) ? (int)$exp_secs : /* Else 10 seconds by default here. */ 10;
335 $sig_var = ($sig_var && is_string ($sig_var)) ? $sig_var : /* Use default. */ "_s2member_sig";
336 /**/
337 $key = /* Obtain the proper encryption/decryption key. */ c_ws_plugin__s2member_utils_encryption::key ();
338 /**/
339 if (preg_match_all /* Does ``$query`` have an s2Member-generated signature? */ ("/" . preg_quote ($sig_var, "/") . "\=([0-9]+)-([^&$]+)/", $query, $sigs))
340 {
341 $query = /* Remove existing s2Member-generated signatures. */ c_ws_plugin__s2member_utils_urls::remove_s2member_sigs ($query, $sig_var);
342 /**/
343 wp_parse_str /* Parse the query string into an array of ``$vars``. Then sort & serialize them into a string. */ ($query, $vars);
344 $vars = serialize (c_ws_plugin__s2member_utils_arrays::ksort_deep (c_ws_plugin__s2member_utils_strings::trim_deep ($vars)));
345 /**/
346 ($time = $sigs[1][($i = count ($sigs[1]) - 1)]) . ($sig = $sigs[2][$i]) . ($valid_sig = md5 ($key . $time . $vars));
347 /**/
348 if /* Checking time? This must NOT be older than ``$exp_secs`` seconds ago. */ ($check_time)
349 return ($sig === $valid_sig && $time >= strtotime ("-" . $exp_secs . " seconds"));
350 /**/
351 else /* Ignoring time? Just need to compare signatures in this case. */
352 return /* Do they match up? */ ($sig === $valid_sig);
353 }
354 else /* Return false. No ``$query``, or no ``$sigs``. */
355 return /* False, it's NOT ok. */ false;
356 }
357 }
358 }
359 ?>