Last active
December 30, 2015 07:29
-
-
Save eugeneglova/7796458 to your computer and use it in GitHub Desktop.
html2canvas php proxy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* html2canvas proxy script | |
* | |
* Provides proxy service for html2canvas.js lib. | |
* Responsible for output javascript callback with image url | |
* to provide work around for the same origin limitation. | |
* | |
* Used to ensure that project images are included in the export PNGs, | |
* as a client side JS request for the file will trip up on CORS issues. | |
* | |
* This script is locked down to certain origins and works only with images. | |
* | |
* The origin of the request should come from either: | |
* - *.typecast.com | |
* - *.frontinternal.net (our dev vhosts) | |
* | |
* Only images are allowed to be proxied through the script. | |
* | |
* Images are detected by content type header. | |
* | |
* @author Eugene Glova | |
*/ | |
class Html2CanvasProxy { | |
// Reference to the url | |
private $url; | |
// Reference to the callback name | |
private $callback_name; | |
// List of the allowed origins | |
private $allowed_origins = array( | |
'typecast.com', | |
'frontinternal.net' | |
); | |
/** | |
* __construct | |
* | |
* Constructor. Accepts url and callback name | |
* | |
* @param string $url | |
* @param string $callback_name | |
* @return Html2CanvasProxy | |
*/ | |
public function __construct($url, $callback_name) { | |
// Check url | |
if ( ! is_string($url) || strlen($url) < 1) return false; | |
// Check callback_name | |
if ( ! is_string($callback_name) || strlen($callback_name) < 1) return false; | |
// Check for origin | |
if ( ! $this->isAllowedOrigin()) return false; | |
// Set url | |
$this->url = $url; | |
// Set callback name | |
$this->callback_name = $callback_name; | |
return $this; | |
} | |
/** | |
* getContent | |
* | |
* Returns javascript callback with argument | |
* | |
* @return string | |
*/ | |
public function getContent() { | |
// Set http headers | |
$this->setHeaders(); | |
// Get callback with content | |
return $this->getCallback(); | |
} | |
/** | |
* isAllowedOrigin | |
* | |
* Returns true if the http referer is in list of allowed origins | |
* | |
* @return boolean | |
*/ | |
private function isAllowedOrigin() { | |
// Get http referer host | |
$host = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST); | |
// Loop through allowed origins | |
foreach ($this->allowed_origins as $allowed_host) { | |
// Compare referer host with allowed origins | |
if (strstr($host, $allowed_host) === $allowed_host) return true; | |
} | |
return false; | |
} | |
/** | |
* setHeaders | |
* | |
* Sets application/javascript content type http header | |
* | |
* @return boolean | |
*/ | |
private function setHeaders() { | |
// Set content type header for the output | |
header('Content-Type: application/javascript'); | |
return true; | |
} | |
/** | |
* getImageBase64DataUrl | |
* | |
* Downloads image data by provided url | |
* and returns base64 encoded data url like | |
* data:image/png;base64,... | |
* | |
* @param string $url | |
* @return string | |
*/ | |
private function getImageBase64DataUrl() { | |
// Get url scheme | |
$scheme = parse_url($this->url, PHP_URL_SCHEME); | |
// Check url scheme | |
if (strpos($scheme, 'http') !== 0) return false; | |
// Get data by url | |
$data = file_get_contents($this->url); | |
// Check data | |
if ( ! is_string($data) || strlen($data) < 1) return false; | |
// Get content type | |
foreach ($http_response_header as $header) { | |
// Check for image content type | |
if ( ! $this->isImageContentTypeHeader($header)) continue; | |
// Get content type | |
$content_type = $this->getContentTypeByHeader($header); | |
break; | |
} | |
// Check content type | |
if ( ! is_string($content_type) || strlen($content_type) < 1) return false; | |
return 'data:' . $content_type . ';base64,' . base64_encode($data); | |
} | |
/** | |
* isImageContentTypeHeader | |
* | |
* Returns true if 'Content-type' header is like 'image/jpeg' | |
* | |
* @param string $header | |
* @return boolean | |
*/ | |
private function isImageContentTypeHeader($header) { | |
// Check header | |
if ( ! is_string($header) || strlen($header) < 1) return false; | |
// Check content type for image | |
if ( ! preg_match('/^content-type:\s*image\/\w+/i', $header)) return false; | |
return true; | |
} | |
/** | |
* getContentTypeByHeader | |
* | |
* Returns сontent type like 'image/jpeg' | |
* | |
* @param string $header | |
* @return string | |
*/ | |
private function getContentTypeByHeader($header) { | |
// Check header | |
if ( ! is_string($header) || strlen($header) < 1) return false; | |
// Check for type and get it | |
if ( ! preg_match('/^content-type:\s*(\w+\/\w+)/i', $header, $matches)) return false; | |
return $matches[1]; | |
} | |
/** | |
* getCallback | |
* | |
* Returns javascript callback | |
* | |
* @return string | |
*/ | |
private function getCallback() { | |
return $this->callback_name . '(' . json_encode($this->getImageBase64DataUrl()) . ')'; | |
} | |
} | |
// Create an instance of the class | |
$proxy = new Html2CanvasProxy($_GET['url'], $_GET['callback']); | |
// Output content | |
echo $proxy->getContent(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment