Zelluloza Dumper

Сохраняет фрагмент или все фрагменты книги, доступные для чтения в формате fb2. Книги защищенные максимальной защитой сохранет в виде картинок в pdf или fb2

目前為 2017-11-02 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Zelluloza Dumper
// @version      0.6
// @description  Сохраняет фрагмент или все фрагменты книги, доступные для чтения в формате fb2. Книги защищенные максимальной защитой сохранет в виде картинок в pdf или fb2
// @author       MadDAD
// @require  https://greasyfork.org/scripts/15924-jspdf/code/jsPDF.js?version=99137
// @require  https://greasyfork.org/scripts/2350-filesaver-js/code/filesaverjs.js?version=6255
// @include  https://zelluloza.ru/books/*
// @include  https://zelluloza.ru/search/*
// @namespace https://greasyfork.org/users/38856
// ==/UserScript==

//*******************************************************************************************
function $(id)
{
	var result = document.getElementById(id);

	if (result === null)
	{
		result = document.getElementsByClassName(id);

		if (result === undefined)
			result = document.getElementsByTagName(id);

		if (result === undefined)
			return null;

		if (result.length == 1)
			return result[0];
	}
	else
		return result;
}

//*******************************************************************************************
function retrieveWindowVariables(variables)
{
	var ret = {};

	var scriptContent = "";
	for (var i = 0; i < variables.length; i++)
	{
		var currVariable = variables[i];
		scriptContent += "if (typeof " + currVariable + " !== 'undefined') document.body.attributes['tmp_" + currVariable + "'] = eval(" + currVariable + ");\n"
	}

	var script = document.createElement('script');
	script.id = 'tmpScript';
	script.appendChild(document.createTextNode(scriptContent));
	(document.body || document.head || document.documentElement).appendChild(script);

	for (var i = 0; i < variables.length; i++)
	{
		var currVariable = variables[i];
		ret[currVariable] = document.body.attributes[currVariable];
		document.body.removeAttribute(currVariable);
	}

	document.getElementById("tmpScript").remove();

	return ret;
}

//***************************************
function getXmlHttp()
{
	var a;
	try
	{
		a = new ActiveXObject("Msxml2.XMLHTTP")
	}
	catch (d)
	{
		try
		{
			a = new ActiveXObject("Microsoft.XMLHTTP")
		}
		catch (b)
		{
			a = false
		}
	}
	if (!a && typeof XMLHttpRequest != "undefined")
	{
		a = new XMLHttpRequest()
	}
	return a
}

//*************************************
HTMLImageElement.prototype.getUrlData = function ()
{
	var cnv = document.createElement("CANVAS");
	cnv.width = this.width;
	cnv.height = this.height;
	var cont = cnv.getContext("2d");
	cont.drawImage(this, 0, 0);
	return cnv.toDataURL('image/png', 0, 0);
};

//Asinc image loader
function ImageLoader(images, callback)
{
	// store the call-back
	this.callback = callback;
	// initialize internal state.
	this.nLoaded = 0;
	this.nProcessed = 0;
	this.aImages = new Array();
	// record the number of images.
	this.nImages = images.length;
	// for each image, call preload()
	for (var i = 0; i < images.length; i++)
		this.preload(images[i]);
}

ImageLoader.prototype.preload = function (image)
{
	// create new Image object and add to array
	var oImage = new Image();
	this.aImages.push(oImage);
	// set up event handlers for the Image object
	oImage.onload = ImageLoader.prototype.onload;
	oImage.onerror = ImageLoader.prototype.onerror;
	oImage.onabort = ImageLoader.prototype.onabort;
	// assign pointer back to this.
	oImage.oImageLoader = this;
	oImage.bLoaded = false;
	oImage._src = image;
	// assign the .src property of the Image object
	oImage.src = image;
};

ImageLoader.prototype.onComplete = function ()
{
	this.nProcessed++;
	my_getbyid("bookpg").innerHTML = 'Загружено страниц: ' + this.nProcessed + ' из ' + this.nImages;
	if (this.nProcessed == this.nImages)
	{
		this.callback(this.aImages, this.nLoaded);
	}
};

ImageLoader.prototype.onload = function ()
{
	this.bLoaded = true;
	this.oImageLoader.nLoaded++;
	this.oImageLoader.onComplete();
};

ImageLoader.prototype.onerror = function ()
{
	this.bError = true;
	this.oImageLoader.onComplete();
};

ImageLoader.prototype.onabort = function ()
{
	this.bAbort = true;
	this.oImageLoader.onComplete();
};
//*************************************

function ParceUserToken(aScripts)
{
	for (var i = 0; i < aScripts.length; i++)
	{
		var CurrentScript = aScripts[i];
		if (CurrentScript.text !== "")
			if (CurrentScript.text.indexOf('getbook') > 0)

			{
				UserToken = eval(CurrentScript.text.split(';')[1].split(',')[5]);
				if (UserToken !== undefined)
					return UserToken;
			}
	}
}

function getDoc(ref)
{
	var xmlhttp = getXmlHttp();
	xmlhttp.open("GET", ref, false);

	if (xmlhttp.readyState == 1)
	{
		xmlhttp.setRequestHeader("Content-Type", "text/html");
		xmlhttp.send();
	}

	if (xmlhttp.status != 200)
	{
		alert(xmlhttp.status + ': ' + xmlhttp.statusText); // пример вывода: 404: Not Found
	}
	else
	{
		return new DOMParser().parseFromString(xmlhttp.responseText, "text/html");
	}
}

function GetUserToken(dDoc)
{
	if (dDoc === undefined)
		dDoc = document;

	var UserToken = ParceUserToken(dDoc.getElementsByTagName("script"));

	if (UserToken === undefined)
	{
		var URL = dDoc.getElementsByClassName("taglnk2");
		for (var i = 0; i < URL.length; i++)
		{
			UserToken = ParceUserToken(getDoc(URL[i].getAttribute("href")).getElementsByTagName("script"));
			if (UserToken !== undefined)
				return UserToken;
		}

	}

	return UserToken;
}

//************************************* Асинхронный загрузчик глав
function FragmentLoader(links, usertoken, callback, progressor)
{
	this.callback = callback;
	this.nLoaded = 0;
	this.nProcessed = 0;
	this.bloaded = false;
	this.nFragments = links.length;
	this.usertoken = usertoken;
	this.aFragments = new Array();
	this.progressor = progressor;
	for (var i = 0; i < this.nFragments; i++)
	{
		this.load(links[i], i);
	}
}

FragmentLoader.prototype.load = function (fragment, fnumber)
{
	var xmlhttp = getXmlHttp();
	xmlhttp.oFragmentLoader = this;

	var Chapter =
	{
		number : fnumber,
		name : fragment.childNodes[3].text,
		link : fragment.childNodes[3].getAttribute("href"),
		bookId : fragment.childNodes[3].getAttribute("href").split('/')[2],
		partId : fragment.childNodes[3].getAttribute("href").split('/')[3],
		text : '<p>Необходимо купить фрагмент</p>',
		needToBuy : fragment.childNodes[1].value.indexOf('Купить') != -1
	};

	xmlhttp.Fragment = Chapter;
	//xmlhttp.onload = FragmentLoader.prototype.onload;
	xmlhttp.onreadystatechange = FragmentLoader.prototype.onload;

	if (Chapter.needToBuy)
	{
		xmlhttp.onreadystatechange();
		return;
	}

	var params = "op=" + encodeURIComponent('getbook') + "&par1=" + encodeURIComponent(Chapter.bookId) + "&par2=" + encodeURIComponent(Chapter.partId + ':0.0.1::0') + "&par4=" + encodeURIComponent(this.usertoken);
	if (xmlhttp.readyState == 0)
	{
		xmlhttp.open("POST", "/ajaxcall/", true);
	}

	if (xmlhttp.readyState == 1)
	{
		xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		xmlhttp.send(params);
	}

};

FragmentLoader.prototype.onload = function ()
{

	if (this.Fragment.needToBuy)
	{
		this.oFragmentLoader.nLoaded++;
		this.oFragmentLoader.aFragments[this.Fragment.number] = this.Fragment;
		this.oFragmentLoader.onComplete();
		return;
	}

	if (this.readyState == 4 && this.status == 200)
	{
		this.Fragment.text = "";
		var str = this.responseText.split("<END>")[0].split(/\n/);
		for (var j in str)
		{
			this.Fragment.text += '<p>' + DS('', str[j]).replace('\r', '').replace('[ctr][gry]- Конец фрагмента -[/][/]', '') + '</p>\n';
		}
		this.oFragmentLoader.nLoaded++;
		this.oFragmentLoader.aFragments[this.Fragment.number] = this.Fragment;
		this.oFragmentLoader.onComplete();
	}
};

FragmentLoader.prototype.onerror = function ()
{
	this.bError = true;
	this.Fragment.text = "<p>Ошибка загрузки фрагмента</p>";
	this.oFragmentLoader.aFragments.push(this.Fragment);
	this.oFragmentLoader.onComplete();
};

FragmentLoader.prototype.onComplete = function ()
{
	this.nProcessed++;
	this.progressor(this.nProcessed, this.nFragments);
	this.bloaded = this.nProcessed == this.nFragments;

	if (this.bloaded)
	{
		this.callback(this.aFragments, this.nProcessed);
	}
};
//**************************************************************************************************************************************

function getGenre(doc)
{
	if (doc === undefined)
		doc = document;

	var genresList =
	{
		"Фантастика" : "sf",
		"ЛитРПГ" : "sf_etc",
		"Фэнтези" : "sf_fantasy",
		"Фантастический боевик" : "sf_action",
		"Ужасы" : "sf_horror",
		"Любовная фантастика" : "love_sf",
		"Альтернативная история" : "sf_history",
		"Социальная фантастика" : "sf_social",
		"Космическая фантастика" : "sf_space",
		"Юмористическая фантастика" : "sf_humor",
		"Детская фантастика" : "child_sf",
		"Попаданцы" : "popadanec",
		"Мистика" : "sf_mystic",
		"Городское фэнтези" : "sf_fantasy_city",
		"Детективная фантастика" : "sf_detective",
		"Героическая фантастика" : "sf_heroic",
		"Постапокалипсис" : "sf_postapocalyptic",
		"Киберпанк" : "sf_cyberpunk",
		"Эпическая фантастика" : "sf_epic",
		"Юмористическое фэнтези" : "humor_fantasy",
		"Космоопера" : "sf_space_opera",
		"Историческое фэнтези" : "historical_fantasy",
		"Сказочная фантастика" : "fairy_fantasy",
		"Технофэнтези" : "sf_technofantasy",
		"Ненаучная фантастика" : "nsf",
		"Ироническая фантастика" : "sf_irony",
		"Стимпанк" : "sf_stimpank",
		"Ироническое фэнтези" : "sf_fantasy_irony",
		"Готический роман" : "gothic_novel",
		"Современная проза" : "prose_contemporary",
		"Классическая проза" : "prose_classic",
		"Историческая проза" : "prose_history",
		"Русская классическая проза" : "prose_rus_classic",
		"Советская классическая проза" : "prose_su_classics",
		"Проза" : "prose",
		"Рассказ" : "short_story",
		"О войне" : "prose_military",
		"Контркультура" : "prose_counter",
		"Роман" : "roman",
		"Эссе, очерк, этюд, набросок" : "essay",
		"Повесть" : "great_story",
		"Магический реализм" : "prose_magic",
		"Эпистолярная проза" : "epistolary_fiction",
		"Афоризмы" : "aphorisms",
		"Новелла" : "story",
		"Антисоветская литература" : "dissident",
		"Семейный роман/Семейная сага" : "sagas",
		"Сентиментальная проза" : "prose_sentimental",
		"Эпопея" : "prose_epic",
		"Феерия" : "extravaganza",
		"История" : "sci_history",
		"Психология" : "sci_psychology",
		"Философия" : "sci_philosophy",
		"Технические науки" : "sci_tech",
		"Политика" : "sci_politics",
		"Литературоведение" : "sci_philology",
		"Культурология" : "sci_culture",
		"Научная литература" : "science",
		"Учебники" : "sci_textbook",
		"Медицина" : "sci_medicine",
		"Военная история" : "military_history",
		"Языкознание" : "sci_linguistic",
		"Религиоведение" : "sci_religion",
		"Юриспруденция" : "sci_juris",
		"Биология" : "sci_biology",
		"Математика" : "sci_math",
		"Педагогика" : "sci_pedagogy",
		"Физика" : "sci_phys",
		"Деловая литература" : "sci_business",
		"Астрономия и Космос" : "sci_cosmos",
		"Геология и география" : "sci_geo",
		"Альтернативная медицина" : "sci_medicine_alternative",
		"Экономика" : "sci_economy",
		"Обществознание" : "sci_social_studies",
		"Секс и семейная психология" : "psy_sex_and_family",
		"Иностранные языки" : "foreign_language",
		"Шпаргалки" : "sci_crib",
		"Химия" : "sci_chem",
		"Психотерапия и консультирование" : "psy_theraphy",
		"Детская психология" : "psy_childs",
		"Зоология" : "sci_zoo",
		"Ботаника" : "sci_botany",
		"Государство и право" : "sci_state",
		"Экология" : "sci_ecology",
		"Биохимия" : "sci_biochem",
		"Ветеринария" : "sci_veterinary",
		"Физическая химия" : "sci_physchem",
		"Биофизика" : "sci_biophys",
		"Органическая химия" : "sci_orgchem",
		"Аналитическая химия" : "sci_anachem",
		"Рефераты" : "sci_abstract",
		"Детективы" : "detective",
		"Триллер" : "thriller",
		"Классический детектив" : "det_classic",
		"Боевик" : "det_action",
		"Исторический детектив" : "det_history",
		"Полицейский детектив" : "det_police",
		"Криминальный детектив" : "det_crime",
		"Любовный детектив" : "love_detective",
		"Иронический детектив" : "det_irony",
		"Детские остросюжетные" : "child_det",
		"Шпионский детектив" : "det_espionage",
		"Крутой детектив" : "det_hard",
		"Дамский детективный роман" : "det_cozy",
		"Политический детектив" : "det_political",
		"Маньяки" : "det_maniac",
		"Медицинский триллер" : "thriller_medical",
		"Юридический триллер" : "thriller_legal",
		"Техно триллер" : "thriller_techno",
		"Биографии и Мемуары" : "nonf_biography",
		"Публицистика" : "nonf_publicism",
		"Научпоп" : "sci_popular",
		"Путешествия и география" : "adv_geo",
		"Критика" : "nonf_criticism",
		"Документальная литература" : "nonfiction",
		"Природа и животные" : "adv_animal",
		"Военная документалистика" : "nonf_military",
		"Современные любовный роман" : "love_contemporary",
		"Короткие любовный роман" : "love_short",
		"Исторические любовный роман" : "love_history",
		"О любви" : "love",
		"18+" : "love_erotica",
		"любовный детективы" : "love_detective",
		"Порно" : "love_hard",
		"Газеты и журналы" : "periodic",
		"Фанфик" : "fanfiction",
		"Музыка" : "music",
		"Недописанное" : "unfinished",
		"Кино" : "cine",
		"Изобразительное искусство, фотография" : "visual_arts",
		"Театр" : "theatre",
		"Партитуры" : "notes",
		"Неотсортированное" : "other",
		"Детская проза" : "child_prose",
		"Сказка" : "child_tale",
		"Детская литература" : "children",
		"Образовательная литература" : "child_education",
		"Детские приключения" : "child_adv",
		"Детские стихи" : "child_verse",
		"Подростковая литература" : "ya",
		"Книга-игра" : "prose_game",
		"Детский фольклор" : "child_folklore",
		"Домоводство" : "Дом и семья",
		"Здоровье" : "home_health",
		"Эротика, Секс" : "home_sex",
		"Хобби и ремесла" : "home_crafts",
		"Кулинария" : "home_cooking",
		"Сделай сам" : "home_diy",
		"Спорт" : "home_sport",
		"Домашние животные" : "home_pets",
		"Сад и огород" : "home_garden",
		"Развлечения" : "home_entertain",
		"Коллекционирование" : "home_collecting",
		"Эзотерика" : "religion_esoterics",
		"Самосовершенствование" : "religion_self",
		"Религия" : "religion_rel",
		"Христианство" : "religion_christianity",
		"Православие" : "religion_orthodoxy",
		"Буддизм" : "religion_budda",
		"Индуизм" : "religion_hinduism",
		"Иудаизм" : "religion_judaism",
		"Астрология" : "astrology",
		"Протестантизм" : "religion_protestantism",
		"Язычество" : "religion_paganism",
		"Ислам" : "religion_islam",
		"Религиозная литература" : "religion",
		"Католицизм" : "religion_catholicism",
		"Хиромантия" : "palmistry",
		"Приключения" : "adventure",
		"Исторические приключения" : "adv_history",
		"Морские приключения" : "adv_maritime",
		"Вестерн" : "adv_western",
		"Приключения про индейцев" : "adv_indian",
		"Юмористическая проза" : "humor_prose",
		"Юмор" : "humor",
		"Сатира" : "humor_satire",
		"Комедия" : "comedy",
		"Анекдоты" : "humor_anecdote",
		"Юмористические стихи" : "humor_verse",
		"Военная техника и вооружение" : "military_weapon",
		"Cпецслужбы" : "military_special",
		"Боевые искусства" : "military_arts",
		"Военное дело" : "military",
		"Справочники" : "ref_ref",
		"Руководства" : "ref_guide",
		"Энциклопедии" : "ref_encyc",
		"Искусство и Дизайн" : "design",
		"Путеводители" : "geo_guides",
		"Справочная литература" : "reference",
		"Словари" : "ref_dict",
		"Поэзия" : "poetry",
		"Лирика" : "lyrics",
		"в стихах" : "in_verse",
		"Эпическая поэзия" : "epic_poetry",
		"Песенная поэзия" : "song_poetry",
		"Басни" : "fable",
		"Экспериментальная поэзия" : "experimental_poetry",
		"Палиндромы" : "palindromes",
		"Верлибры" : "vers_libre",
		"Визуальная поэзия" : "visual_poetry",
		"Транспорт и авиация" : "sci_transport",
		"Радиоэлектроника" : "sci_radio",
		"Автомобили и ПДД" : "auto_regulations",
		"Строительство и сопромат" : "sci_build",
		"Архитектура" : "architecture_book",
		"Металлургия" : "sci_metal",
		"Драматургия" : "dramaturgy",
		"Драма" : "drama",
		"Киносценарии" : "screenplays",
		"Трагедия" : "tragedy",
		"Сценарии" : "scenarios",
		"Водевиль" : "vaudeville",
		"Мистерия" : "mystery",
		"О бизнесе популярно" : "popular_business",
		"Управление, подбор персонала" : "management",
		"Маркетинг, PR, реклама" : "marketing",
		"Ценные бумаги, инвестиции" : "stock",
		"Бухучет и аудит" : "accounting",
		"Личные финансы" : "personal_finance",
		"Малый бизнес" : "small_business",
		"Поиск работы, карьера" : "job_hunting",
		"Корпоративная культура" : "org_behavior",
		"Отраслевые издания" : "industries",
		"Банковское дело" : "banking",
		"Торговля" : "trade",
		"Делопроизводство" : "paper_work",
		"Недвижимость" : "real_estate",
		"Внешняя торговля" : "global_economy",
		"Околокомпьютерная литература" : "computers",
		"Программирование" : "comp_programming",
		"Программы" : "comp_soft",
		"ОС и Сети" : "comp_osnet",
		"Интернет" : "comp_www",
		"Аппаратное обеспечение" : "comp_hard",
		"Базы данных" : "comp_db",
		"Цифровая обработка сигналов" : "comp_dsp",
		"Мифы.Легенды.Эпос" : "antique_myths",
		"Древневосточная литература" : "antique_east",
		"Античная литература" : "antique_ant",
		"Древнеевропейская литература" : "antique_european",
		"Старинная литература" : "antique",
		"Древнерусская литература" : "antique_russian",
		"Народные сказки" : "folk_tale",
		"Фольклор" : "folklore",
		"Пословицы, поговорки" : "proverbs",
		"Былины" : "epic",
		"Народные песни" : "folk_songs",
		"Частушки, прибаутки, потешки" : "limerick",
		"Загадки" : "riddles"
	};

	var genre = "";
	var Series = doc.getElementsByClassName('gnres');

	if (Series.length == 1)
		var genres = RegExp('.*Жанры: (.*)$', 'm').exec(Series[0].outerText)[1].split(', ').join(',').split(',');
	else
		var genres = RegExp('.*Жанры: (.*)$', 'm').exec(Series[1].outerText)[1].split(', ').join(',').split(',');

	if (genres !== null)
	{
		for (var i = 0; i < genres.length; i++)
		{

			if (genresList[genres[i]] !== undefined)
			{
				genre += "<genre>" + genresList[genres[i]] + "</genre>\n";
			}
		}

		return genre;
	}

	if (genre === "")
	{
		return "<genre/>";
	}

}

function getAuthorName(doc)
{
	if (doc === undefined)
		doc = document;

	var authors = doc.getElementsByClassName('city3');

	if (authors.length == 1)
		var FIO = authors[0].getElementsByClassName('txt')[0].text.split(' ');
	else
		var FIO = authors[1].getElementsByClassName('txt')[0].text.split(' ');

	if (FIO.length == 1)
	{
		return "<first-name>" + FIO[0] + "</first-name>";
	}

	if (FIO.length == 2)
	{
		return "<first-name>" + FIO[0] + "</first-name>\n<last-name>" + FIO[1] + "</last-name>";
	}

	if (FIO.length == 3)
	{
		return "<first-name>" + FIO[1] + "</first-name>\n<middle-name>" + FIO[2] + "</middle-name>\n<last-name>" + FIO[0] + "</last-name>";
	}

	return "<first-name>" + FIO[0].join(' ') + "</first-name>";

}

function getAnnotation(doc)
{
	if (doc === undefined)
		doc = document;

	return doc.getElementsByTagName("meta", "")[4].content;
}

function getSeries(doc)
{
	if (doc === undefined)
		doc = document;

	var Series = doc.getElementsByClassName('serie');

	if (Series.length == 1)
		var res = new RegExp('.*Серия: (.*)$', 'm').exec(Series[0].outerText);
	else
		var res = new RegExp('.*Серия: (.*)$', 'm').exec(Series[1].outerText);

	if (res !== null)
		return '<sequence name="' + res[1].trim() + '" number=""/>';
	else
		return '';
}

function getBookCover()
{
	
}

function AllBook(event)
{
	var book = event.path[1].children[1];
	var bookid = parseInt(book.href.split('/')[4]);
	//var MaxProtection = my_getbyid("protected1").src !== '';
	var doc = getDoc(book.getAttribute("href"));

	var coverImage = new Image();
	coverImage.src = doc.getElementById("relat" + bookid).children[0].children[0].getAttribute("src");
	var coverLoaded = false;
	coverImage.onload = function ()
	{

		var cover = coverImage.getUrlData();
		var MaxProtection = false;
		if (!MaxProtection)
		{
			var pageHtml = "";
			var UserToken = GetUserToken(doc);
			var BookTitle = book.childNodes[0].textContent;

			pageHtml = '<?xml version="1.0" encoding="utf-8"?>\n<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:xlink="http://www.w3.org/1999/xlink">\n';
			pageHtml += '<description>\n<title-info>' + getGenre(doc) + '<author>' + getAuthorName(doc) + '</author>\n';
			pageHtml += '<coverpage><image xlink:href="#' + coverImage.src + '"/></coverpage>\n';
			pageHtml += '<book-title>' + BookTitle + '</book-title>\n';
			pageHtml += '<annotation><p>' + getAnnotation(doc) + '</p></annotation>\n';
			pageHtml += '<lang>ru</lang><src-lang>ru</src-lang>\n';
			pageHtml += getSeries(doc);
			pageHtml += '</title-info><document-info><author><nickname/><email/></author><version>2.0</version></document-info>\n';
			pageHtml += '<publish-info><book-name>' + BookTitle + '</book-name></publish-info></description>\n';
			pageHtml += '<body>\n';
			pageHtml += '<title>\n';
			pageHtml += '<p>' + BookTitle + '</p>\n';
			pageHtml += '</title>\n';

			var loader = new FragmentLoader(doc.getElementsByClassName('chapt'), UserToken,
					function (aChapters, nChapters)
				{
					aChapters.forEach(function (item, i, aChapters)
					{
						pageHtml += '<section><title><p>' + item.name + '</p></title>\n';
						pageHtml += item.text;
						pageHtml += '</section>\n';

					}
					);

					pageHtml += '</body>';
					pageHtml += '<binary content-type="image/png" id="' + coverImage.src + '">\n' + cover.replace('data:image/png;base64,', '') + '\n</binary>';
					pageHtml += '</FictionBook>';

					var file = new File([pageHtml], BookTitle + '.fb2',
						{
							type : "text/plain;charset=utf-8"
						}
						);
					saveAs(file, BookTitle + '.fb2');
					book.childNodes[0].innerHTML = BookTitle;

				},
					function (nProcessed, nCount)
				{
					book.childNodes[0].innerHTML = BookTitle + "(Загружено " + nProcessed + " глав из " + nCount + ")";
				}
				);
		}
	};
}

function getMaxPages()
{
	var scripts = document.getElementsByTagName("script");
	var maxpg = null;
	for (var i = 0; i < scripts.length; i++)
	{
		if(scripts[i].text.indexOf('InitRead') != -1)
		{
			return scripts[i].text.split('\n')[1];
			maxpg = parseInt(scripts[i].text.split('\n')[1].split(',')[6]);
			return maxpg;
		}
	}
	return null;
}

function unprotect(text, format)
{
	var pageHtml = null;
	if (format === undefined)
		format = "fb2";

	if (document.location.hostname == "zelluloza.ru")
	{

		eval(getMaxPages());
		//var maxpg = getMaxPages();

		var BookId = document.getElementById("gotobook").value;
		var PartId = document.getElementsByClassName("taglnk2")[0].href.split('/')[5];
		var UserToken = GetUserToken();
		var BookTitle = "";

		if (books.length == 1)
			BookTitle = document.getElementsByClassName("booklnk4")[0].childNodes[0].innerHTML;
		else
			BookTitle = document.getElementsByClassName("booklnk4")[1].childNodes[0].innerHTML;
		var PartTitle = document.getElementsByClassName("taglnk2")[0].text;

		if (document.getElementsByClassName("booklnk4"))
		{

			pageHtml = '<?xml version="1.0" encoding="utf-8"?>\n<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:xlink="http://www.w3.org/1999/xlink">\n';
			pageHtml += '<description>\n<title-info>' + getGenre() + '<author>' + getAuthorName() + '</author>\n';
			//pageHtml += '<coverpage><image xlink:href="#' + coverImage.src + '"/></coverpage>\n';
			pageHtml += '<book-title>' + BookTitle + '</book-title>\n';
			pageHtml += '<annotation><p>' + getAnnotation() + '</p></annotation>\n';
			pageHtml += '<lang>ru</lang><src-lang>ru</src-lang>\n';
			pageHtml += getSeries();
			pageHtml += '</title-info><document-info><author><nickname/><email/></author><version>2.0</version></document-info>\n';
			pageHtml += '<publish-info><book-name>' + BookTitle + '</book-name></publish-info></description>\n';
			pageHtml += '<body>\n';
			pageHtml += '<title>\n';
			pageHtml += '<p>' + BookTitle + '</p>\n';
			pageHtml += '</title>\n';

			pageHtml += '<section><title><p>' + PartTitle + '</p></title>';
		}

		var MaxProtection = my_getbyid("protected1").src !== '';
		if (!MaxProtection)
		{
			var Z = chp[0].split(/\n/);
			for (var j in Z)
			{
				pageHtml += '<p>' + DS('', Z[j]).replace('\r', '').replace('\n', '').replace('[ctr][gry]- Конец фрагмента -[/][/]', '') + '</p>\n';
			}
			pageHtml += '</section></body></FictionBook>';
			var file = new File([pageHtml], BookTitle + '.fb2',
				{
					type : "text/plain;charset=utf-8"
				}
				);
			saveAs(file, BookTitle + '(' + PartTitle + ').fb2');
		}
		else
		{
			var pages = new Array();
			oCanvas = my_getbyid("cnv1");
			oCtx = oCanvas.getContext("2d");
			pagessize = 5;
			var page = 0;
			var loaded = false;
			for (page = 0; page <= maxpg; page += pagessize)
			{
				pages[page] = "/get/" + base64_encode(BookId + ":" + PartId + ":" + pagessize + ":" + page);
			}

			var binaryImages = "";
			var pp = new ImageLoader(pages, function (aImages, nLoaded)
				{
					if (format == "fb2")
					{

						aImages.forEach(function (item, i, aImages)
						{
							if (item.bLoaded)
							{
								oCtx.drawImage(item, 0, 0);
								pageHtml += '<image xlink:href="#page_' + i + '.jpg"/>\n';
								binaryImages += '<binary content-type="image/png" id="page_' + i + '.jpg">\n' + oCanvas.toDataURL("image/png", 1.0).replace('data:image/png;base64,', '') + '\n</binary>';
							}
						}
						);

						pageHtml += '</section></body>';
						pageHtml += binaryImages;
						pageHtml += '</FictionBook>';
						var file = new File([pageHtml], BookTitle + '(' + PartTitle + ').fb2',
							{
								type : "text/plain;charset=utf-8"
							}
							);
						saveAs(file, BookTitle + '(' + PartTitle + ').fb2');
					}
					else
					{
						var pdf = new jsPDF('p', 'pt', 'b5', 1);
						pdf.internal.pageSize =
						{
							"height" : 480,
							"widht" : 550
						};

						var pdfInternals = pdf.internal;
						var pdfPageSize = pdfInternals.pageSize;
						var pdfPageWidth = pdfPageSize.width;
						var pdfPageHeight = pdfPageSize.height;

						var flags =
						{
							"noBOM" : true,
							"autoencode" : true
						};

						pdf.text(BookTitle, pdfPageWidth / 3, 20, flags);
						pdf.text(PartTitle, pdfPageWidth / 3, 40, flags);

						aImages.forEach(function (item, i, aImages)
						{
							if (item.bLoaded)
							{
								oCtx.drawImage(item, 0, 0);
								var img = oCanvas.toDataURL("image/png", 1.0);
								pdf.addPage();
								pdf.addImage(img, "png", 10, 70, 0, 0);
							}
						}
						);

						pdf.save(BookTitle + '(' + PartTitle + ').pdf');
					}
				}
				);

		}
	}
}

function loadScriptText(ref)
{
	var xmlhttp = getXmlHttp();
	xmlhttp.open("GET", ref, false);

	if (xmlhttp.readyState == 1)
	{
		xmlhttp.setRequestHeader("Content-Type", "text/html");
		xmlhttp.send();
	}

	if (xmlhttp.status != 200)
	{
		alert(xmlhttp.status + ': ' + xmlhttp.statusText); // пример вывода: 404: Not Found
	}
	else
	{
		return xmlhttp.responseText;
	}
}

function loadNativeScript()
{
	var scripts = document.getElementsByTagName("script");
	for (var i = 0; i < scripts.length; i++)
	{
		if (scripts[i].src !== "")
			if (scripts[i].src.indexOf("zelluloza") != -1)
				return loadScriptText(scripts[i].src);
	}
}

var wait_for_text = function ()
{
	var text = document.getElementById("bookpgm");
	if (null === books)
		alert('No copyable text found!');
	else
	{
		for (var i = 0; i < books.length; i++)
		{
			buttons[i] = document.createElement("INPUT");
			buttons[i].setAttribute("type", "button");
			buttons[i].setAttribute("value", 'Скачать в fb2');
			buttons[i].setAttribute("ref", books[i].href);
			buttons[i].addEventListener('click', AllBook, true);
			books[i].parentNode.insertBefore(buttons[i], books[i]);
		}
	}

	if (null !== text)
		if (text.innerHTML.length > 100)
		{
			var button = document.createElement("BUTTON");
			button.value = 'Скачать в fb2';

			button.addEventListener('click', function ()
			{
				unprotect(text);
			}, true);
			text.parentNode.insertBefore(button, text);
			var MaxProtection = my_getbyid("protected1").src !== '';

			if (MaxProtection)
			{
				var button2 = document.createElement("BUTTON");
				button2.innerHTML = 'Скачать в pdf';
				button2.addEventListener('click', function ()
				{
					unprotect(text, "pdf");
				}, true);
				text.parentNode.insertBefore(button2, text);
			}
		}
		else
			window.setTimeout("wait_for_text()", 100);
};

eval(loadNativeScript());
eval(loadScriptText("https://cdn.rawgit.com/eligrey/FileSaver.js/master/FileSaver.min.js"));
eval(loadScriptText("https://greasyfork.org/scripts/15924-jspdf/code/jsPDF.js?version=99137"));

var books = document.getElementsByClassName("booklnk4");
var buttons = new Array();
window.setTimeout("wait_for_text()", 100);