| 1 |
<?php |
| 2 |
die('Disabled: use this only for testing'); |
| 3 |
|
| 4 |
/** |
| 5 |
* Fetch and minify a URL (auto-detect HTML/JS/CSS) |
| 6 |
*/ |
| 7 |
|
| 8 |
$app = (require __DIR__ . '/../../bootstrap.php'); |
| 9 |
/* @var \Minify\App $app */ |
| 10 |
|
| 11 |
$app->cache = new Minify_Cache_Null(); |
| 12 |
|
| 13 |
$env = $app->env; |
| 14 |
|
| 15 |
function getPost($key) |
| 16 |
{ |
| 17 |
if (! isset($_POST[$key])) { |
| 18 |
return null; |
| 19 |
} |
| 20 |
return (PHP_VERSION_ID < 50400 && get_magic_quotes_gpc()) |
| 21 |
? stripslashes($_POST[$key]) |
| 22 |
: $_POST[$key]; |
| 23 |
} |
| 24 |
|
| 25 |
function sniffType($headers) |
| 26 |
{ |
| 27 |
$charset = 'utf-8'; |
| 28 |
$type = null; |
| 29 |
$headers = "\n\n" . implode("\n\n", $headers) . "\n\n"; |
| 30 |
if (preg_match( |
| 31 |
'@\\n\\nContent-Type: *([\\w/\\+-]+)( *; *charset *= *([\\w-]+))? *\\n\\n@i', |
| 32 |
$headers, |
| 33 |
$m |
| 34 |
)) { |
| 35 |
$sentType = $m[1]; |
| 36 |
if (isset($m[3])) { |
| 37 |
$charset = $m[3]; |
| 38 |
} |
| 39 |
if (preg_match('@^(?:text|application)/(?:x-)?(?:java|ecma)script$@i', $sentType)) { |
| 40 |
$type = 'application/x-javascript'; |
| 41 |
} elseif (preg_match('@^(?:text|application)/(?:html|xml|xhtml+xml)$@i', $sentType, $m)) { |
| 42 |
$type = 'text/html'; |
| 43 |
} elseif ($sentType === 'text/css') { |
| 44 |
$type = $sentType; |
| 45 |
} |
| 46 |
} |
| 47 |
return array( |
| 48 |
'minify' => $type |
| 49 |
,'sent' => $sentType |
| 50 |
,'charset' => $charset |
| 51 |
); |
| 52 |
} |
| 53 |
|
| 54 |
if (isset($_POST['url'])) { |
| 55 |
require '../config.php'; |
| 56 |
|
| 57 |
$url = trim($env->post('url')); |
| 58 |
$ua = trim($env->post('ua')); |
| 59 |
$cook = trim($env->post('cook')); |
| 60 |
|
| 61 |
if (! preg_match('@^https?://@', $url)) { |
| 62 |
die('HTTP(s) only.'); |
| 63 |
} |
| 64 |
|
| 65 |
$httpOpts = array( |
| 66 |
'max_redirects' => 0 |
| 67 |
,'timeout' => 3 |
| 68 |
); |
| 69 |
if ($ua !== '') { |
| 70 |
$httpOpts['user_agent'] = $ua; |
| 71 |
} |
| 72 |
if ($cook !== '') { |
| 73 |
$httpOpts['header'] = "Cookie: {$cook}\r\n"; |
| 74 |
} |
| 75 |
$ctx = stream_context_create(array( |
| 76 |
'http' => $httpOpts |
| 77 |
)); |
| 78 |
|
| 79 |
// fetch |
| 80 |
if (! ($fp = @fopen($url, 'r', false, $ctx))) { |
| 81 |
die('Couldn\'t open URL.'); |
| 82 |
} |
| 83 |
$meta = stream_get_meta_data($fp); |
| 84 |
$content = stream_get_contents($fp); |
| 85 |
fclose($fp); |
| 86 |
|
| 87 |
// get type info |
| 88 |
$type = sniffType($meta['wrapper_data']); |
| 89 |
if (! $type['minify']) { |
| 90 |
die('Unrecognized Content-Type: ' . $type['sent']); |
| 91 |
} |
| 92 |
|
| 93 |
if ($type['minify'] === 'text/html' |
| 94 |
&& isset($_POST['addBase']) |
| 95 |
&& ! preg_match('@<base\\b@i', $content)) { |
| 96 |
$content = preg_replace( |
| 97 |
'@(<head\\b[^>]*>)@i', |
| 98 |
'$1<base href="' . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . '" />', |
| 99 |
$content |
| 100 |
); |
| 101 |
} |
| 102 |
|
| 103 |
$sourceSpec['content'] = $content; |
| 104 |
$sourceSpec['id'] = 'foo'; |
| 105 |
$sourceSpec['contentType'] = $type['minify']; |
| 106 |
|
| 107 |
if ($type['minify'] === 'text/html') { |
| 108 |
if ($env->post('minJs')) { |
| 109 |
$sourceSpec['minifyOptions']['jsMinifier'] = array('JSMin\\JSMin', 'minify'); |
| 110 |
} |
| 111 |
if ($env->post('minCss')) { |
| 112 |
$sourceSpec['minifyOptions']['cssMinifier'] = array('Minify_CSSmin', 'minify'); |
| 113 |
} |
| 114 |
} |
| 115 |
|
| 116 |
$source = new Minify_Source($sourceSpec); |
| 117 |
|
| 118 |
$sendType = 'text/plain'; |
| 119 |
if ($type['minify'] === 'text/html' && $env->post('asText') === null) { |
| 120 |
$sendType = $type['sent']; |
| 121 |
} |
| 122 |
if ($type['charset']) { |
| 123 |
$sendType .= ';charset=' . $type['charset']; |
| 124 |
} |
| 125 |
header('Content-Type: ' . $sendType); |
| 126 |
// using combine instead of serve because it allows us to specify a |
| 127 |
// Content-Type like application/xhtml+xml IF we need to |
| 128 |
|
| 129 |
try { |
| 130 |
echo $app->minify->combine(array($source)); |
| 131 |
} catch (Exception $e) { |
| 132 |
header('Content-Type: text/html;charset=utf-8'); |
| 133 |
echo htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8'); |
| 134 |
} |
| 135 |
exit(); |
| 136 |
} |
| 137 |
|
| 138 |
header('Content-Type: text/html; charset=utf-8'); |
| 139 |
|
| 140 |
$ua = $env->server('HTTP_USER_AGENT'); |
| 141 |
|
| 142 |
?> |
| 143 |
<!DOCTYPE html><head><title>Minify URL</title></head> |
| 144 |
|
| 145 |
<p><strong>Warning! Please do not place this application on a public site.</strong> This should be used only for testing.</p> |
| 146 |
|
| 147 |
<h1>Fetch and Minify a URL</h1> |
| 148 |
<p>This tool will retrieve the contents of a URL and minify it. |
| 149 |
The fetched resource Content-Type will determine the minifier used.</p> |
| 150 |
|
| 151 |
<form action="?2" method="post"> |
| 152 |
<p><label>URL: <input type="text" name="url" value="https://code.jquery.com/jquery-2.2.1.js" size="60"></label></p> |
| 153 |
<p><input type="submit" value="Fetch and minify"></p> |
| 154 |
|
| 155 |
<fieldset><legend>HTML options</legend> |
| 156 |
<p>If the resource above is sent with an (x)HTML Content-Type, the following options will apply:</p> |
| 157 |
<ul> |
| 158 |
<li><label><input type="checkbox" name="asText" checked> Return plain text (o/w send the original content type)</label> |
| 159 |
<li><label><input type="checkbox" name="minCss" checked> Minify CSS</label> |
| 160 |
<li><label><input type="checkbox" name="minJs" checked> Minify JS</label> |
| 161 |
<li><label><input type="checkbox" name="addBase" checked> Add BASE element (if not present)</label> |
| 162 |
</ul> |
| 163 |
</fieldset> |
| 164 |
|
| 165 |
<fieldset><legend>Retreival options</legend> |
| 166 |
<ul> |
| 167 |
<li><label>User-Agent: <input type="text" name="ua" size="60" value="<?php echo htmlspecialchars($ua, ENT_QUOTES, 'UTF-8'); ?>"></label> |
| 168 |
<li><label>Cookie: <input type="text" name="cook" size="60"></label> |
| 169 |
</ul> |
| 170 |
</fieldset> |
| 171 |
|
| 172 |
</form> |
| 173 |
|