PluginProbe
Surge / 1.0.3
Surge v1.0.3
trunk 0.1.0 1.0.0 1.0.2 1.0.3 1.0.5 1.1.0 1.2.0 1.2.1
surge / include / common.php

common.php in Surge 1.0.3, at include/common.php

233 lines 5.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Surge Common
4 *
5 * Common functions used by various Surge components.
6 *
7 * @package Surge
8 */
9
10 namespace Surge;
11
12 const CACHE_DIR = WP_CONTENT_DIR . '/cache/surge';
13
14 /**
15 * Caching configuration settings.
16 *
17 * @param string $key Configuration key
18 *
19 * @return mixed The config value for the supplied key.
20 */
21 function config( $key ) {
22 static $config = null;
23
24 if ( isset( $config ) ) {
25 return $config[ $key ];
26 }
27
28 $config = [
29 'ttl' => 600,
30 'ignore_cookies' => [ 'wordpress_test_cookie' ],
31
32 // https://github.com/mpchadwick/tracking-query-params-registry/blob/master/_data/params.csv
33 'ignore_query_vars' => [
34 'fbclid', 'gclid', 'gclsrc', 'utm_content', 'utm_term', 'utm_campaign',
35 'utm_medium', 'utm_source', 'utm_id', '_ga', 'mc_cid', 'mc_eid',
36 '_bta_tid', '_bta_c', 'trk_contact', 'trk_msg', 'trk_module', 'trk_sid',
37 'gdfms', 'gdftrk', 'gdffi', '_ke', 'redirect_log_mongo_id',
38 'redirect_mongo_id', 'sb_referer_host', 'mkwid', 'pcrid', 'ef_id',
39 's_kwcid', 'msclkid', 'dm_i', 'epik', 'pk_campaign', 'pk_kwd',
40 'pk_keyword', 'piwik_campaign', 'piwik_kwd', 'piwik_keyword', 'mtm_campaign',
41 'mtm_keyword', 'mtm_source', 'mtm_medium', 'mtm_content', 'mtm_cid',
42 'mtm_group', 'mtm_placement', 'matomo_campaign', 'matomo_keyword',
43 'matomo_source', 'matomo_medium', 'matomo_content', 'matomo_cid',
44 'matomo_group', 'matomo_placement', 'hsa_cam', 'hsa_grp', 'hsa_mt',
45 'hsa_src', 'hsa_ad', 'hsa_acc', 'hsa_net', 'hsa_kw', 'hsa_tgt',
46 'hsa_ver', '_branch_match_id',
47 ],
48
49 // Add items to this array to add a unique cache variant.
50 'variants' => [],
51 ];
52
53 // Run a custom configuration file.
54 if ( defined( 'WP_CACHE_CONFIG' ) ) {
55 $_config = ( function( $config ) {
56 $_config = (array) include( WP_CACHE_CONFIG );
57 return $_config;
58 } ) ( $config );
59
60 $config = array_merge( $config, $_config );
61 }
62
63 return $config[ $key ];
64 }
65
66 /**
67 * Generate a cache key array.
68 *
69 * @return array
70 */
71 function key() {
72 static $cache_key = null;
73
74 if ( isset( $cache_key ) ) {
75 return $cache_key;
76 }
77
78 // Break the URL down.
79 $parsed = parse_url( 'http://example.org' . $_SERVER['REQUEST_URI'] );
80 $path = $parsed['path'];
81 $query = $parsed['query'] ?? '';
82 $query_vars = [];
83
84 // Simplified parse_str without urldecoding
85 foreach ( explode( '&', $query ) as $pair ) {
86 $parts = explode( '=', $pair, 2 );
87 $key = $parts[0];
88 $value = $parts[1] ?? '';
89
90 if ( ! array_key_exists( $key, $query_vars ) ) {
91 $query_vars[ $key ] = $value;
92 } else {
93 if ( ! is_array( $query_vars[ $key ] ) ) {
94 $query_vars[ $key ] = [ $query_vars[ $key ] ];
95 }
96 $query_vars[ $key ][] = $value;
97 }
98 }
99
100 // Ignore some query vars.
101 foreach ( $query_vars as $key => $value ) {
102 if ( in_array( $key, config( 'ignore_query_vars' ) ) ) {
103 unset( $query_vars[ $key ] );
104 }
105 }
106
107 $cache_key = [
108 'https' => $_SERVER['HTTPS'] ?? '',
109 'method' => strtoupper( $_SERVER['REQUEST_METHOD'] ) ?? '',
110 'host' => strtolower( $_SERVER['HTTP_HOST'] ?? '' ),
111 'path' => $path,
112 'query_vars' => $query_vars,
113 'cookies' => [],
114 'variants' => config( 'variants' ),
115 ];
116
117 // Return early if this request is anonymized.
118 if ( anonymize( $cache_key ) ) {
119 return $cache_key;
120 }
121
122 // Clean up and normalize cookies.
123 $cookies = [];
124 foreach ( $_COOKIE as $key => $value ) {
125
126 // Ignore cookies that begin with a _, assume they're JS-only.
127 if ( substr( $key, 0, 1 ) == '_' ) {
128 unset( $_COOKIE[ $key ] );
129 continue;
130 }
131
132 if ( ! in_array( $key, config( 'ignore_cookies' ) ) ) {
133 $cookies[ $key ] = $value;
134 }
135 }
136
137 $cache_key['cookies'] = $cookies;
138
139 return $cache_key;
140 }
141
142 function flag( $flag = null ) {
143 static $flags;
144
145 if ( ! isset( $flags ) ) {
146 $flags = [];
147 }
148
149 if ( $flag ) {
150 $flags[] = $flag;
151 }
152
153 return $flags;
154 }
155
156 function expire( $flag = null ) {
157 static $expire;
158
159 if ( ! isset( $expire ) ) {
160 $expire = [];
161 }
162
163 if ( $flag ) {
164 $expire[] = $flag;
165 }
166
167 return $expire;
168 }
169
170 /**
171 * Read metadata from a file resource.
172 *
173 * @param resource $f A file resource opened with fopen().
174 *
175 * @return null|array The decoded cache metadata or null.
176 */
177 function read_metadata( $f ) {
178 // Skip security header.
179 fread( $f, strlen( '<?php exit; ?>' ) );
180
181 // Read the metadata length.
182 $bytes = fread( $f, 4 );
183 if ( ! $bytes ) {
184 return;
185 }
186
187 $data = unpack( 'Llength', $bytes );
188 if ( empty( $data['length'] ) ) {
189 return;
190 }
191
192 $bytes = fread( $f, $data['length'] );
193 $meta = json_decode( $bytes, true );
194 return $meta;
195 }
196
197 /**
198 * Anonymize a request
199 *
200 * This function checks whether this request should be anonymized, and alters
201 * the cache key to reflect that. Also touches certain super-globals, such
202 * as $_COOKIE to make sure the request is truly anonymous.
203 *
204 * @param string $cache_key The cache key, passed by reference
205 *
206 * @return bool True if the request was anonymized.
207 */
208 function anonymize( &$cache_key ) {
209
210 // Don't anonymize POST and other requests that may alter data.
211 if ( $cache_key['method'] !== 'GET' && $cache_key['method'] !== 'HEAD' ) {
212 return false;
213 }
214
215 // TODO: Maybe increase the TTL on these paths.
216 if ( ! in_array( $cache_key['path'], [
217 '/robots.txt',
218 '/favicon.ico',
219 ] ) ) {
220 return false;
221 }
222
223 // Very anonymous.
224 // TODO: Clean php://input too.
225 $_COOKIE = [];
226 $_GET = [];
227 $_REQUEST = [];
228 $_POST = [];
229
230 $cache_key['query_vars'] = [];
231 return true;
232 }
233