Sequenzia/lib/Danbooru.php

98 lines
3.9 KiB
PHP
Executable File

<?php
abstract class Danbooru
{
static public function http_get_streaming($source, array $options = [], $block = null)
{
$max_size = !empty($options['max_size']) ? $options['max_size'] : CONFIG()->max_image_size;
if (!$max_size == 0) # unlimited
$max_size = null;
# Decode data: URLs.
if (preg_match('/^data:([^;]{1,100})(;[^;]{1,100})?,(.*)$/', $source, $m)) {
$data = base64_decode($m[3]);
return $data;
}
$redirections_limit = 4;
$timeout = (int)CONFIG()->http_streaming_timeout;
$file = '';
$write_function = function($handle, $data) use (&$file, $max_size) {
$file .= $data;
if ($max_size && strlen($file) > $max_size)
return 0;
return strlen($data);
};
while (true) {
$file = '';
$url = parse_url($source);
if (empty($url['scheme']) || $url['scheme'] != 'http' && $url['scheme'] != 'https')
throw new Danbooru\Exception\RuntimeException('SocketError: URL must be HTTP or HTTPS');
# check if the request uri is not percent-encoded
// if url.request_uri.match "/[^!*'();:@&=+$,\/?#\[\]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\-_.~%]/"
// url.path = Addressable::URI.encode(url.path)
// url.query = Addressable::URI.encode(url.query)
// end
# Addressable doesn't fill in port data if not explicitly given.
if (!isset($url['port']))
$url['port'] = $url['scheme'] == 'https' ? 443 : 80;
$opts = [];
if ($url['scheme'] == 'https') {
$opts[CURLOPT_SSL_VERIFYPEER] = false;
$opts[CURLOPT_SSL_VERIFYHOST] = false;
}
if ($timeout)
$opts[CURLOPT_TIMEOUT] = $timeout;
$opts[CURLOPT_RETURNTRANSFER] = true;
$opts[CURLINFO_HEADER_OUT] = true;
$opts[CURLOPT_WRITEFUNCTION] = $write_function;
$opts[CURLOPT_HTTPHEADER] = [
"User-Agent: " . CONFIG()->app_name . '/' . CONFIG()->version,
"Referer: " . $source
];
if (preg_match('/pixiv\.net/', $source)) {
$opts[CURLOPT_HTTPHEADER][] = "Referer: http://www.pixiv.net";
# Don't download the small version
if (preg_match('~(/img/.+?/.+?)_m.+$~', $source, $m)) {
$match = $m[1];
$source = str_replace($match . "_m", $match);
}
}
$ch = curl_init($source);
curl_setopt_array($ch, $opts);
$res = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
if ($timeout && $info['total_time'] === (float)$timeout) {
throw new Danbooru\Exception\RuntimeException("Request timed out");
} elseif ($info['redirect_url']) {
if ($info['redirect_count'] > $redirections_limit)
throw new Danbooru\Exception\RuntimeException("Too many redirects");
$source = $info['redirect_url'];
} elseif ($info['http_code'] == 200) {
if ($max_size) {
$len = $info['size_download'];
if ($len > $max_size)
throw new Danbooru\Exception\RuntimeException("File is too large ($len bytes)");
}
if (!$file)
throw new Danbooru\Exception\RuntimeException("Response is empty");
return $file;
} else {
throw new Danbooru\Exception\RuntimeException("HTTP error code: " . $info['http_code']);
}
}
}
}