<?php
$domain = strtolower($_GET['domain']);
$id = (int) $_GET['id'];
$additional = array();
$hash = $id;
$mode = isset($_GET['mode']) ? $_GET['mode'] : 'normal';
foreach ($_GET as $key => $value) {
if (!preg_match('|^add_([a-z0-9_-]+)$|i', strtolower($key), $a)) {
continue;
}
$additional[$a[1]] = $value;
$hash .= '&'.$a[1].'='.$value;
}
$current_hash = sha1($hash);
if (($id == 0) and (count($additional) == 0)) {
AscetCMSEngine::$http_status = 400;
echo 'domain or id is malformed';
return;
}
AscetCMSEngine::error_reporting(0);
/* */
abstract class aBooru {
var $ch;
var $status = -1;
var $image_url;
var $page_url;
const user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36';
function get_header_list($referer = null) {
if ($referer === null) {
$referer = 'http://'.$this->get_main_domain().'/';
}
return array(
'Cache-Control: max-age=0',
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'User-agent: '.self::user_agent,
'Referer: '.$referer,
'Accept-Language: ru,en;q=0.8',
);
}
function get_image($id, $additional) {
$url = $this->get_url($id, $additional);
$this->page_url = $url;
$this->ch = curl_init($url);
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($this->ch, CURLOPT_AUTOREFERER, true);
curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($this->ch, CURLOPT_HEADER, true);
curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, 20);
curl_setopt($this->ch, CURLOPT_TIMEOUT, 20);
curl_setopt($this->ch, CURLOPT_HTTPHEADER, $this->get_header_list());
$http_status = -1;
for ($try_count = 0; $try_count < 3; $try_count++) {
$raw_buf = curl_exec($this->ch);
list($header, $buf) = explode("\r\n\r\n", $raw_buf, 2);
if (curl_errno($this->ch) != 0) {
header('X-raw-page-'.$try_count.'-errno: '.curl_errno($this->ch));
continue;
}
$http_status = curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
header('X-raw-page-'.$try_count.'-http-status: '.$http_status);
if ($http_status == 200) {
// обрабатываем полученное
// $r = mt_rand(1, 1000000);
// file_put_contents('/dev/shm/care-'.$r.'.html', $buf, LOCK_EX);
// header('X-saved-raw-file-'.$r.': /dev/shm/care-'.$r.'.html');
$img_src = $this->parse_text_for_image($buf);
if ($img_src === null) {
sleep(10);
continue;
}
$this->image_url = $img_src;
break;
} elseif ($http_status == 403) {
sleep(10);
continue;
}
}
if (curl_errno($this->ch) != 0) {
$this->status = 1000 + curl_errno($this->ch);
return null;
}
if ($http_status != 200) {
$this->status = 3000 + $http_status;
return null;
}
/** @noinspection PhpUndefinedVariableInspection */
if ($img_src === null) {
$this->status = 1;
return null;
}
// Теперь получаем изображение
curl_setopt($this->ch, CURLOPT_URL, $this->image_url);
curl_setopt($this->ch, CURLOPT_HTTPHEADER, $this->get_header_list($this->page_url));
$buf = '';
for ($try_count = 0; $try_count < 3; $try_count++) {
$raw_buf = curl_exec($this->ch);
list($header, $buf) = explode("\r\n\r\n", $raw_buf, 2);
if (curl_errno($this->ch) != 0) {
header('X-image-'.$try_count.'-errno: '.curl_errno($this->ch));
continue;
}
$http_status = curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
header('X-image-'.$try_count.'-http-status: '.$http_status);
if ($http_status == 200) {
break;
} elseif ($http_status == 403) {
sleep(10);
continue;
}
}
if (curl_errno($this->ch) != 0) {
$this->status = 2000 + curl_errno($this->ch);
return null;
}
if ($http_status !== 200) {
$this->status = 4000 + $http_status;
return null;
}
$this->status = 0;
// Сохраняем thumb изображения
$content_type = curl_getinfo($this->ch, CURLINFO_CONTENT_TYPE);
header('X-content-type: '.$content_type);
$thumb_buf = '';
if (preg_match('|^image/|', $content_type)) {
$rnd = mt_rand(1, 10000000000);
switch (strtolower(preg_replace('|(;.*)?$|', '', $content_type))) {
case 'image/gif':
$extension = 'gif';
$additional = '-alpha on -coalesce';
break;
case 'image/png':
$extension = 'png';
$additional = '';
break;
default:
$extension = 'jpg';
$additional = '';
}
file_put_contents('/dev/shm/booru_tmp_'.$rnd.'.'.$extension, $buf, LOCK_EX);
system('convert /dev/shm/booru_tmp_'.$rnd.'.'.$extension.' '.
$additional.' -resize x300 /dev/shm/booru_tmp_'.$rnd.'.out.'.$extension);
$thumb_buf = file_get_contents('/dev/shm/booru_tmp_'.$rnd.'.out.'.$extension);
@unlink('/dev/shm/booru_tmp_'.$rnd.'.'.$extension);
@unlink('/dev/shm/booru_tmp_'.$rnd.'.out.'.$extension);
}
return (object) array(
'status' => 0,
'url' => $img_src,
'page_url' => $url,
'img' => $buf,
'thumb' => $thumb_buf,
'content_type' => $content_type,
);
}
abstract function parse_text_for_image($text);
abstract function get_url($id, $additional);
abstract function get_main_domain();
}
// Danbooru
class aBooru_danbooru extends aBooru {
function get_url($id, $additional) {
return 'http://danbooru.donmai.us/posts/'.$id;
}
function parse_text_for_image($text) {
if (preg_match('#http\\://danbooru\\.donmai\\.us/data/(.+?)\\.(jpg|bmp|png|gif|jpeg|webm)#', $text, $a)) {
return $a[0];
}
if (preg_match('#Size\\: +<a +href\\="/data/([a-f0-9]+)\\.(jpg|bmp|png|gif|jpeg|webm)"#', $text, $a)) {
return 'http://danbooru.donmai.us/data/'.$a[1].'.'.$a[2];
}
return null;
}
function get_main_domain() {
return 'danbooru.donmai.us';
}
}
// Gelbooru
class aBooru_gelbooru extends aBooru {
function get_url($id, $additional) {
// return 'http://gelbooru.com/index.php?page=post&s=view&id='.$id;
return 'http://gelbooru.com/index.php?page=dapi&s=post&q=index&id='.$id;
}
function parse_text_for_image($text) {
if (!preg_match('#file_url="(.+?)"#', $text, $a)) {
return null;
}
return $a[1];
}
function get_main_domain() {
return 'gelbooru.com';
}
}
// Safebooru
class aBooru_safebooru extends aBooru {
function get_url($id, $additional) {
return 'http://safebooru.org/index.php?page=post&s=view&id='.$id;
}
function parse_text_for_image($text) {
if (!preg_match('#http\\://(([0-9a-z]+?)\\.)?safebooru\\.org//images/(.+?)\\.'.
'(jpg|bmp|png|gif|jpeg|webm)#', $text, $a)
) {
return null;
}
return $a[0];
}
function get_main_domain() {
return 'safebooru.org';
}
}
// Deviantart
class aBooru_deviantart extends aBooru {
function get_url($id, $additional) {
return 'http://www.deviantart.com/art/a-'.$id;
}
function parse_text_for_image($text) {
if (!preg_match('#(name|property)\\="og\\:image" content="(https?\\://[^"]+?)"#', $text, $a)) {
return null;
}
return $a[2];
}
function get_main_domain() {
return 'www.deviantart.com';
}
}
// E621
class aBooru_e621 extends aBooru {
function get_url($id, $additional) {
return 'https://e621.net/post/show/'.$id.'/';
}
function parse_text_for_image($text) {
if (!preg_match('#(https?://static[0-9]+\\.e621\\.net\\/data\\/.+?.(jpg|bmp|png|gif|jpeg|))">Download<\\/a>#i',
$text, $a)
) {
return null;
}
return $a[1];
}
function get_main_domain() {
return 'e621.net';
}
}
//
class aBooru_derpibooru extends aBooru {
function get_url($id, $additional) {
return 'https://derpiboo.ru/'.$id;
}
function parse_text_for_image($text) {
if (!preg_match('#data\\-download\\-uri\\="(https?\\:)?\\/\\/(derpicdn\\.net\\/.+?\\.(jpg|bmp|png|gif|jpeg|webm))"#i',
$text, $a)
) {
return null;
}
return 'https://'.$a[2];
}
function get_main_domain() {
return 'derpiboo.ru';
}
}
//
class aBooru_tumblr extends aBooru {
function get_url($id, $additional) {
return 'http://'.($additional['username']).'.tumblr.com/image/'.$id;
}
function parse_text_for_image($text) {
if (!preg_match('#data-src="(https?:\\/\\/[0-9]+.media.tumblr.com/.+?\\.(jpg|bmp|png|gif|jpeg|webm))"#i', $text, $a)
) {
return null;
}
return $a[1];
}
function get_main_domain() {
return 'tumblr.com';
}
}
//
class aBooru_konachancom extends aBooru {
function get_url($id, $additional) {
return 'http://konachan.com/post/show/'.$id;
}
function parse_text_for_image($text) {
if (!preg_match('#content\\="(http\\:\\/\\/konachan\\.com\\/.+?\\.(jpg|bmp|png|gif|jpeg|webm))" +property\\="og\\:image"#i',
$text, $a)
) {
return null;
}
return $a[1];
}
function get_main_domain() {
return 'konachan.com';
}
}
//
class aBooru_pixiv extends aBooru {
function get_url($id, $additional) {
return 'http://www.pixiv.net/member_illust.php?mode=medium&illust_id='.$id;
}
function parse_text_for_image($text) {
if (preg_match('|"(https?://[a-z0-9.-]*?pixiv\\.net/img\\-original/.+?)"|', $text, $a)) {
return $a[1];
}
preg_match_all('|"(https?://[a-z0-9.-]*?pixiv\\.net/c/([0-9]+)x[0-9]+/img\\-master/img/.+?)"|',
$text, $a, PREG_SET_ORDER);
$url = null;
$max = 0;
foreach ($a as $set) {
if ($set[2] > $max) {
$max = (int) $set[2];
$url = $set[1];
}
}
return $url;
}
function get_main_domain() {
return 'pixiv.com';
}
function get_header_list() {
$r = parent::get_header_list();
$r[] = 'Cookie: PHPSESSID=10566162_9e6e80b6f3ba259832c056d813c56dc2; ';
return $r;
}
}
//
class aBooru_animepicturesnet extends aBooru {
function get_url($id, $additional) {
return 'https://anime-pictures.net/pictures/view_post/'.$id;
}
function parse_text_for_image($text) {
if (!preg_match('#"/pictures/download_image/(.+\\.(jpg|bmp|png|gif|jpeg|webm))?"#i',
$text, $a)
) {
return null;
}
return 'https://anime-pictures.net/pictures/download_image/'.$a[1];
}
function get_main_domain() {
return 'anime-pictures.net';
}
}
// Yandere
class aBooru_yandere extends aBooru {
function get_url($id, $additional) {
return 'https://yande.re/post/show/'.$id;
}
function parse_text_for_image($text) {
if (!preg_match('#files.yande.re/(image/.+?)"#i',
$text, $a)
) {
return null;
}
return 'https://files.yande.re/'.$a[1];
}
function get_main_domain() {
return 'yande.re';
}
}
// Sankakucomples
class aBooru_sankakucomplex extends aBooru {
function get_url($id, $additional) {
return 'https://chan.sankakucomplex.com/post/show/'.$id;
}
function parse_text_for_image($text) {
if (!preg_match('#cs\\.sankakucomplex\\.com\\/data\\/(.+?)(\\?[0-9]*)?"#i', $text, $a)) {
return null;
}
return 'https://cs.sankakucomplex.com/data/'.$a[1].$a[2];
}
function get_main_domain() {
return 'chan.sankakucomplex.com';
}
}
/* */
$classname = 'aBooru_'.$domain;
if (!class_exists($classname)) {
AscetCMSEngine::$http_status = 400;
echo 'domain not found';
return;
}
$folder = '/dev/shm';
$storage = new KeyValueStorageFile((object) array(
'folder' => $folder,
'prefix' => 'booru_pic_'
));
$image_value_key = 'pic_'.$domain.'_'.$current_hash;//Название ключа этого изображения
// Создаём мьютекс
$mutex_get = new SmartMutex('get_booru_'.$image_value_key);
if (!$mutex_get->get_lock(-1)) {
AscetCMSEngine::$http_status = 503;
echo 'Wtf? Can not acq lock';
return;
}
// Получаем значение кеша
$value = $storage->get_value_full($image_value_key);
if ($value === null) {
$mutex = new SmartMutex('booru_get_'.$domain);
if (!$mutex->get_lock(-1)) {
AscetCMSEngine::$http_status = 503;
echo 'Wtf? Can not acq lock';
return;
}
$inst = new $classname();
unset($mutex, $classname);
$a = $inst->get_image($id, $additional);
if ($a === null) {
$this->http_status = 503;
echo 'Can not get image. Status: '.$inst->status.'; image url: '.$inst->image_url.'; page url: '.$inst->page_url;
return;
}
$hash = sha1($a->img);
$value = (object) array(
'value' => (object) array(
'hash' => $hash,
'page_url' => $a->page_url,
'img_url' => $a->url,
'get_create' => time(),//Хотя эта инфа есть в контейнере
'get_last_time' => time(),
'get_ip' => array($_SERVER['REMOTE_ADDR']),
'get_count' => 1,
'img' => $a->img,
'thumb' => $a->thumb,
'content_type' => $a->content_type
));
AscetCMSEngine::$header_time_last_modified = time();
AscetCMSEngine::$header_time_expires = (time() + 31 * 24 * 3600);
unset($a);
} else {
AscetCMSEngine::$header_time_last_modified = $value->time_create;
AscetCMSEngine::$header_time_expires = $value->time_create + 31 * 24 * 3600;
$value->value->get_last_time = time();
$value->value->get_ip[] = $_SERVER['REMOTE_ADDR'];
$value->value->get_ip = array_unique($value->value->get_ip);
$value->value->get_count++;
}
$storage->set_value($image_value_key, $value->value, 31 * 24 * 3600);
unset($mutex_get);
header('Access-Control-Allow-Origin: *');
if ($mode == 'mime') {
$sad_contype = 'application/javascript;';
echo json_encode(array(
'status' => 0,
'content_type' => $value->value->content_type
));
} else {
$sad_contype = $value->value->content_type;
if (($mode == 'thumb') and preg_match('|^image/|', $value->value->content_type)) {
AscetCMSEngine::$etag_hash = $value->value->hash.'-thumb';
echo $value->value->thumb;
} else {
AscetCMSEngine::$etag_hash = $value->value->hash;
echo $value->value->img;
}
}
?>
Comments