kinopoisk.ru and other downloader

Download from kinopoisk.ru, filmz.ru, celeber.ru and some theme of tumblr.com.

当前为 2016-07-22 提交的版本,查看 最新版本

// ==UserScript==
// @name        kinopoisk.ru and other downloader
// @name:ru     Получение ссылок на изображения с kinopoisk.ru и других сайтов
// @namespace   kinopoisk_and_other
// @description Download from kinopoisk.ru, filmz.ru, celeber.ru and some theme of tumblr.com.
// @description:ru Получает ссылки на изображения на сайтах: kinopoisk.ru, filmz.ru, celeber.ru и некоторых темах tumblr.com.
// @author      Heinrich Schweinsteiger
// @include     htts://www.kinopoisk.ru/*/posters/
// @include     htt*://www.kinopoisk.ru/*/fanart/
// @include     htt*://www.kinopoisk.ru/*/stills/
// @include     htt*://www.kinopoisk.ru/*/shooting/
// @include     htt*://www.kinopoisk.ru/*/promo/
// @include     htt*://www.kinopoisk.ru/*/concept/
// @include     htt*://www.kinopoisk.ru/*/covers/
// @include     http://www.filmz.ru/photos/*
// @include     http://www.celeber.ru/browse/*
// @include     http://www.celeber.ru/photo/*
// @include     htt*.tumblr.com/*
// @exclude     htt*.tumblr.com*iframe*
// @exclude     htt*.tumblr.com*analytics.html*
// @exclude     htt*.tumblr.com*yahoo_cookie_receiver.html*
// @version     0.0.1
// @license GPL
// @grant       GM_xmlhttpRequest
// @run-at	document-end
// ==/UserScript==

var DEBUG_MODE = true;

function DebugLog(text)
{
	if (DEBUG_MODE)
	{
		console.log(text);
	}
}

var baseRipper = {
	isChrome : /chrome/i.test(navigator.userAgent),
	isFireFox : /firefox/i.test(navigator.userAgent),
	abortLinkGrabbing: false,	// flag to abort link grabbing

	pages : {
		//recurse var used for thumbnail pages mainly. if set to 0 and button
		//clicked on single page it doesn't really do anything useful.
		recurse: true,     // recuse into lower gallery pages
		current: 0,        // current counter reused for image and gallery parsing
		totalImages: 0,		// total counter used for image parsing
		URLs: [],          // ссылки для скачивания изображений, создаем из экзмепляров URLTemplate holder for url html list
		//1 содержит galleryIndex, 2 ссылку
        URLTemplate: function (url, decription) {
            this.URL = url;
            this.Decription	= decription;
        },
		toParse: [],       // список ссылок на страницы из которых надо выудить ссылки на скачивание list of urls of single image pages that need to be parsed for DDL
		//toParseSecond: [],
		//textbox: null,     // textbox holder
		fetchStatus: 0     // status id for script checking status:
							// 0 = not started
							// 1 = getting indexes
							// 2 = getting image DDL
							// 3 = finished everything
							// 4 = displayed urls (finished or aborted)
        /*fetchStatus : {
            NotStarted: 0,
            GettingIndexes: 1,
            GettingImageDDL: 2,
        }*/
	},
	//добавление в HandleOnClick
	//удаление в checkers.NextGallery
	GalleryPages: [], // массив ссылкок на страницы с эскизами, list of urls to thumbnail pages needed to fetch
	GalleryData: {},// holds thumbnail image target info (GalleryTemplate)
	GalleryTemplate: function () {
		this.isFetched 	= false;	// if page was fetched set during ScanFirstLevel
		this.Failed		= null;		// flag if page failed to find a image link
		this.error		= '';		// error value to show on list
		this.url 		= null;		// url of image page set during ScanGallery
		this.id 		= null;		// id of image set during ScanFirstLevel
		this.ddl		= null;		// ddl link to image file set by ScanFirstLevel
		this.title		= null;		// title of the image for failure display
		this.xhttp		= null;		// xHttpRequest result holder
	},
	
	URLbox: document.createElement('div'),
	//tableFailed: document.createElement('table'),
    tableFailed: document.createElement('div'),

	httpCounter: {
		MAXREQ:  4, //количество потоков скачки
		runCon:  0, //running connections
		interval: null //хранит ссылку на функцию интервала, которая по времени запускает переданную функцию
	}, // end httpCounter
	
	sleepTime : 2000, //сколько времени спать при получение ошибки 503. The server is currently unavailable
	
	levelForURLScaning : 2, //уровень с которого будем получать ссылки, если стоит 2 значит будет запускаться ScanSecondLevel()
	
	_this : undefined,
	
    /*
	 * init()
	 * 
	 * Called as first function execution upon script load.
	 * Sets up the xmlHttpRequest helpers and generates click button.
	 */
	init : function () {
		DebugLog('Call: init()');
		
		DebugLog("init() isChrome: " + this.isChrome + ", isFireFox: " + this.isFireFox);
		//if (pages.isChrome) pages.Get_URL_CB = GM_Get_URL_CB;
		//if (baseRipper.isFireFox === true) { baseRipper.Get_URL_CB = baseRipper.GM_Get_URL_CB; }
        
        _this = this;

		this.btn.btnID = this.btn.GenerateButton(this);
	},

	btn: {			// button holder
		btnID : null,
		// creates the click button for our page
		GenerateButton : function (base) {
			DebugLog('GenerateButton()');
			var new_button;
			var btnLoc;
            
            //debugger;
            //base.tableFailed.innerHTML = '<table width="97%"><tr><td>http://media.filmz.ru/photos/full/filmz.ru_f_226002.jpg Not Loaded</td></tr></table>';
            //base.tableFailed.style.background = "red";
			base.tableFailed.style.display = 'none';
			document.body.insertBefore(base.tableFailed, document.body.firstChild);
            
            /*base.URLbox.style.overflow = "auto";
            //base.URLbox.style.overflow = "visible";
			base.URLbox.style.height = "100px";
			base.URLbox.style.width = "97%";
            //base.URLbox.style.zIndex = 1;
            base.URLbox.style.background = "white";
            base.URLbox.innerHTML = '<table width="97%"><tr><td><a title="Марго Робби Title" href="http://media.filmz.ru/photos/full/filmz.ru_f_226002.jpg">Марго Робби</a></td></tr></table>';
            //urlLoc = document.querySelector('#top');
            //document.body.insertBefore(base.URLbox, urlLoc);*/
            
			base.URLbox.style.display = 'none';
			document.body.insertBefore(base.URLbox, document.body.firstChild);

			new_button = document.createElement('input');
			new_button.type = 'button';
			new_button.value = 'Get URLs for Gallery';
			new_button.setAttribute('onsubmit', 'return false;');
			//new_button.addEventListener('click', this.btn.debugToggleCheck, false);
			
			/*
			 * use individual selector OR's to get target by preference instead of first
			 * dom object availability
			 *
			 * alternate: btnLoc = document.querySelector('#gmi-ResViewContainer, #gmi-GalleryEditor, #output');
			 */
			btnLoc = base.parsers.GetButtonLocation();
			
			if (btnLoc) {
				btnLoc.insertBefore(new_button, btnLoc.firstChild);
				new_button.addEventListener('click', base.HandleOnClick, false);
			}
			else {
				new_button.value = 'Root Thumbnail Page?';
				document.body.insertBefore(new_button, document.body.firstChild);
			}
			
			// Disable button on base domain if using chrome due to same origin complications
			/* DA seems to have changed server settings to fix same origin
			 * issues from www.deviantart.com and other subdomains commented
			 * for testing. will re-enable if problems show up.
			 * actually seems to have been Chrome whose behavior changed. If script is loaded
			 * as an extension it is allowed to violate same origin rules. If pasted into the
			 * developer console it errors out same origin failures.
			 if (document.location.hostname === 'www.deviantart.com' && pages.isChrome === true) {
				new_button.value = 'Script will fail on root www.deviantart.com';
				new_button.disabled = true;
			}
			*/
			DebugLog('GenerateButton(): Created Button:');
			DebugLog(new_button);
			return new_button;
		}, // end GenerateButton
	}, // end btn
    
	 /*Основной цикл сбора ссылок, запускается по нажатию на кнопку
	 * 
	 * onclick function triggered when the
	 * button we injected is clicked to get
	 * our direct links.
	 */
	HandleOnClick : function (eventID) {
		var galleryLink = document;
		var a_gallery; //страницы со ссылками найденные на странице
        DebugLog('HandleOnClick()');
		
        _this.btn.btnID.removeEventListener('click', _this.HandleOnClick, false);
		_this.btn.btnID.addEventListener('click', _this.AbortLinkChecking, false);
		if (_this.checkers.isThumbnailGallery(galleryLink)) {
			galleryLink = document.location.href;
		}
		else {
			DebugLog('HandleOnClick(): Current page is not a gallery.');
			/*DebugLog('HandleOnClick(): Current page is not a gallery trying to find it.');
			galleryLink = this.parsers.GetLinkOnNextGalleryPage();
			DebugLog(galleryLink);*/
		}
		_this.GalleryPages.push(galleryLink);
		DebugLog("HandleOnClick(): Gallery link found: " + _this.GalleryPages);
		_this.fetchStatus = 1;
		//запускаем получение ссылок со страниц галерей
		_this.httpCounter.interval = setInterval(_this.intervalFunc.LoadGalleries, 50);
	}, // end HandleOnClick
	
	// button click abort function
	AbortLinkChecking : function (eventID)
	{
		_this.abortLinkGrabbing = true;
		DebugLog('AbortLinkChecking()');
		_this.btn.btnID.removeEventListener('click', _this.AbortLinkChecking, false);
		_this.btn.btnID.value = 'Aborted: ' + _this.btn.btnID.value;
		DebugLog('FetchStatus: ' + _this.pages.fetchStatus);
		if (_this.pages.fetchStatus > 1 ||  _this.pages.URLs.length > 0)
			_this.DoneDisplayUrlList();
		else
			DebugLog('AbortLinkChecking(): Nothing to show.');

		_this.GalleryPages = [];
		_this.pages.toParse = [];
	}, // end AbortLinkChecking
	
	//функции которые запускаются в setInterval
	intervalFunc : {
		// heartbeat while loading galleries (страница с несколькими изображениями)
		LoadGalleries : function () {
			if ((_this.httpCounter.runCon < _this.httpCounter.MAXREQ) && (_this.GalleryPages.length)) {
				DebugLog("LoadGalleries():" + 
					' GalleryPages.length=' + _this.GalleryPages.length +
					', running connections: (' + _this.httpCounter.runCon + ')' +
					', max running (' + _this.httpCounter.MAXREQ + ')');
				DebugLog('Получение ссылок на изображения с загруженного списка галерей');
				
				//скачка галерей
				_this.checkers.NextGallery();
			}
            
			//все галлереи загружены, запускаем скачку изображений
			if ((_this.GalleryPages.length === 0) && (_this.httpCounter.runCon === 0)) 
			{
				DebugLog('LoadGalleries(): все галлереи загружены, запускаем скачку изображений');
				//Останавливаем таймер pages.xmlHttp_Counter.interval = LoadGalleries
				DebugLog('LoadGalleries(): Stopping heartbeat out of galleries to check.');
				clearInterval(_this.httpCounter.interval);
				_this.btn.btnID.value = 'Finished loading galleries (' + _this.pages.current + ')';
				_this.pages.current = 0;
				_this.pages.fetchStatus = 2;
                if (_this.levelForURLScaning !== 0)
                    _this.httpCounter.interval = setInterval(_this.intervalFunc.LoadImages, 50);
                else {
                    _this.DoneDisplayUrlList(); 
                    _this.pages.fetchStatus = 3;
                }
			}
		}, // end LoadGalleries

		// оканчивается когда pages.toParse = 0
		// heartbeat while loading images
		LoadImages : function () {
			if ((_this.httpCounter.runCon < _this.httpCounter.MAXREQ) && (_this.pages.toParse.length)) {
				DebugLog("LoadImages(): " + 
					'running connections: (' + _this.httpCounter.runCon + ') ' +
					'max running (' + _this.httpCounter.MAXREQ + ')');
				
				//скачка изображений
				_this.checkers.NextImage();
			}
			
			if ((_this.pages.toParse.length === 0) && (_this.httpCounter.runCon === 0)) {
				DebugLog('LoadImages():Stopping heartbeat out of images to load.');
				_this.DoneDisplayUrlList(); 
				_this.pages.fetchStatus = 3;
				clearInterval(_this.httpCounter.interval);
			}
		
			/*if ((baseRipper.pages.toParse.length == 0) && (baseRipper.httpCounter.runCon == 0)) 
			{
				DebugLog('загружены основные изображения, запускаем закачку больших');
				clearInterval(baseRipper.httpCounter.interval);
				baseRipper.pages.current = 0;
				baseRipper.pages.fetchStatus = 2;
				baseRipper.httpCounter.interval = setInterval(baseRipper.intervalFunc.LoadImagesSecond, 50);
			}*/
		} // end LoadImages
		
		// heartbeat while loading images
		/*LoadImagesSecond : function () {
			if ((baseRipper.httpCounter.runCon < baseRipper.httpCounter.MAXREQ) && (baseRipper.pages.toParseSecond.length)) {
				DebugLog("HeartBeat LoadImagesSecond()\n" + 
					'running connections: (' + baseRipper.httpCounter.runCon + ') ' +
					'max running (' + baseRipper.httpCounter.MAXREQ + ')');
				
				//скачка изображений
				baseRipper.checkers.NextImageS();
			}
			
			if ((baseRipper.pages.toParseSecond.length == 0) && (baseRipper.httpCounter.runCon == 0)) {
				DebugLog('Stopping heartbeat out of images to load.');
				baseRipper.pages.fetchStatus = 3;
				clearInterval(baseRipper.httpCounter.interval);
			}
		} // end LoadImages*/
	}, // end intervalFunc


	checkers : {
		// checkers.isThumbnailGallery (doc)
		// return true if page seems to be a gallery
		// or false if it looks like its a single image page
		// detection is looking for the comments by the artist
		// usually found on the single image page
		isThumbnailGallery : function (docbase) {
			var rtnval;
			//DebugLog('Call: isThumbnailGallery()');
            var container = _this.parsers.FindThumbnailContainer(docbase);
            DebugLog('isThumbnailGallery() container = ' + rtnval);
			rtnval = (container) ? true : false;
			DebugLog('isThumbnailGallery(): ' + rtnval);
			return rtnval;
		}, // end isThumbnailGallery

		// скачка сраниц из GalleryPages и запуск для скаченных ScanGallery()
		// get our next gallery page from our stack
		NextGallery : function () {
			var link_info;
			DebugLog('NextGallery()');
 			if (_this.checkers.isAborted()) return;
			if (_this.GalleryPages.length) 
			{
				link_info = _this.GalleryPages.shift(); //Метод shift() удаляет и возвращает первый элемент массива
				_this.Get_URL_CB(link_info, _this.callbacks.ScanGallery, _this.GalleryPages.length);
			}
		}, // end NextGallery

		// уменьшает pages.toParse
		// get the next image page from our stack
		NextImage : function () {
			var link_info;
			DebugLog('NextImage()');
			if (_this.checkers.isAborted()) return;
			if (_this.pages.toParse) {
				// pull image page url and index off the stack
				// index 0 is the page #, index 1 is the url
				link_info = _this.pages.toParse.shift();
                if(link_info[1] === "")
                    throw new Error('Пустая ссылка!'); 
				DebugLog('NextImage(): Start download image and (ScanFirstLevel()) on link: ' + link_info);
				_this.Get_URL_CB(link_info[1], _this.callbacks.ScanFirstLevel, link_info[0]);
			}
		}, // end NextImage

		// function checkers.isAborted ()
		// check if we clicked the button to abort script
		// if we did it requires a page reload to start again
		isAborted : function () {
			if (_this.abortLinkGrabbing) {
				//DebugLog('checkers.isAborted(): ' + _this.abortLinkGrabbing);
				return true;
			}
			return false;
		} // end isAborted
	}, // end checkers
    
    RemoveInvalidSymbols : function (string) {
        return string.replace(/^\s+|\s+$/g, "");
    },
	
	callbacks :	{
		/* 	Обработка страницы галереи скаченной Get_URL_CB.
			Запускается GetLinks-LoadGalleries
			function callback_ScanPages(docbase)
			called when gallery page html is loaded so we can parse images out and set next page
		 */
		ScanGallery : function (docbase, GalleryURL) {
			//galleryIndex = GalleryURL будет пустым
			DebugLog('ScanGallery(' + GalleryURL + ')');
			DebugLog('Получение ссылок на иконки с галереи по адресу: ' + GalleryURL);
			_this.pages.current += 1;
			DebugLog('ScanGallery(): pages.current=' + _this.pages.current);
			_this.btn.btnID.value = 'Loading gallery page ' + _this.pages.current;
			_this.parsers.GetLinksOnThumbsOnGalleryPage(docbase);
			if (_this.pages.recurse === true) {
				nextPage = _this.parsers.GetNextGalleryPageLink(docbase);
				if (nextPage) 
					_this.GalleryPages.push(nextPage);
			}
		}, // end ScanGallery
        
		// callback from Get_URL_CB
		// Из скаченной страницы получение ссылки на большой файл.
		// Функция остановится когда pages.current == pages.totalImages
		// callback routine when getting an image page to parse out the DDL link.
		ScanFirstLevel : function (docbase, galleryIndex) {
			//DebugLog('ScanFirstLevel(baseURI=' + docbase.baseURI + ', galleryIndex=' + galleryIndex + ')');
			DebugLog('ScanFirstLevel(galleryIndex=' + galleryIndex + ')');
			//DebugLog("docbase code: \n" + docbase.innerHTML);
			var pageWithBigImageUrl;
			var smallImageUrl;
			//var title;
            var desc;
			//var ImageID;
			
			_this.pages.current += 1;
			_this.btn.btnID.value = 'Loading image page ' + _this.pages.current + ' of ' + _this.pages.totalImages;
			DebugLog('ScanFirstLevel(): Loading image page ' + _this.pages.current + ' of ' + _this.pages.totalImages);

			/*ImageID = docbase.querySelector('a.image-holder img');
			if (!ImageID) { 
				ImageID = 'FailedID-' + this.GalleryData[galleryIndex].url.split('/').pop(); 
			}
			else { 
				ImageID = ImageID.getAttribute('src'); 
			}
			DebugLog('ImageID: ' + ImageID);

			this.GalleryData[galleryIndex].id = ImageID;
			this.GalleryData[galleryIndex].isFetched = true;*/
           
            if(_this.parsers.GetDescription) {
                desc = _this.parsers.GetDescription(docbase);
            }
            
            if(desc) {
                DebugLog('ScanFirstLevel(): Description: ' + desc);
            }
            else {
                var title = docbase.querySelector('title');
                if (title) { 
                    desc = title.text; 
                }
            }
            
            desc = _this.RemoveInvalidSymbols(desc);
            //desc = desc.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, '');
            _this.GalleryData[galleryIndex].title = desc;
			//_this.GalleryData[galleryIndex].title = title || ImageID;
			
			if (_this.GalleryData[galleryIndex].error !== '') 
			{
				if (_this.pages.current === _this.pages.totalImages) 
				{ 
					DebugLog('pages.current = pages.totalImages, return');
					_this.DoneDisplayUrlList(); 
				}
				return;
			}
			
            //грузим большую картинку
			pageWithBigImageUrl = _this.parsers.GetUrlOnFirstLevelPage(docbase);

			if (pageWithBigImageUrl) {
				DebugLog('ScanFirstLevel(): Found url on page with big image: ' + pageWithBigImageUrl);
				
				if(_this.levelForURLScaning === 2) {
					_this.GalleryData[galleryIndex].ddl = pageWithBigImageUrl;
					_this.Get_URL_CB(pageWithBigImageUrl, _this.callbacks.ScanSecondLevel, galleryIndex);
				}
				else {
					_this.pages.URLs.push(new _this.pages.URLTemplate(pageWithBigImageUrl, desc));
				}
			}
			else {
				// если нет увеличенной версии.
				DebugLog('ScanFirstLevel(): Failed found url to page with big image');
				//if (_this.levelForURLScaning === 2)
				{
					smallImageUrl = _this.parsers.GetSmallImageUrlOnFirstLevelPage(docbase);
					if (smallImageUrl) {
						DebugLog('ScanFirstLevel(): Found download url for small image: ' + smallImageUrl);
						_this.GalleryData[galleryIndex].ddl = smallImageUrl;
						_this.pages.URLs.push(new _this.pages.URLTemplate(smallImageUrl, desc));
					} else {
						DebugLog('ScanFirstLevel(): Failed found small image');
						
						// no image found, probably a text page for a poem or something.
						_this.GalleryData[galleryIndex].error = 'No download or large image found.';
						
						// check if we're done loading since the throw below will prevent a
						if (_this.pages.current === _this.pages.totalImages) { 
							_this.DoneDisplayUrlList(); 
						}
						return false;
						//throw this.GalleryData[galleryIndex].error + ' (' + this.GalleryData[galleryIndex].url + ')';
						
					}
				}
			}
			
			_this.GalleryData[galleryIndex].Failed = false;
			//if (this.pages.current == this.pages.totalImages) { 
			//	this.DoneDisplayUrlList(); 
			//}
		}, // end ScanFirstLevel
		
		ScanSecondLevel : function (docbase, galleryIndex) {
			var bigImageUrl;
			DebugLog('Call: ScanSecondLevel( docbase=' + docbase + ', galleryIndex=' + galleryIndex + ')');
			bigImageUrl = _this.parsers.GetSmallImageUrlOnFirstLevelPage(docbase);
			if (bigImageUrl) {
					DebugLog('ScanSecondLevel(): Found download url for big image: ' + bigImageUrl);
					_this.GalleryData[galleryIndex].ddl = bigImageUrl;
					_this.pages.URLs.push(new _this.pages.URLTemplate(bigImageUrl, null));
			}
			else
				DebugLog('ScanSecondLevel(): Failed found big image');
		}, // end ScanSecondLevel
	}, // end callbacks
	
	parsers : {
		GetButtonLocation : function () 
        {
            throw new Error("Функция не реализована");
        },
		
		/*GetLinkOnNextGalleryPage : function ()
		{
			var a_gallery = document.querySelector('div.navigator ul.list li.arr a');
			if (a_gallery) { 
				return a_gallery.href; 
			}
			else{ 
				throw 'Error finding upper gallery'; 
			}
		}, // end GetLinkOnNextGalleryPage*/
		
		FindThumbnailContainer : function (docbase) {
			return docbase.querySelector('div.block_left');
		}, // end FindThumbnailContainer
		
		/* 	возврашет ссылку на следующую страницу галлереи
			GetNextGalleryPageLink(docbase)
			requires docbase: DOM Object
			returns string of url for next page
		 */	
		GetNextGalleryPageLink : function (docbase) {
            //throw new Error("Функция не реализована");
			DebugLog('Заглушка GetNextGalleryPageLink() всегда возврашет что нет следующих страниц галлерей');
			return false;
		}, // end GetNextGalleryPageLink
        
        FindLinksInThumbnailContainer : function (docbase) {
			var links = docbase.querySelectorAll('table.fotos tr td b a');
            return links;
            /*urls = [];

            for (i = 0; i < links.length; i += 1) 
            {
                var href = links[i].getAttribute('href');
                urls.push(href);
            }
			return urls;*/
		}, // end FindLinksInThumbnailContainer
        
        GetRefFromLinksInThumbnailContainer : function (obj) {
            return obj.getAttribute('href');
        }, // end GetRefFromLinksInThumbnailContainer

		/* 	GetLinksOnThumbsOnGalleryPage(docbase)
			Заполняет GalleryData ссылками на эскизы.
			requires docbase: DOM Object to scan
		 */
		GetLinksOnThumbsOnGalleryPage : function (docbase) 
		{
			DebugLog('Call: GetLinksOnThumbsOnGalleryPage(' + docbase.baseURI + ')');
			var thumb_links;
			var thumb_count;
			var newdocbase;
			var galleryIndex;

			// look for thumbnail container
			DebugLog('GetLinksOnThumbsOnGalleryPage(): Searching for thumbnail container on: ' + docbase.baseURI);
			newdocbase = this.FindThumbnailContainer(docbase);
			if (newdocbase) {
				//Находим ссылки на эскизы в найденном контейнере.
                thumb_links = this.FindLinksInThumbnailContainer(newdocbase);
			}
			else {
				//throw 'Error finding thumbnail window.';
				//не удалось скачать следующую страницу
				DebugLog('GetLinksOnThumbsOnGalleryPage(): Error finding thumbnail window.');
			}
			
			if (!thumb_links) {
				// no thumbnails found so stop searching pages
				// this happens if you scan browse pages and it runs over the 1000 image limit
				if (_this.parsers.FindNoResultsContainer(docbase)) {
					_this.pages.recurse = false;
				}
				return false;
			}
			
			DebugLog('GetLinksOnThumbsOnGalleryPage(): Found ' + thumb_links.length + ' link on thumbs');
			thumb_count = thumb_links.length;
			for (image_counter = 0; image_counter < thumb_count; image_counter += 1) 
            {
                var href = this.GetRefFromLinksInThumbnailContainer(thumb_links[image_counter]);
                DebugLog('GetLinksOnThumbsOnGalleryPage(): image_counter=' + image_counter + '; ' +
                    'thumb_count=' + thumb_count + '; ' + href);
                if (href)
                {
                    if (_this.levelForURLScaning === 0) {
                        var desc;
                        if(_this.parsers.GetDescription) {
                            desc = _this.parsers.GetDescription(thumb_links[image_counter]);
                            if (desc)
                                desc =  _this.RemoveInvalidSymbols(desc);
                        }
                        _this.pages.URLs.push(new _this.pages.URLTemplate(href, desc));
                    }
                    else {
                        _this.pages.totalImages += 1;
                        galleryIndex = _this.pages.totalImages;

                        DebugLog('GetLinksOnThumbsOnGalleryPage(): Push parse: ' + galleryIndex + ' url=' + href);
                        _this.pages.toParse.push([galleryIndex, href]);
                        _this.GalleryData[galleryIndex] = new _this.GalleryTemplate();
                        _this.GalleryData[galleryIndex].url = href;
                        //_this.GalleryData[galleryIndex].ImageID = 'NotLoaded-' + _this.GalleryData[galleryIndex].url.split('/').pop();
                        //_this.GalleryData[galleryIndex].title = _this.GalleryData[galleryIndex].ImageID;
                        _this.GalleryData[galleryIndex].title = 'NotLoaded-' + _this.GalleryData[galleryIndex].url.split('/').pop();
                        _this.GalleryData[galleryIndex].Failed = true;
                        // DebugLog(pages.GalleryData[galleryIndex]);
                    }
                }
                else
                    DebugLog('GetLinksOnThumbsOnGalleryPage(): href = null');
			}
            return true;
			//DebugLog(this.pages);
		}, // end GetLinksOnThumbsOnGalleryPage
		
		FindNoResultsContainer : function (docbase)
		{
			return docbase.querySelector('div.browse-no-results');
		}, // end FindNoResultsContainer
		
		GetUrlOnFirstLevelPage : function (docbase)
		{
			//DebugLog('GetUrlOnFirstLevelPage()');
			var dlbutton = docbase.querySelector('b.enlarge_3 a');
			if (dlbutton) {
				//DebugLog('dlbutton=' + dlbutton);
				var src = dlbutton.href;
				if (src === undefined) 
					DebugLog('GetUrlOnFirstLevelPage(): dlbutton.href = undefined, dlbutton: ' + dlbutton);
				return src;
			}
			//DebugLog('GetUrlOnFirstLevelPage(): return false');
			return false;
		}, // end GetUrlOnFirstLevelPage
		
		// если нет увеличенной версии.
		GetSmallImageUrlOnFirstLevelPage : function (docbase)
		{
            //debugger;
			var image = docbase.querySelector('img#image');
			if (image) {
				//var src = image.src;
                var src = image.getAttribute('src');
				if (src === undefined) 
					DebugLog('GetSmallImageUrlOnFirstLevelPage(): image.src = undefined, image: ' + image);
               if (src.lastIndexOf('//', 0) === 0)
					src = 'https:' + src;
				return src;
			}
			return false;
		}, // end GetSmallImageUrlOnFirstLevelPage
				
	}, // end parsers
	
	DoneDisplayUrlList : function () {
		DebugLog('Call: DoneDisplayUrlList()');
		if (_this.pages.fetchStatus > 3) return;
		var urlList;
		urlList = _this.URLbox;
        
        /*urlList.rows = 15;
		urlList.style.width = '100%';
		urlList.innerHTML = _this.pages.URLs.join('\r\n');*/
		var table = '<table width="97%">';
		//_this.pages.URLs.forEach(function(item, i, URLs) {
		//	table += '<tr><td><a title="Title" href="' + item.URL + '">' + item.Decription ? item.Decription : '' + '</a></td></tr>';
		//});
        for(var i = 0; i < _this.pages.URLs.length; i++){
            table += '<tr><td><a title="Title" href="' + _this.pages.URLs[i].URL + '">';
            table += _this.pages.URLs[i].Decription ? _this.pages.URLs[i].Decription : _this.pages.URLs[i].URL;
            table += '</a></td></tr>';
        }
		table += '</table>';
        urlList.innerHTML = table;
        urlList.style.overflow = "auto";
        //urlList.style.overflow = "visible";
		urlList.style.height = "100px";
		urlList.style.width = "97%";
        //base.URLbox.style.zIndex = 1;
        urlList.style.background = "white";
		urlList.style.display = '';
		_this.pages.fetchStatus = 4;
        // когда галереи не скачиваются levelForURLScaning = 0, totalImages = 0
		if (_this.pages.totalImages !== _this.pages.URLs.length && _this.levelForURLScaning !== 0) {
			_this.btn.btnID.value = 'Some pages failed to find links (found ' + _this.pages.URLs.length + ' of ' + _this.pages.totalImages + ')';
			_this.ShowFailedUrlList();
		}
		else {
			_this.btn.btnID.value = 'Displaying (found ' + _this.pages.URLs.length + ' of ' + _this.pages.totalImages + ')';
		}
	}, // end DoneDisplayUrlList
	
	ShowFailedUrlList : function () {
		DebugLog('Call: ShowFailedUrlList()');
		var counter;
		var failedURLs;
		var tableFailed, tableInner;
        
		tableFailed = _this.tableFailed;
        tableFailed.style.overflow = "auto";
        tableFailed.style.height = "100px";
		//tableFailed.width = '100%';
        tableFailed.style.width = "97%";
		//tableFailed.border = '2 px';
        tableFailed.style.border = '2px double black';
		tableFailed.style.backgroundColor= 'white';
        //tableFailed.style.background = "red";
		tableInner = '';
		
		for (counter in _this.GalleryData) 
		{
			if (_this.GalleryData[counter].Failed === true) 
			{
				/*tableInner = tableInner + 
					'<a href="' + this.GalleryData[counter].url + '">' +
						this.GalleryData[counter].title + '</a> ' +
						this.GalleryData[counter].error +
				'<br/>';*/
				tableInner = tableInner + 
					'<a href="' + _this.GalleryData[counter].url + '">' +
						_this.GalleryData[counter].url + '</a> ' +
						_this.GalleryData[counter].title + 
						_this.GalleryData[counter].error +
					'<br/>';
			}
		}
		tableInner = '<table width="97%"><tbody><tr><td>' + 
			'<b>Failed Pages:</b>' + '</td></tr><tr><td>' + 
			tableInner + 
			'</td></tr></tbody></table>';
		tableFailed.innerHTML = tableInner;
		tableFailed.style.display = '';
	}, // end ShowFailedUrlList
	
	createRequestObject : function () 
	{
		/*if (typeof XMLHttpRequest === 'undefined') 
        {
            XMLHttpRequest = function() 
            {
                try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
                catch(e) {}
                try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
                catch(e) {}
                try { return new ActiveXObject("Msxml2.XMLHTTP"); }
                catch(e) {}
                try { return new ActiveXObject("Microsoft.XMLHTTP"); }
                catch(e) {}
                throw new Error("This browser does not support XMLHttpRequest.");
            };
		}*/
		return new XMLHttpRequest();
	},
	
	/*html2dom : function (html)
	{
		var container = document.createElement("tbody");
		container.innerHTML = html.replace(/<script(.|\s)*?\/script>/gi,"").replace(/<iframe(.|\s)*?\/iframe>/gi,"");
		return container;
	},*/
    
    //ChangeEncoding: function (httpReq) {}, 
	
	/* 	function Get_URL_CB(url_link, callback, galleryIndex)
		multithreaded url fetching routine
		url_link	:	downloads contect from this url
		callback	:	function to call once content is downloaded
		 	called as callback(DOM object, galleryIndex)
		 	DOM object containing newly downloaded page content
		galleryIndex:	identifier of the image # to reference pages.GalleryPage
		gets url contents and puts in an on the fly div
		then calls routine "callback" with div object
		callback это ScanGallery(docbase) или
	 */
	Get_URL_CB	: function (url_link, callback, galleryIndex) {
		DebugLog('Call: Get_URL_CB(' + url_link + '): index: ' + galleryIndex);
		_this.httpCounter.runCon += 1;
		try {
			//var httpReq = new XMLHttpRequest();
			var httpReq = _this.createRequestObject();
			httpReq.onreadystatechange = function(xHttpRequest) {
				//if (galleryIndex) { pages.GalleryData[galleryIndex].xhttp = xHttpRequest; }
				//DebugLog('xmlhttpRequest readystate: ' + xHttpRequest.target.readyState + ' on ' + url_link);
				if (xHttpRequest.target.readyState == 4) {
					if (xHttpRequest.target.status == 200) 
					{
						//загружен адрес успешно
						//DebugLog('xmlhttpRequest response: ' + xHttpRequest.target.readyState + ' ' + xHttpRequest.target.status + //' ' + url_link);
						if (_this.checkers.isAborted()) return;
						DebugLog('Got 200 OK: ' + url_link);
						
                        //debugger;
                        //DebugLog(xHttpRequest.target.responseText);
                        
						var container = document.implementation.createHTMLDocument("");
						container.body.innerHTML = xHttpRequest.target.responseText;
						callback(container, galleryIndex);
						
						/*var xmlDoc = document.createElement('div');
						xmlDoc.innerHTML = xHttpRequest.target.responseText;
						callback(xmlDoc, galleryIndex);
						while (xmlDoc.firstChild) {
							xmlDoc.removeChild(xmlDoc.firstChild);
						}
						xmlDoc = null;*/
					}
					else 
					{
						DebugLog('xmlhttpRequest status error: ' + xHttpRequest.target.status + '. If 0, Probably using chrome and errored on cross-domain issue.');
						switch(xHttpRequest.target.status) {
							case 0:
								if(_this.GalleryData[galleryIndex])
									_this.GalleryData[galleryIndex].error = '0. Cross Domain Block'; 
								DebugLog('Probably using chrome and errored on cross-domain issue.');
								break;
                            case 503:
								DebugLog(url_link + ' 503. The server is currently unavailable. Sleep ' + _this.sleepTime);
								setTimeout(function(){
									DebugLog(url_link + ' Relaunch after 503.');
									_this.Get_URL_CB(url_link, callback, galleryIndex, true);
								}, _this.sleepTime);
								return;
							default:
								if(_this.GalleryData[galleryIndex])
									_this.GalleryData[galleryIndex].error = 'xmlhttpRequest status: ' + xHttpRequest.target.status;
						}
						// call the callback so we decrement the fetch counter and try another
						// запускаем на пустом div, поэтому ничего там не найдется
						//callback(document.createElement('div'), galleryIndex);
						//callback(xHttpRequest.target.response, galleryIndex);
					}
					//DebugLog('run connections: ' + this.httpCounter.runCon);
					_this.httpCounter.runCon -= 1;
					//DebugLog('run connections: ' + this.httpCounter.runCon);
				}
			};
			httpReq.open('GET', url_link, true);
			//httpReq.setRequestHeader("Access-Control-Allow-Origin", "*") 
            //_this.ChangeEncoding(httpReq);
            //для следующей галереии kinopoiska
			//if (httpReq.overrideMimeType) { 
			//	httpReq.overrideMimeType('text/html; charset=windows-1251'); 
			//}
			httpReq.send('');
		}
		catch (err) {
			//nothing to do really
			_this.httpCounter.runCon -= 1;
			DebugLog('Error occured: ' + err.message);
		}
	}, // end Get_URL_CB
	/* 	function GM_Get_URL_CB(url_link, callback, galleryIndex)
		multithreaded url fetching routine
		url_link	:	downloads contect from this url
		callback	:	function to call once content is downloaded
		 	called as callback(DOM object, galleryIndex)
		 	DOM object containing newly downloaded page content
		galleryIndex:	identifier of the image # to reference pages.GalleryPage
		gets url contents and puts in an on the fly div
		then calls routine "callback" with div object

	 	grease monkey specific url fetching routine
		needs to be used in firefox when handling
		search thumbnail pages to get around the
		same origin limitations. can be used in
		google chrome as converted userscript but
		still has same origin restriction so will fail
		on search pages.
	 */
	GM_Get_URL_CB : function (url_link, callback, galleryIndex) {
		DebugLog('Call: GM_Get_URL_CB(' + url_link + '): index: ' + galleryIndex);
		_this.httpCounter.runCon += 1;
		try {
			GM_xmlhttpRequest({
				method:'GET',
				url:url_link,
				onload:function(xHttpRequest) {
					//if (galleryIndex) { pages.GalleryData[galleryIndex].xhttp = xHttpRequest; }
					DebugLog('GM_xmlhttpRequest onload: ' + xHttpRequest.readyState + ' ' + url_link);
					if (checkers.isAborted()) return;
					if (xHttpRequest.readyState == 4) {
						if (xHttpRequest.status == 200) {
							DebugLog('xmlhttpRequest response: ' + xHttpRequest.readyState + ' ' + xHttpRequest.status + ' ' + url_link);
							if (checkers.isAborted()) return;
							if (ScriptDebug && SuperVerbose) { GM_log('Response: ' + xHttpRequest.responseText); }
							DebugLog('Got 200 OK: ' + url_link);
							var xmlDoc = document.createElement('div');
							xmlDoc.innerHTML = xHttpRequest.responseText;
							callback(xmlDoc, galleryIndex);
							while (xmlDoc.firstChild) {
								xmlDoc.removeChild(xmlDoc.firstChild);
							}
							xmlDoc = null;
						}
						else {
							DebugLog('xmlhttpRequest status error: ' + xHttpRequest.status + '. If 0, Probably using chrome and errored on cross-domain issue.');
							if (xHttpRequest.status === 0) { 
								_this.GalleryData[galleryIndex].error = 'Cross Domain Block'; 
							}
							// call the callback so we decrement the fetch counter and try another
							callback(document.createElement('div'), galleryIndex);
						}
						_this.http_Counter.runCon -= 1;
					}
				}
			});
		}
		catch (err) {
			//nothing to do really
			_this.httpCounter.runCon -= 1;
			DebugLog('Error occured: ' + err.message);
		}
	} // end GM_Get_URL_CB
};//end of baseRipper

/* Implementation */
//var kinopoiskRipper = function() {};
var KinopoiskRipper = function() {};
//kinopoiskRipper = Object.create(baseRipper);
KinopoiskRipper.prototype = Object.create(baseRipper);
KinopoiskRipper.prototype.parsers = Object.create(baseRipper.parsers);
KinopoiskRipper.prototype.parsers.GetButtonLocation = function()
{
	DebugLog('kinopoiskRipper.GetButtonLocation');
	return	document.querySelector('div.block_left table tbody tr td');
}; // end GetButtonLocation
/* 	возврашет ссылку на следующую страницу галлереи
GetNextGalleryPageLink(docbase)
requires docbase: DOM Object
returns string of url for next page
*/	
KinopoiskRipper.prototype.parsers.GetNextGalleryPageLink = function (docbase) {
    DebugLog('GetNextGalleryPageLink()');
    var links;
    var rtn_val;

    DebugLog('GetNextGalleryPageLink(): Looking for pagination container');
    links = docbase.querySelectorAll('div.navigator > ul.list > li.arr a');
    if (links) 
    {
        for (index = 0; index < links.length; ++index) 
        {
            //DebugLog(links[index]);
            if (links[index] && links[index].text === "»") 
            {
                var href = links[index].getAttribute('href');
                DebugLog('GetNextGalleryPageLink(): Next gallery is: ' + href);
                return href;
            }
        }
    }
    DebugLog('GetNextGalleryPageLink(): Failed to found next gallery.');
    return false;
}; // end GetNextGalleryPageLink
//kinopoiskRipper.isChrome = true;
//kinopoiskRipper.prototype.isChrome = true;
//KinopoiskRipper.prototype.ChangeEncoding = function (httpReq) {
    //для следующей галереии kinopoiska
	//if (httpReq.overrideMimeType)
	//	httpReq.overrideMimeType('text/html; charset=windows-1251'); 
//};
var kinopoiskRipper = new KinopoiskRipper();

//if (!kinopoiskRipper.hasOwnProperty('GetButtonLocation'))
//    throw new Error("kinopoiskRipper не имеет свойства GetButtonLocation");
//alert( kinopoiskRipper.hasOwnProperty('isChrome') );
//alert( kinopoiskRipper.parsers.hasOwnProperty('GetButtonLocation') );

//var filmzRipper = function() {};
//filmzRipper.prototype = Object.create(baseRipper);
//FilmzRipper = Object.create(baseRipper);
var FilmzRipper = function() {};
FilmzRipper.prototype = Object.create(baseRipper);
FilmzRipper.prototype.httpCounter.MAXREQ = 1;
FilmzRipper.prototype.levelForURLScaning = 1;
FilmzRipper.prototype.parsers = Object.create(baseRipper.parsers);
FilmzRipper.prototype.parsers.GetButtonLocation = function(){
	return document.querySelector('div.pages');
}; // end GetButtonLocation
FilmzRipper.prototype.parsers.GetNextGalleryPageLink = function (docbase) {
    var links = docbase.querySelectorAll('div.pages.fll.br5 > a');
    DebugLog('GetNextGalleryPageLink(): Looking for next button: ' + links);
    /*links.forEach(function(entry) {
				DebugLog(entry);
			});*/
    DebugLog("GetNextGalleryPageLink(): links:");
    for (index = 0; index < links.length; ++index) 
    {
        if (links[index] && links[index].text == "следующая") 
        {
            var href = links[index].getAttribute('href');
            DebugLog('NextGallery: ' + href);
            return href;
        }
    }
    return false;
}; // end GetNextGalleryPageLink
FilmzRipper.prototype.parsers.FindThumbnailContainer = function (docbase) {
	return docbase.querySelector('#photos_list > center:nth-child(2)');
}; // end FindThumbnailContainer
FilmzRipper.prototype.parsers.FindLinksInThumbnailContainer = function (docbase) {
    return docbase.querySelectorAll('a.fullink[href*=full]');
}; // end FindLinks
FilmzRipper.prototype.parsers.GetUrlOnFirstLevelPage = function (docbase)
{
	//var image = docbase.querySelector('div.content > div:nth-child(4) > center:nth-child(3) > a:nth-child(1) > img:nth-child(1)') ||
	//docbase.querySelector('div.content > div:nth-child(4) > center:nth-child(3) > img:nth-child(1)');
	var image = docbase.querySelector('div.content center a img');
	if (image) {
		var src = image.getAttribute('src');
		if (src === undefined) 
			DebugLog('GetBigImageUrl(): image.src = undefined, image: ' + image);
		return src;
	}
	return false;
}; // end GetUrlOnFirstLevelPage
FilmzRipper.prototype.callbacks = Object.create(baseRipper.callbacks);
var filmzRipper = new FilmzRipper();

var CeleberRipper = function() {};
CeleberRipper.prototype = Object.create(baseRipper);
CeleberRipper.prototype.levelForURLScaning = 1;
CeleberRipper.prototype.parsers = Object.create(baseRipper.parsers);
CeleberRipper.prototype.parsers.GetButtonLocation = function()
{
	return	document.querySelector('#real_content') || 
			document.querySelector('#google-horizontal-ad');
}; // end GetButtonLocation
CeleberRipper.prototype.parsers.FindThumbnailContainer = function (docbase) {
	return docbase.querySelector('div > .normal-thumbs');
}; // end FindThumbnailContainer
CeleberRipper.prototype.parsers.FindLinksInThumbnailContainer = function (docbase) {
    return docbase.querySelectorAll('a');
}; // end FindLinks
CeleberRipper.prototype.parsers.GetNextGalleryPageLink = function (docbase) {
    DebugLog('GetNextGalleryPageLink()');
    var newdocbase;
    var rtn_val;

    DebugLog('Looking for pagination container');
    newdocbase = docbase.querySelector('div.pages');

    DebugLog('Looking for next button in ' + newdocbase);
    if (newdocbase) 
        rtn_val = newdocbase.querySelector('a.next-page');

    if (rtn_val) 
    {
        //rtn_val.href
        var href = rtn_val.getAttribute('href');
        DebugLog('NextGallery: ' + href);
        return href;
    }
    else 
        return false;
    DebugLog('GetNextGalleryPageLink(): Failed to found next gallery.');
    return false;
}; // end GetNextGalleryPageLink
CeleberRipper.prototype.parsers.GetUrlOnFirstLevelPage = function (docbase)
{
	//var but = docbase.querySelector('#download_button < a');
    var but = docbase.querySelector('#real_content > div.zoom-container > img');
    //return but.href;
    return but.getAttribute('data-src');
}; // end GetUrlOnFirstLevelPage
CeleberRipper.prototype.parsers.GetSmallImageUrlOnFirstLevelPage = function (docbase)
{
    //return docbase.querySelector('a.image-holder img');
    return docbase.querySelector('#image_1').src;
}; // end GetSmallImageUrlOnFirstLevelPage
CeleberRipper.prototype.parsers.GetDescription = function (docbase) {
    return docbase.querySelector('#real_content > div.description > p:nth-child(1)').innerText;
}; 
var celeberRipper = new CeleberRipper();



var TumblrRipper = function() {};
TumblrRipper.prototype = Object.create(baseRipper);
TumblrRipper.prototype.levelForURLScaning = 0;
TumblrRipper.prototype.parsers = Object.create(baseRipper.parsers);
TumblrRipper.prototype.parsers.GetButtonLocation = function(){
    //debugger;
    //return	document.querySelector('#content');
    return	document.querySelector('.description') ||
        document.querySelector('#content-wrapper > div.grid.three-col > article') ||
        document.querySelector('#header > div.xnav');
        //document.querySelector('#blog_info > h1');
}; // end GetButtonLocation*/
TumblrRipper.prototype.parsers.GetNextGalleryPageLink = function (docbase) {
    var href;
    var link = docbase.querySelector('#content-wrapper > div.pagination > a.next');
    DebugLog('GetNextGalleryPageLink(): Looking for next button: ' + link);
    if(link)
    {
        href = link.getAttribute('href');
        DebugLog('NextGallery: ' + href);
        return href;
    }
    
    link = docbase.querySelector('#pagination > a');
    if(link)
    {
        href = link.getAttribute('href');
        var totalPages = link.getAttribute('data-total-pages');
        if (totalPages)
            DebugLog('data-total-pages: ' + totalPages);
        return href;
    }
    return false;
}; // end GetNextGalleryPageLink
TumblrRipper.prototype.parsers.FindThumbnailContainer = function (docbase) {
    //debugger;
    //var i1 = docbase.querySelectorAll('#content-wrapper div.post-content');
    //var i2 = docbase.querySelectorAll('#content-wrapper > div.post-content');
    //return docbase.querySelectorAll('#content-wrapper ');
    //return docbase.querySelector('#content-wrapper div.init-posts.active');
	//return docbase.querySelector('#content-wrapper div.post-content');
    return docbase;
}; // end FindThumbnailContainer
TumblrRipper.prototype.parsers.FindLinksInThumbnailContainer = function (docbase) {
    //debugger;
	var links = docbase.querySelectorAll('#content-wrapper div.post-content');
    if (links.length === 0)
        links = docbase.querySelectorAll('#posts section.top.media > a > img');
    if (links.length === 0)
        links = docbase.querySelectorAll('#posts > div > article');
    if (links.length === 0)
        links = docbase.querySelectorAll('#content > div');
        //links = docbase.querySelectorAll('div.photoset');
    /*var links = [];
    for(var i = 0; i < docbase.length; i++)
    {
        links.push(docbase[i].querySelector('div.post-content > a > img'));
    }*/
    return links;
}; // end FindLinks
TumblrRipper.prototype.parsers.GetRefFromLinksInThumbnailContainer = function (doc) {
    //debugger;
    var atr;
    var link = doc.querySelector('a > img');
    if (link) {
        atr = link.getAttribute('data-highres');
        if (atr) return atr;
        
        atr = link.getAttribute('src');
        if (atr) return atr;
        
        atr = doc.getAttribute('src');
        if (atr) return atr;
    }
    
    link = doc.querySelector('a');
    if (link) {
        atr = link.getAttribute('href');
        if (atr) return atr;
    }
}; // end GetRefFromLinksInThumbnailContainer
TumblrRipper.prototype.parsers.GetDescription = function (docbase) {
    //debugger;
    var text;
    var sel = docbase.querySelector('blockquote > p');
    if (sel) {
        text = sel.textContent;
        if (text) {
            text = text.replace(/www.OnlyRippedGirls.com/gi, "");
            text = text.replace(/More Girls on the website/gi, "");
            return text;
        }
    }
    
    sel = docbase.querySelector('div > section.post figcaption.caption');
    if (sel) {
         text = sel.textContent;
         if (text) {
            text = text.trim();
            return text;
        }
    }
    return false;
}; 
var tumblrRipper = new TumblrRipper();


function ready() {
	//alert( 'DOM готов' );
	//alert( "Размеры картинки: " + img.offsetWidth + "x" + img.offsetHeight );
     //       debugger;
	DebugLog("Current URL loaded from: " + document.location.href);
	try 
	{
		//DebugLog(kinopoiskRipper.parsers);
		//var t = kinopoiskRipper.parsers.GetButtonLocation();
		//DebugLog(t);
		if(location.href.match('filmz.ru')){
			DebugLog('Запускаем filmzRipper');
			filmzRipper.init();
		}
		else if(location.href.match('kinopoisk.ru')){
            DebugLog('Запускаем kinopoiskRipper');
			kinopoiskRipper.init();
		}
        //x(?!y) 	Находит x, только если за x не следует y. 
        //Например, /\d+(?!\.)/ найдет число, только если за ним не следует десятичная точка. /\d+(?!\.)/.exec("3.141") найдет 141, но не 3.141.
        //else if(location.href.match(/tumblr.com.*(?!iframe)/)){
        else if(location.href.match(/tumblr.com/) &&
               !location.href.match(/iframe/) &&
               !location.href.match(/analytics.html/) &&
               !location.href.match(/yahoo_cookie_receiver.html/)){
            DebugLog('Запускаем TumblrRipper');
			tumblrRipper.init();
		}
		else if(location.href.match('celeber.ru')){
            DebugLog('Запускаем CeleberRipper');
			celeberRipper.init();
		}
	}
	catch(e)
	{
		alert('Ripper error: ' + e);
	}
}
  
document.addEventListener("DOMContentLoaded", ready, false);
if (baseRipper.isChrome)
    setTimeout(ready, 2000);

/*window.onload = function() 
{
	DebugLog("Current URL loaded from: " + document.location.href);
	try 
	{
		baseRipper.init();
	}
	catch(e)
	{
		alert(e);
	}
};*/