PageSourceSearch

https://thethrottleup.com/gdpr/gdprscript.js?buildTime=1705295107&hasRemindMe=true&stealth=false

js thethrottleup.com collected 2026-09-30 20:24:00 UTC 11,861 bytes, 436 lines download raw bytes

1<?php
2/**
3 * Handler performs request handling and file proxying via stepping in front of the 404 handler
4 *
5 * @package Weebly
6 * @subpackage ResellerServices
7 * @author Dustin Doiron <[email protected]>
8 * @since 2014-07-01
9 * @copyright 2014 Weebly, Inc
10 */
11require_once( __DIR__ . '/Bootstrap.php' );
12
13define("MEMORY_LIMIT", 1048576);
14
15class Handler
16{
17	/**
18	 * @var $request
19	 */
20	private $request = NULL;
21
22	/**
23	 * @var $site
24	 */
25	private $site = NULL;
26
27	/**
28	 * @var boolean
29	 */
30	private $isRedirect = false;
31
32	/**
33	 * Constructor
34	 * On construct, Handler runs through everything needed to either render the requested page, or render a 404
35	 * No methods are called outside of this class, and no values are returned
36	 *
37	 * @param array $request
38	 *
39	 * @return void
40	 */
41	public function __construct( $request )
42	{
43		$this->buildSiteArray( );
44		$this->buildRequestArray( $request );
45
46		/**
47		 * Is this an API request to a client API that we need to proxy along?
48		 */
49		if ( $this->isClientApiRequest( ) === true )
50		{
51			\OriginAPI::makeClientAPIRequest( $this->request, file_get_contents( 'php://input' ) );
52		}
53
54		if ( $this->isPage( ) === true )
55		{
56			/**
57			 * Might have the mobile cookie, and just need to get redirected to mobile file on disk
58			 * For dynamic mobile page, always let dynamic page handle it.
59			 */
60			if (
61				$this->request['mobile'] === true &&
62				file_exists( \BASE_DOCROOT_DIR . '/mobile/' . $this->request['file'] ) === true
63			) {
64				\setcookie( 'is_mobile', 1, time( ) + 2592000, '/' );
65				if ($this->isDynamicPage() === false) {
66					\Output::sendHeader('Location: ' . $this->request['file']);
67					$this->isRedirect = true;
68					$this->finalizeOutput();
69					exit();
70				}
71			}
72
73			/**
74			 * Do we have it in the page hierarchy, or is it a dynamic page? Go get it from Origin
75			 */
76			if ($this->isPageInPublishedData( $this->request['file'] ) === true || $this->isDynamicPage( ) === true )
77			{
78				$this->isDynamicStandardPage(); // update request with isDynamic if needed
79				$response = \OriginRequest::getObject( $this->request );
80				$this->handleOriginResponse( $response );
81			} else {
82				\Output::render404( );
83			}
84
85			/**
86			 * Should we try a simple redirect from .htm to .html?
87			 */
88			if ( $this->isPageInPublishedData( $this->request['file'] . 'l' ) === true )
89			{
90				if ( file_exists( \BASE_DOCROOT_DIR . '/' . $this->request['file'] ) === true )
91				{
92					\Output::sendHeader( 'Location: ' . $this->request['file'] . 'l' );
93					$this->isRedirect = true;
94					$this->finalizeOutput();
95					exit( );
96				}
97				else
98				{
99					/**
100					 * Don't have it yet, go get it before forwarding
101					 */
102					$this->request['file'] .= 'l';
103					$this->isDynamicStandardPage(); // update request with isDynamic if needed
104					$response = \OriginRequest::getObject( $this->request );
105					$this->handleOriginResponse( $response );
106				}
107			}
108		}
109		else
110		{
111			/**
112			 * Not a page, we have to use benefit of the doubt here for checking origin
113			 */
114			// Assets files.
115			// Set default memory_limit so wServer will send back retryRaw message for file larger than 1MB.
116			// Not setting it means it's remote server published before this change,
117			// then wServer will always return old type of response. (no retryRaw mechanism)
118			$this->request['memory_limit'] = MEMORY_LIMIT;
119			$response = \OriginRequest::getObject( $this->request );
120			$this->handleOriginResponse( $response );
121		}
122
123		// if redirect header, then add text to prevent some ftp server's firewall from block pure header redirect.
124		$this->finalizeOutput();
125	}
126
127	/**
128	 * Builds the site array for the current request
129	 *
130	 * @return void
131	 */
132	private function buildSiteArray( )
133	{
134		if ( file_exists( \BASE_SERVICES_DIR . '/' . Configuration::PUBLISHED_DATA_LOCATION ) === true )
135		{
136			$this->site = json_decode( file_get_contents( \BASE_SERVICES_DIR . '/' . Configuration::PUBLISHED_DATA_LOCATION ), true );
137		}
138	}
139
140	/**
141	 * Builds the request data array for the current request
142	 * During one of the build cases, we may redirect out to the properly formed .html location
143	 *
144	 * @param array $request
145	 *
146	 * @return void
147	 */
148	private function buildRequestArray( $request )
149	{
150		// Better detection of HTTPS
151		if (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] === 'on' || $_SERVER['HTTPS'] == '1')) {
152			$_SERVER['REQUEST_SCHEME'] = 'https';
153		} elseif (!isset($_SERVER['REQUEST_SCHEME'])) {
154			$_SERVER['REQUEST_SCHEME'] = 'http';
155		}
156
157		$this->request = parse_url( $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'] );
158
159		// Always trim the trailing slash.
160		$this->request['path'] = rtrim($this->request['path'], '/');
161		$this->request['directories'] = explode('/', trim( $this->request['path'], '/' ));
162		$this->request['headers'] = self::getHeaders( );
163		$this->request['method'] = $_SERVER['REQUEST_METHOD'];
164
165		if ( count( $this->request['directories'] ) > 1 )
166		{
167			$this->request['file'] = array_pop( $this->request['directories'] );
168		}
169		else
170		{
171			unset( $this->request['directories'] );
172			$this->request['file'] = trim($this->request['path'], '/');
173		}
174
175		if ( strpos( $this->request['file'], '.' ) === false )
176		{
177			/**
178			 * Is this a redirect to a .html file?
179			 */
180			$file = trim($this->request['path'], '/' ) . '.html';
181
182			if ( $this->isPageInPublishedData( $file ) === true )
183			{
184				\Output::sendHeader( 'Location: /' . $file );
185				$this->isRedirect = true;
186				$this->finalizeOutput();
187				exit( );
188			}
189
190			if ( $this->request['file'] !== '' )
191			{
192				$this->request['directories'][] = $this->request['file'];
193			}
194
195			$this->request['file'] = 'index.html';
196
197			if ( $this->request['path'] === '/' )
198			{
199				$this->request['path'] = $this->request['path'] . $this->request['file'];
200			}
201		}
202
203		$this->request['ua'] = $_SERVER['HTTP_USER_AGENT'];
204		$this->request['mobile'] = ( ( isset( $_COOKIE['disable_mobile'] ) === false || $_COOKIE['disable_mobile'] === '0' ) &&
205			( isset( $_COOKIE['is_mobile'] ) && $_COOKIE['is_mobile'] !== '0' || isset( $this->request['directories'] ) && $this->request['directories'][0] === 'mobile' ) );
206	}
207
208	/**
209	 * Handles a response from Origin, generally the last item in the lifecycle of a request
210	 *
211	 * @param mixed $response
212	 *
213	 * @return void
214	 */
215	private function handleOriginResponse( $response )
216	{
217		/**
218		 * Origin didn't have the object
219		 */
220		if ( $response === false )
221		{
222			\Output::render404( );
223		}
224
225		/**
226		 * We're good to go, start rendering
227		 */
228		\Output::sendHeader( $_SERVER['SERVER_PROTOCOL'] . ' 200 OK' );
229
230		/**
231		 * Origin had the object, and it's now stored on disk, render the stored object
232		 */
233		if ( $response === true )
234		{
235			if ( isset( $_COOKIE['is_redirecting'] ) === true )
236			{
237				sleep( 2 );
238			}
239
240			\setcookie( 'is_redirecting', 1, time( ) + 5 );
241			\Output::sendHeader( 'Location: ' . $this->request['path'] );
242			$this->isRedirect = true;
243		}
244
245		if ( is_object( $response ) === true )
246		{
247			/**
248			 * It's a streaming object, so we'll render it from here
249			 */
250			\Output::sendHeader( $_SERVER['SERVER_PROTOCOL'] . ' 200 OK' );
251
252			if ($response->type && $response->type === 'js') {
253				\Output::sendHeader('Content-Type: text/javascript;');
254			}
255
256			\Output::render( \Output::decodeWireObject( $response->object ) );
257		}
258	}
259
260	/**
261	 * Determines if the current request is to a page
262	 *
263	 * @return bool
264	 */
265	private function isPage( )
266	{
267		/**
268		 * The only pages with directories are mobile pages and dynamic pages (commerce & blog)
269		 */
270		if( isset( $this->request['directories'] ) === true
271			&& count( $this->request['directories'] ) > 0
272			&& $this->request['directories'] !== 'mobile' && $this->isDynamicPage( ) === false
273		)
274		{
275			$this->request['isPage'] = false;
276			return false;
277		}
278
279		if ( preg_match( '/.html\Z/', $this->request['file'] ) > 0 || preg_match( '/.htm\Z/', $this->request['file'] ) > 0 )
280		{
281			$this->request['isPage'] = true;
282			return true;
283		}
284
285		$this->request['isPage'] = false;
286		return false;
287	}
288
289	/**
290	 * Uses base directory to determine if the a page is a dynamic page (blog & commerce)
291	 * These pages are not always in published data and therefore require directory checking
292	 *
293	 * @return bool
294	 */
295	private function isDynamicPage()
296	{
297		if ( isset( $this->request['directories'] ) === true && count( $this->request['directories'] ) > 0 )
298		{
299			/**
300			 * Check if either the base directory is a store or a call to a file in the apps folder
301			 * or if it is the base directory for a blog (meaning the base directory is also a file in published data)
302			 */
303			if ( $this->isDynamicRoute( $this->request['directories'][0] ) ||
304				( is_numeric( $this->request['directories'][0] ) === true )
305			)
306			{
307				return true;
308			}
309		}
310
311		return false;
312	}
313
314	/**
315	 * Check if a standard page should be considered dynamic, thus not cached.
316	 * i.e. Standard page with commerce element, we want to keep commerce data up to date,
317	 *     So we can't allow odysseus to cache the page, serving outdated commerce data.
318	 *
319	 * @return bool
320	 */
321	private function isDynamicStandardPage()
322	{
323		if ($this->isDynamicRoute(ltrim($this->request['path'], '/'))) {
324			// page containing commerce element is considered dynamic page here,
325			// so odysseus don't cache it.
326			// so commerce data can stay up to date.
327
328			// we add a isDynamic in request.
329			// it will tell DeployedServiceController to return in dynamic page's format instead.
330			$this->request['isDynamic'] = true;
331			return true;
332		}
333		return false;
334	}
335
336	/**
337	 * Determines if the first directory in the request is a known "dynamic" endpoint
338	 *
339	 * @param string $directory
340	 *
341	 * @return bool
342	 */
343	private function isDynamicRoute( $directory )
344	{
345		if (starts_with_any($directory, array('store', 'blog', 'apps', 'gdpr', '.well-known'))) {
346			return true;
347		}
348
349		return (isset($this->site['dynamic']) && isset($this->site['dynamic'][$directory]));
350	}
351
352	/**
353	 * Determines if the current page (by filename) is in the published site data hierarchy
354	 *
355	 * @param string $page
356	 *
357	 * @return bool
358	 */
359	private function isPageInPublishedData( $page )
360	{
361		if ( isset( $page ) === false )
362		{
363			$page = $this->request['file'];
364		}
365
366		return in_array( $page, $this->site['pages'] );
367	}
368
369	/**
370	 * Determines if the current request is a client API related request
371	 *
372	 * @return bool
373	 */
374	private function isClientApiRequest( )
375	{
376		if ( strpos( $this->request['path'], '/ajax/' ) === 0 )
377		{
378			return true;
379		}
380
381		if (strpos($this->request['path'], '/app/store/api/') === 0) {
382			return true;
383		}
384
385		return false;
386	}
387
388	/**
389	 * Attempts to retrieve the HTTP headers from the current request
390	 *
391	 * @return array|bool
392	 */
393	private static function getHeaders( )
394	{
395		if ( \function_exists( 'apache_request_headers' ) === true )
396		{
397			return \apache_request_headers( );
398		}
399
400		foreach ( $_SERVER as $key => $value )
401		{
402			if ( substr( $key, 0, 5 ) === 'HTTP_' )
403			{
404				$headers[str_replace( ' ', '-', ucwords( strtolower( str_replace( '_', ' ', substr( $key, 5 ) ) ) ) )] = $value;
405			}
406			elseif ( $key === 'CONTENT_TYPE' || $key === 'CONTENT_LENGTH' )
407			{
408				$headers[str_replace( '_', '-', ucwords( strtolower( $key ) ) )] = $value;
409			}
410		}
411
412		if ( isset(  $headers ) === true )
413		{
414			return $headers;
415		}
416
417		return false;
418	}
419
420	/**
421	 * Output some content if the page has redirect header.
422	 *
423	 * This is used to prevent some FTP (i.e. fatcow.com) has firewall not allow empty content redirect header.
424	 *
425	 */
426	private function finalizeOutput()
427	{
428		if ($this->isRedirect === true) {
429			// this shouldn't appear, as redirect header would take care of it.
430			// in case it's seen, reload link would help user to manually reload/redirect the page.
431			echo "<a onclick='location.reload()'>click here to reload the page.</a>";
432		}
433	}
434}
435
436$handler = new Handler( $_REQUEST );

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.