1+ <?php
2+
3+ namespace Valet ;
4+
5+ class Server {
6+ /**
7+ * @var array
8+ */
9+ public $ config ;
10+
11+ public function __construct ($ config ) {
12+ $ this ->config = $ config ;
13+ }
14+
15+ /**
16+ * Extract $uri from $SERVER['REQUEST_URI'] variable.
17+ *
18+ * @param string $requestUri The request URI.
19+ *
20+ * @return string The extracted URI.
21+ */
22+ public function uriFromRequestUri ($ requestUri ) {
23+ return rawurldecode (
24+ explode ('? ' , $ requestUri )[0 ]
25+ );
26+ }
27+
28+ /**
29+ * Extract site name from HTTP host, stripping www. and supporting wildcard DNS.
30+ *
31+ * @param string $httpHost The HTTP host.
32+ *
33+ * @return string The extracted site name.
34+ */
35+ public function siteNameFromHttpHost ($ httpHost ) {
36+ $ siteName = basename (
37+ // Filter host to support wildcard dns feature
38+ $ this ->supportWildcardDnsDomains ($ httpHost ),
39+ '. ' .$ this ->config ['tld ' ]
40+ );
41+
42+ if (strpos ($ siteName , 'www. ' ) === 0 ) {
43+ $ siteName = substr ($ siteName , 4 );
44+ }
45+
46+ return $ siteName ;
47+ }
48+
49+ /**
50+ * You may use wildcard DNS providers xip.io or nip.io as a tool for testing your site via
51+ * an IP address.
52+ * It's simple to use: First determine the IP address of your local computer
53+ * (like 192.168.0.10).
54+ * Then simply use http://project.your-ip.xip.io - ie: http://laravel.192.168.0.10.xip.io.
55+ *
56+ * @param string $domain The domain to check.
57+ *
58+ * @return string The domain
59+ */
60+ public function supportWildcardDnsDomains ($ domain ) {
61+ $ services = [
62+ '.*.*.*.*.xip.io ' ,
63+ '.*.*.*.*.nip.io ' ,
64+ '-*-*-*-*.nip.io '
65+ ];
66+
67+ if (isset ($ this ->config ['tunnel_services ' ])) {
68+ $ services = array_merge ($ services , (array ) $ this ->config ['tunnel_services ' ]);
69+ }
70+
71+ $ patterns = [];
72+ foreach ($ services as $ service ) {
73+ $ pattern = preg_quote ($ service , '# ' );
74+ $ pattern = str_replace ('\* ' , '.* ' , $ pattern );
75+ $ patterns [] = '(.*) ' . $ pattern ;
76+ }
77+
78+ $ pattern = implode ('| ' , $ patterns );
79+
80+ if (preg_match ('#(?: ' . $ pattern . ')\z#u ' , $ domain , $ matches )) {
81+ $ domain = array_pop ($ matches );
82+ }
83+
84+ if (strpos ($ domain , ': ' ) !== false ) {
85+ $ domain = explode (': ' , $ domain )[0 ];
86+ }
87+
88+ return $ domain ;
89+ }
90+
91+ /**
92+ * Determine the fully qualified path to the site.
93+ * Inspects registered path directories, case-sensitive.
94+ *
95+ * @param string $siteName The site name.
96+ *
97+ * @return string|null The fully qualified path to the site, or null if not found.
98+ */
99+ public function sitePath ($ siteName ) {
100+ $ valetSitePath = null ;
101+ $ domain = $ this ->domainFromSiteName ($ siteName );
102+
103+ foreach ($ this ->config ['paths ' ] as $ path ) {
104+ if (!is_dir ($ path )) {
105+ continue ;
106+ }
107+
108+ $ handle = opendir ($ path );
109+
110+ if ($ handle === false ) {
111+ continue ;
112+ }
113+
114+ $ dirs = [];
115+
116+ while (($ file = readdir ($ handle )) !== false ) {
117+ if (is_dir ("$ path/ $ file " ) && !in_array ($ file , ['. ' , '.. ' ])) {
118+ $ dirs [] = $ file ;
119+ }
120+ }
121+
122+ closedir ($ handle );
123+
124+ foreach ($ dirs as $ dir ) {
125+ // Note: strtolower used below because Nginx only tells us lowercase names
126+ if (strtolower ($ dir ) === $ siteName ) {
127+ // Early return when exact match for linked subdomain
128+ return "$ path/ $ dir " ;
129+ }
130+
131+ if (strtolower ($ dir ) === $ domain ) {
132+ // No early return here because the foreach may still have some subdomains to
133+ // process with higher priority
134+ $ valetSitePath = "$ path/ $ dir " ;
135+ }
136+ }
137+
138+ if ($ valetSitePath ) {
139+ return $ valetSitePath ;
140+ }
141+ }
142+
143+ return null ;
144+ }
145+
146+ /**
147+ * Extract the domain from the site name.
148+ *
149+ * @param string $siteName The site name.
150+ *
151+ * @return string The extracted domain.
152+ */
153+ public function domainFromSiteName ($ siteName ) {
154+ return array_slice (explode ('. ' , $ siteName ), -1 )[0 ];
155+ }
156+
157+ /**
158+ * Get the default site path for uncaught URLs, if it's set.
159+ *
160+ * @return string|null If set, default site path for uncaught urls
161+ */
162+ public function defaultSitePath () {
163+ if (isset ($ this ->config ['default ' ]) && is_string ($ this ->config ['default ' ]) && is_dir ($ this ->config ['default ' ])) {
164+ return $ this ->config ['default ' ];
165+ }
166+
167+ return null ;
168+ }
169+
170+ /**
171+ * Set the ngrok server forwarded host if it's not already set.
172+ * (ngrok uses the X-Original-Host to store the forwarded hostname.)
173+ */
174+ public function setNgrokServerForwardedHost () {
175+ if (isset ($ _SERVER ['HTTP_X_ORIGINAL_HOST ' ]) && !isset ($ _SERVER ['HTTP_X_FORWARDED_HOST ' ])) {
176+ $ _SERVER ['HTTP_X_FORWARDED_HOST ' ] = $ _SERVER ['HTTP_X_ORIGINAL_HOST ' ];
177+ }
178+ }
179+
180+ /**
181+ * Is the incoming request for a static file?
182+ *
183+ * @param string $uri The URI of the request.
184+ * @param string $valetSitePath The path to the Valet site.
185+ * @param string $siteName The name of the site.
186+ * @param object $valetDriver The Valet driver instance.
187+ *
188+ * @return string|false The path to the static file or false if not found.
189+ */
190+ public function isRequestStaticFile ($ uri , $ valetSitePath , $ siteName , $ valetDriver ) {
191+
192+ $ isPhpFile = pathinfo ($ uri , PATHINFO_EXTENSION ) === 'php ' ;
193+
194+ if ($ uri !== '/ ' && !$ isPhpFile && $ staticFilePath = $ valetDriver ->isStaticFile ($ valetSitePath , $ siteName , $ uri )) {
195+ return $ staticFilePath ;
196+ }
197+ return false ;
198+ }
199+
200+ /**
201+ * Show the Valet 404 "Not Found" page.
202+ */
203+ public function show404 () {
204+ http_response_code (404 );
205+ require __DIR__ . '/../templates/404.html ' ;
206+ exit ;
207+ }
208+
209+ /**
210+ * Show directory listing or 404 if directory doesn't exist.
211+ *
212+ * @param string $valetSitePath The path to the Valet site.
213+ * @param string $uri The URI of the request.
214+ */
215+ public function showDirectoryListing ($ valetSitePath , $ uri ) {
216+ $ is_root = ($ uri == '/ ' );
217+ $ directory = $ is_root ? $ valetSitePath : $ valetSitePath . $ uri ;
218+
219+ if (!file_exists ($ directory )) {
220+ $ this ->show404 ();
221+ }
222+
223+ // Sort directories at the top
224+ $ paths = glob ("$ directory/* " );
225+ usort ($ paths , function ($ a , $ b ) {
226+ return (is_dir ($ a ) == is_dir ($ b )) ? strnatcasecmp ($ a , $ b ) : (is_dir ($ a ) ? -1 : 1 );
227+ });
228+
229+ // If the directory is a file, output its contents and exit.
230+ if (is_file ($ directory )) {
231+ echo "<pre> " ;
232+ echo file_get_contents ($ directory );
233+ echo "</pre> " ;
234+
235+ exit ;
236+ }
237+
238+ // Output the HTML for the directory listing
239+ echo "<h1>Index of $ uri</h1> " ;
240+ echo '<hr> ' ;
241+ echo implode ("<br> \n" , array_map (function ($ path ) use ($ uri , $ is_root ) {
242+ $ file = basename ($ path );
243+
244+ return ($ is_root ) ? "<a href='/ $ file'>/ $ file</a> " : "<a href=' $ uri/ $ file'> $ uri/ $ file/</a> " ;
245+ }, $ paths ));
246+
247+ exit ;
248+ }
249+
250+ /**
251+ * Show directory listing if it's enabled or 404.
252+ *
253+ * @param string $valetSitePath The path to the Valet site.
254+ * @param string $uri The URI of the request.
255+ */
256+ public function showDirectoryListingOr404 ($ valetSitePath , $ uri ) {
257+ if (isset ($ this ->config ['directory-listing ' ]) && $ this ->config ['directory-listing ' ] == 'on ' ) {
258+ $ this ->showDirectoryListing ($ valetSitePath , $ uri );
259+ }
260+
261+ $ this ->show404 ();
262+ }
263+
264+ /**
265+ * Change into front controller path when executing
266+ *
267+ * @param string $frontControllerPath The path to the front controller.
268+ */
269+ public function changeDir ($ frontControllerPath ) {
270+ chdir (dirname ($ frontControllerPath ));
271+ }
272+ }
0 commit comments