$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\\: +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; } } ?>