Zelluloza Dumper

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

当前为 2017-11-02 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Zelluloza Dumper
// @version      0.7
// @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);
	}
}

unsafeWindow.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);