<?php
	
	error_reporting(E_ALL ^ E_STRICT);

	// returning false causes the web server to process the request
    // returning true causes the web server to do nothing, allowing this script to process the request
    
    // ========================================================================================================================
    // Return the current working directory to pair up with rw
    // ========================================================================================================================
    if (preg_match('/^\/RWWebServerCurrentWorkingDirectory.php$/', $_SERVER["REQUEST_URI"])) {
        return false;
    }
    
    // ========================================================================================================================
    // Used for auto-refresh to check if the server is still running
    // ========================================================================================================================
    if (preg_match('/^\/RWWebServerIsAliveAndKicking.txt$/', $_SERVER["REQUEST_URI"])) {
        return "Yup, hit me!";
    }
    
    // ========================================================================================================================
    // Allow pages running in preview to ask this server for remote information to bypass CORS
    // ========================================================================================================================
    if (preg_match('/^\/ajax\//', $_SERVER["REQUEST_URI"])) {
        
        $method = $_SERVER['REQUEST_METHOD'];
        $headers = array();
        $url = "";
        
        foreach (getallheaders() as $name => $value) {
            if (preg_match('/^Accept-Encoding$/i', $name)) {
                continue;
            }
            
            if (preg_match('/^Host$/i', $name)) {
                continue;
            }
            
            // echo "$name: $value <br>";
            
            if (preg_match('/^RW-REQUEST-URL$/i', $name)) {
                $url = $value;
            }
            else {
                $headers[] = "$name: $value";
            }
        }
        
        if (empty($url)) {
            echo "Please set an 'rw-request-url' header.";
            return true;
        }
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        
        if ($method == 'POST') {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST);
        }
        
        curl_setopt($ch, CURLOPT_RETURNTRANSFER , 0);
        curl_exec($ch);
        curl_close($ch);
        
        return true;
        
    }
    
    // ========================================================================================================================
    // Process the request
    // ========================================================================================================================
    $requestedFile = $_SERVER["DOCUMENT_ROOT"] . $_SERVER['REQUEST_URI'];
	$requestedFileParts = explode('?',$requestedFile);
	$requestedFile = array_shift($requestedFileParts);
	$requestedFile = rawurldecode($requestedFile);
    $requestedFileExists = file_exists($requestedFile);
    $performNavigation = '1';
    
    // Check for AJAX get requests pulling data from other pages and prevent navigation
    if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
        $performNavigation = '0';
    }
    
    if(isset($_GET['rw_perform_navigation']) && $_GET['rw_perform_navigation'] == 'no') {
        $performNavigation = '0';
    }

    
    
    // Support video streaming
    if(isset($_SERVER['HTTP_RANGE'])) {
        return sendFile($requestedFile);
    }
    
    // Check for known resource files
    if (preg_match('/(\.js|\.css|\.woff|\.woff2|\.ttf|\.svg)$/', $requestedFile)) {
        return false;
    }
    
    // Check for image files
    if (is_file($requestedFile) && getimagesize($requestedFile)) {
        return false;
    }
    
    // Check for plugin common files
    if (preg_match('/\/rw_common\//', $requestedFile)) {
        return false;
    }
    
    // Check for @0.5x, @2x, @3x image files
    if (preg_match('/@[2|3|0\.5]x\./', $requestedFile)) {
        $sdImageFileName = preg_replace('/@[2|3|0\.5]x\./', '.', $requestedFile);
        if (is_file($sdImageFileName) && getimagesize($sdImageFileName)) {
            return false;
        }
    }
    
    // Ask RW to export the requested page
    $fh = fopen('php://stdout','w') or die($php_errormsg);
    fwrite($fh, "EXPORT URL $requestedFile $performNavigation\n");
    fclose($fh);
    
    // Wait for an acknowledgement on the stdin channel
    $inputHandle = fopen('php://stdin','r');
    $line = fgets($inputHandle);
    fclose($inputHandle);
    
    // If RW didn't find a page at this URL
    if (preg_match('/^PageNotFound$/', $line)) {
        
        // If the file exists, it's most likely a page resource like js, css etc
        if (file_exists($requestedFile)) {
            return sendFile($requestedFile);
        }

        // If no page found and no resource exists, return an error
        include "RWWebServerPageNotFound.html";
        return true;
    }
    
    // Send the newly exported page to the browser
    $responseFile = $requestedFile;
    $renderPHP = false;
    
    if (preg_match('/^Exported (.*?) (.*?)$/', $line, $match)) {
        $dir = is_dir($responseFile) ? $responseFile : dirname($responseFile);
        
        if ($match[1] == 'PHP') {
            $renderPHP = true;
        }
        
        $newResponseFile = $dir . "/" . $match[2];
        
        // Check if the returned filename from RW actually exists. In the case of blog sub pages, it does not exist so we just use the requested page url
        if (file_exists($newResponseFile)) {
            $responseFile = $newResponseFile;
        }
    }
    
    // Change to the directory the file is in before including
    chdir(dirname($responseFile));
    
    function errorHandler($n, $m, $f, $l) {
        $line = $l;
        $fh = fopen('php://stderr','w') or die($php_errormsg);
        fwrite($fh, "ERROR Error:$n on line $line: $m\n");
        fclose($fh);
    }
    
    if (preg_match('/\.php$/', $responseFile) && $renderPHP == true){
        $old_error_handler = set_error_handler('errorHandler');
        include $responseFile;
        set_error_handler($old_error_handler);
    } else {
        echo file_get_contents($responseFile);
    }

    return true;
    
    
    function sendFile($file) {
        
        $fileHandle = @fopen($file,'rb');
        
        if(!$fileHandle) {
            header ("HTTP/1.0 505 Internal server error");
            return true;
        }

        $fileSize       = filesize($file);
        $contentLength  = $fileSize;
        $startByte      = 0;
        $endByte        = $fileSize;
        
        if (isset($_SERVER['HTTP_RANGE'])) {
            if (preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches)) {
                $startByte = $matches[1];
                if(!empty($matches[2])) {
                    $endByte = $matches[2];
                }
                fseek($fileHandle, $startByte, 0);
            }
            
        }
        
        $contentLength = $endByte - $startByte;
        
        if ($startByte > 0 || $endByte < $fileSize) {
            header('HTTP/1.1 206 Partial Content');
            header("Accept-Ranges: bytes");
            header("Content-Range: bytes $startByte-$endByte/$fileSize");
        }
        else {
            header('HTTP/1.1 200 OK');
            header("Content-Length: $fileSize");
        }
        
        
        header("Content-Type: " . mime_content_type($file));
        header("Content-Transfer-Encoding: binary");
        header("Cache-Control: public, must-revalidate, max-age=0");
        header("Pragma: no-cache");
        header("Connection: close");
        
        while (@ob_end_flush());
        
        $chunkSize = (1024 * 512);
        while(!feof($fileHandle) && ($p = ftell($fileHandle)) <= $endByte) {
            
            if ($p + $chunkSize > $endByte) {
                $chunkSize = $endByte - $p + 1;
            }
            
            set_time_limit(0);
            print fread($fileHandle, $chunkSize);
            flush();
        }
        
        fclose($fileHandle);
        
        return true;
    }
    
    function rw_require_failed($path) {
        $fh = fopen('php://stderr','w') or die($php_errormsg);
        fwrite($fh, "ERROR Ignoring missing file:$path\n");
        fclose($fh);
    }
    
?>
