Files
core/Fb2File/Fb2File.cpp
Куликова Светлана Александровна 8df6583150 started writing fb2 in docx
2020-07-07 18:47:33 +03:00

1222 lines
41 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "Fb2File.h"
#include "../DesktopEditor/xml/include/xmlutils.h"
#include "../DesktopEditor/common/Base64.h"
#include "../DesktopEditor/common/File.h"
#include "../DesktopEditor/common/Directory.h"
#include <vector>
#include <map>
// Информация об авторе книги. Тэг author, translator
struct SAuthor
{
std::wstring first_name;
std::wstring middle_name;
std::wstring last_name;
std::wstring nickname;
std::vector<std::wstring> home_page;
std::vector<std::wstring> email;
std::wstring id;
};
// Описание информации о произведении. Тэг title-info, src-title-info
struct STitleInfo
{
std::vector<std::wstring> m_arGenres; // Жанры
std::vector<SAuthor> m_arAuthors; // Авторы
std::vector<SAuthor> m_arTranslator; // Переводчики
std::wstring m_sBookTitle; // Название
std::wstring m_sLang; // Язык после перевода
std::wstring* m_pAnnotation; // Аннотация (ФОРМАТИРОВАННЫЙ ТЕКСТ)
std::wstring* m_pKeywords; // Ключевые слова
std::pair<std::wstring, std::wstring>* m_pDate; // Дата
std::wstring* m_pCoverpage; // Обложка
std::wstring* m_pSrcLang; // Язык до перевода
std::map<std::wstring, std::wstring> m_mSequence; // Серии книг
STitleInfo()
{
m_pAnnotation = NULL;
m_pKeywords = NULL;
m_pDate = NULL;
m_pCoverpage = NULL;
m_pSrcLang = NULL;
}
~STitleInfo()
{
m_arGenres.clear();
m_arAuthors.clear();
m_arTranslator.clear();
m_mSequence.clear();
RELEASEARRAYOBJECTS(m_pAnnotation);
RELEASEARRAYOBJECTS(m_pKeywords);
RELEASEARRAYOBJECTS(m_pDate);
RELEASEARRAYOBJECTS(m_pCoverpage);
RELEASEARRAYOBJECTS(m_pSrcLang);
}
};
// Описание информации о fb2-документе. Тэг document-info
struct SDocumentInfo
{
std::vector<SAuthor> m_arAuthors; // Авторы
std::vector<std::wstring> m_arSrcUrl; // URL страницы
std::pair<std::wstring, std::wstring> m_pDate; // Дата
std::wstring m_sId; // Идентификатор
std::wstring m_sVersion; // Версия документа
std::wstring* m_pProgramUsed; // Использованные программы
std::wstring* m_pSrcOcr; // Автор текста
std::wstring* m_pHistory; // История (ФОРМАТИРОВАННЫЙ ТЕКСТ)
SDocumentInfo()
{
m_pProgramUsed = NULL;
m_pSrcOcr = NULL;
m_pHistory = NULL;
}
~SDocumentInfo()
{
m_arAuthors.clear();
m_arSrcUrl.clear();
RELEASEARRAYOBJECTS(m_pProgramUsed);
RELEASEARRAYOBJECTS(m_pSrcOcr);
RELEASEARRAYOBJECTS(m_pHistory);
}
};
// Информация о бумажном издании. Тэг publish-info
struct SPublishInfo
{
std::wstring* m_pBookName; // Название
std::wstring* m_pPublisher; // Издательство
std::wstring* m_pCity; // Место
std::wstring* m_pYear; // Год
std::wstring* m_pIsbn; // ISBN
std::map<std::wstring, std::wstring> m_mSequence; // Серии книг
SPublishInfo()
{
m_pBookName = NULL;
m_pPublisher = NULL;
m_pCity = NULL;
m_pYear = NULL;
m_pIsbn = NULL;
}
~SPublishInfo()
{
m_mSequence.clear();
RELEASEARRAYOBJECTS(m_pBookName);
RELEASEARRAYOBJECTS(m_pPublisher);
RELEASEARRAYOBJECTS(m_pCity);
RELEASEARRAYOBJECTS(m_pYear);
RELEASEARRAYOBJECTS(m_pIsbn);
}
};
class CFb2File_Private
{
public:
XmlUtils::CXmlLiteReader m_oLightReader; // SAX Reader
std::wstring m_sFile; // Имя файла
std::wstring m_sDstFolder; // Путь к результату
std::wstring m_sBody; // Текст
STitleInfo m_oTitleInfo; // Данные о книге
SDocumentInfo m_oDocumentInfo; // Информация об fb2-документе
NSFile::CFileBinary m_oDocumentXmlWriter; // Файл document.xml
STitleInfo* m_pSrcTitleInfo; // Данные об исходнике книги
SPublishInfo* m_pPublishInfo; // Сведения об издании книги
std::map<std::wstring, std::wstring> m_mXmlns; // Ссылки
std::map<std::wstring, std::wstring> m_mImage; // Картинки
std::map<std::wstring, std::wstring> m_mCustomInfo; // Произвольная информация
public:
CFb2File_Private()
{
m_pSrcTitleInfo = NULL;
}
~CFb2File_Private()
{
m_oLightReader.Clear();
m_mXmlns.clear();
m_mImage.clear();
if(m_pSrcTitleInfo)
delete m_pSrcTitleInfo;
}
// Читает и проверят соответствует ли текущий раздел ожиданиям
bool isSection(const std::wstring& sName)
{
if(!m_oLightReader.ReadNextNode())
return false;
if(m_oLightReader.GetName() != sName)
return false;
return true;
}
// Читает поля автора
bool getAuthor(std::vector<SAuthor>& arAuthor)
{
SAuthor oAuthor;
int nDepth = m_oLightReader.GetDepth();
while(m_oLightReader.ReadNextSiblingNode(nDepth))
{
std::wstring sName = m_oLightReader.GetName();
if(sName == L"first-name")
oAuthor.first_name = content();
else if(sName == L"middle-name")
oAuthor.middle_name = content();
else if(sName == L"last-name")
oAuthor.last_name = content();
else if(sName == L"nickname")
oAuthor.nickname = content();
else if(sName == L"home-page")
oAuthor.home_page.push_back(content());
else if(sName == L"email")
oAuthor.email.push_back(content());
else if(sName == L"id")
oAuthor.id = content();
else
return false;
}
arAuthor.push_back(oAuthor);
return true;
}
// Читает image
bool readImage()
{
return false;
}
// Читает title
bool readTitle(unsigned int nLevel)
{
int nDeath = m_oLightReader.GetDepth();
while(m_oLightReader.ReadNextSiblingNode(nDeath))
{
// Уровень заголовка
std::wstring sLevel = (nLevel == 0) ? L"" : std::to_wstring(nLevel);
if(m_oLightReader.GetName() == L"p")
{
m_oDocumentXmlWriter.WriteStringUTF8(L"<w:p><w:pPr><w:pStyle w:val=\"title" + sLevel + L"\"/></w:pPr>");
if(!readP())
return false;
m_oDocumentXmlWriter.WriteStringUTF8(L"</w:p>");
}
else if(m_oLightReader.GetName() == L"empty-line")
m_oDocumentXmlWriter.WriteStringUTF8(L"<w:p><w:pPr><w:pStyle w:val=\"title" + sLevel + L"\"/></w:pPr></w:p>");
else
return false;
}
return true;
}
// Читает epigraph
bool readEpigraph()
{
m_sBody += L"epigraph\n";
int nDeath = m_oLightReader.GetDepth();
while(m_oLightReader.ReadNextSiblingNode(nDeath))
{
std::wstring sName = m_oLightReader.GetName();
if(sName == L"p")
{
if(!readP())
return false;
}
else if(sName == L"poem")
{
if(!readPoem())
return false;
}
else if(sName == L"cite")
{
if(!readCite())
return false;
}
else if(sName == L"empty-line")
m_sBody += L"\n";
else if(sName == L"text-author")
break;
else
return false;
}
// Читаем text-author (любое)
if(m_oLightReader.GetName() == L"text-author")
{
do
{
if(m_oLightReader.GetName() != L"text-author")
return false;
m_sBody += L"text-author\n";
if(!readP())
return false;
} while(m_oLightReader.ReadNextSiblingNode(nDeath));
}
return true;
}
// Читает p
bool readP()
{
// Читаем id, style, xml:lang
/*
while(m_oLightReader.MoveToNextAttribute())
m_sBody += L"\t" + m_oLightReader.GetName() + L" " + m_oLightReader.GetText() + L"\n";
m_oLightReader.MoveToElement();
*/
m_oDocumentXmlWriter.WriteStringUTF8(L"<w:r>");
int nDepth = m_oLightReader.GetDepth();
while(m_oLightReader.ReadNextSiblingNode2(nDepth))
{
std::wstring sName = m_oLightReader.GetName();
// Читаем обычный текст
if(sName == L"#text")
m_oDocumentXmlWriter.WriteStringUTF8(L"<w:t>" + m_oLightReader.GetText() + L"</w:t>");
// Читаем полужирный текст
else if (sName == L"strong")
{
m_oDocumentXmlWriter.WriteStringUTF8(L"<w:rPr><w:b/></w:rPr>");
if(!readP())
return false;
}
// Читаем курсивный текст
else if(sName == L"emphasis")
{
m_oDocumentXmlWriter.WriteStringUTF8(L"<w:rPr><w:i/></w:rPr>");
if(!readP())
return false;
}
// Читаем стилизованный текст
else if(sName == L"style")
{
m_sBody += L"style\n";
if(!readP())
return false;
}
// Читаем ссылку
else if(sName == L"a")
{
m_sBody += L"a\n";
if(!readP())
return false;
}
else if(sName == L"strikethrough")
{
m_sBody += L"strikethrough\n";
if(!readP())
return false;
}
else if(sName == L"sub")
{
m_sBody += L"sub\n";
if(!readP())
return false;
}
else if(sName == L"sup")
{
m_sBody += L"sup\n";
if(!readP())
return false;
}
else if(sName == L"code")
{
m_sBody += L"code\n";
return readP();
}
else if(sName == L"image")
{
m_sBody += L"image\n";
while(m_oLightReader.MoveToNextAttribute())
m_sBody += L"\t" + m_oLightReader.GetName() + L" " + m_oLightReader.GetText() + L"\n";
}
else
return false;
}
m_oDocumentXmlWriter.WriteStringUTF8(L"</w:r>");
return true;
}
// Читает poem
bool readPoem()
{
m_sBody += L"poem\n";
while(m_oLightReader.MoveToNextAttribute())
m_sBody += L"\t" + m_oLightReader.GetName() + L" " + m_oLightReader.GetText() + L"\n";
if(!m_oLightReader.ReadNextNode())
return false;
// Читаем title (ноль или один)
if(m_oLightReader.GetName() == L"title")
{
if(!readTitle(0))
return false;
if(!m_oLightReader.ReadNextNode())
return false;
}
// Читаем epigraph (любое)
if(m_oLightReader.GetName() == L"epigraph")
{
do
{
if(!readEpigraph())
return false;
} while(isSection(L"epigraph"));
}
// Читаем stanza (один или более)
if(m_oLightReader.GetName() != L"stanza")
return false;
int nDeath = m_oLightReader.GetDepth() - 1;
do
{
if(m_oLightReader.GetName() != L"stanza")
break;
// Читаем title (ноль или один)
if(isSection(L"title"))
{
if(!readTitle(0))
return false;
if(!m_oLightReader.ReadNextNode())
return false;
}
// Читаем subtitle (ноль или один)
if(m_oLightReader.GetName() == L"subtitle")
{
m_sBody += L"subtitle\n";
if(!readP())
return false;
if(!m_oLightReader.ReadNextNode())
return false;
}
// Читаем v (один или более)
if(m_oLightReader.GetName() != L"v")
return false;
int nVDeath = m_oLightReader.GetDepth() - 1;
do
{
if(m_oLightReader.GetName() != L"v")
return false;
m_sBody += L"v\n";
if(!readP())
return false;
} while(m_oLightReader.ReadNextSiblingNode(nVDeath));
} while(m_oLightReader.ReadNextSiblingNode(nDeath));
// Читаем text-author (любое)
if(m_oLightReader.GetName() == L"text-author")
{
do
{
if(m_oLightReader.GetName() != L"text-author")
break;
m_sBody += L"text-author\n";
if(!readP())
return false;
} while(m_oLightReader.ReadNextSiblingNode(nDeath));
}
// Читаем date (ноль или один)
if(m_oLightReader.GetName() == L"date")
{
m_sBody += L"date\n";
while(m_oLightReader.MoveToNextAttribute())
m_sBody += L"\t" + m_oLightReader.GetName() + L" " + m_oLightReader.GetText() + L"\n";
m_oLightReader.MoveToElement();
}
return true;
}
// Читает cite
bool readCite()
{
m_sBody += L"cite\n";
int nDeath = m_oLightReader.GetDepth();
while(m_oLightReader.ReadNextSiblingNode(nDeath))
{
std::wstring sName = m_oLightReader.GetName();
if(sName == L"p")
{
if(!readP())
return false;
}
else if(sName == L"subtitle")
{
m_sBody += L"subtitle\n";
if(!readP())
return false;
}
else if(sName == L"empty-line")
m_sBody += L"\n";
else if(sName == L"poem")
{
if(!readPoem())
return false;
}
else if(sName == L"table")
{
if(!readTable())
return false;
}
else if(sName == L"text-author")
break;
else
return false;
}
// Читаем text-author (любое)
if(m_oLightReader.GetName() == L"text-author")
{
do
{
if(m_oLightReader.GetName() != L"text-author")
return false;
m_sBody += L"text-author\n";
if(!readP())
return false;
} while(m_oLightReader.ReadNextSiblingNode(nDeath));
}
return true;
}
// Читает table
bool readTable()
{
m_sBody += L"table\n";
while(m_oLightReader.MoveToNextAttribute())
m_sBody += L"\t" + m_oLightReader.GetName() + L" " + m_oLightReader.GetText() + L"\n";
m_oLightReader.MoveToElement();
int nDeath = m_oLightReader.GetDepth();
if(!m_oLightReader.ReadNextSiblingNode(nDeath))
return false;
// Читаем tr (один или более)
if(m_oLightReader.GetName() != L"tr")
return false;
do
{
if(m_oLightReader.GetName() != L"tr")
return false;
m_sBody += L"tr\n";
int nTrDeath = m_oLightReader.GetDepth();
while(m_oLightReader.ReadNextSiblingNode(nTrDeath))
{
// Читаем th (любое)
if(m_oLightReader.GetName() == L"th")
{
m_sBody += L"th\n";
if(!readP())
return false;
}
// Читаем td (любое)
else if(m_oLightReader.GetName() == L"td")
{
m_sBody += L"td\n";
if(!readP())
return false;
}
else
return false;
}
} while(m_oLightReader.ReadNextSiblingNode(nDeath));
return true;
}
// Читает section
bool readSection()
{
m_sBody += L"section\n";
while(m_oLightReader.MoveToNextAttribute())
m_sBody += L"\t" + m_oLightReader.GetName() + L" " + m_oLightReader.GetText() + L"\n";
if(!m_oLightReader.ReadNextNode())
return false;
// Читаем title (ноль или один)
if(m_oLightReader.GetName() == L"title")
{
if(!readTitle(0))
return false;
if(!m_oLightReader.ReadNextNode())
return false;
}
// Читаем epigraph (любое)
if(m_oLightReader.GetName() == L"epigraph")
{
do
{
if(!readEpigraph())
return false;
} while(isSection(L"epigraph"));
}
// Читаем image (ноль или один)
if(m_oLightReader.GetName() == L"image")
{
m_sBody += L"image\n";
while(m_oLightReader.MoveToNextAttribute())
m_sBody += L"\t" + m_oLightReader.GetName() + L" " + m_oLightReader.GetText() + L"\n";
if(!m_oLightReader.ReadNextNode())
return false;
}
// Читаем annotation (ноль или один)
if(m_oLightReader.GetName() == L"annotation")
{
m_sBody += L"annotation\n";
int nDeath = m_oLightReader.GetDepth();
while(m_oLightReader.ReadNextSiblingNode(nDeath))
{
std::wstring sAnName = m_oLightReader.GetName();
if(sAnName == L"p")
{
if(!readP())
return false;
}
else if(sAnName == L"poem")
{
if(!readPoem())
return false;
}
else if(sAnName == L"cite")
{
if(!readCite())
return false;
}
else if(sAnName == L"subtitle")
{
m_sBody += L"subtitle\n";
if(!readP())
return false;
}
else if(sAnName == L"empty-line")
m_sBody += L"\n";
else if(sAnName == L"table")
{
if(!readTable())
return false;
}
else
return false;
}
if(!m_oLightReader.ReadNextNode())
return false;
}
// Читаем вложенные section (любое)
if(m_oLightReader.GetName() == L"section")
{
int nDeath = m_oLightReader.GetDepth() - 1;
do
{
if(m_oLightReader.GetName() != L"section")
return false;
if(!readSection())
return false;
} while(m_oLightReader.ReadNextSiblingNode(nDeath));
}
// Читаем произвольный набор
else
{
int nDeath = m_oLightReader.GetDepth() - 1;
do
{
std::wstring sName = m_oLightReader.GetName();
if(sName == L"p")
{
if(!readP())
return false;
}
else if(sName == L"image")
{
m_sBody += L"image\n";
while(m_oLightReader.MoveToNextAttribute())
m_sBody += L"\t" + m_oLightReader.GetName() + L" " + m_oLightReader.GetText() + L"\n";
m_oLightReader.MoveToElement();
}
else if(sName == L"poem")
{
if(!readPoem())
return false;
}
else if(sName == L"subtitle")
{
m_sBody += L"subtitle\n";
if(!readP())
return false;
}
else if(sName == L"cite")
{
if(!readCite())
return false;
}
else if(sName == L"empty-line")
m_sBody += L"\n";
else if(sName == L"table")
{
if(!readTable())
return false;
}
else
return false;
} while(m_oLightReader.ReadNextSiblingNode(nDeath));
}
return true;
}
// Читает body
bool readBody()
{
m_oDocumentXmlWriter.WriteStringUTF8(L"<w:body>");
int nDeath = m_oLightReader.GetDepth();
if(!m_oLightReader.ReadNextSiblingNode(nDeath))
return false;
// Читаем image (ноль или один)
if(m_oLightReader.GetName() == L"image")
{
if(!readImage())
return false;
if(!m_oLightReader.ReadNextSiblingNode(nDeath))
return false;
}
// Читаем title (ноль или один)
if(m_oLightReader.GetName() == L"title")
{
if(!readTitle(0))
return false;
if(!m_oLightReader.ReadNextSiblingNode(nDeath))
return false;
}
// Читаем epigraph (любое)
if(m_oLightReader.GetName() == L"epigraph")
{
do
{
if(!readEpigraph())
return false;
} while(isSection(L"epigraph"));
}
// Читаем section (один или более)
if(m_oLightReader.GetName() != L"section")
return false;
do
{
if(m_oLightReader.GetName() != L"section")
return false;
if(!readSection())
return false;
} while(m_oLightReader.ReadNextSiblingNode(nDeath));
m_oDocumentXmlWriter.WriteStringUTF8(L"<w:sectPr><w:footnotePr/><w:type w:val=\"nextPage\"/><w:pgSz w:w=\"11906\" w:h=\"16838\" w:orient=\"portrait\"/><w:pgMar w:top=\"1134\" w:right=\"850\" w:bottom=\"1134\" w:left=\"1701\" w:header=\"709\" w:footer=\"709\" w:gutter=\"0\"/><w:cols w:num=\"1\" w:sep=\"0\" w:space=\"708\" w:equalWidth=\"1\"/><w:docGrid w:linePitch=\"360\"/></w:sectPr></w:body>");
return true;
}
// Читает custom-info
bool getCustomInfo()
{
if(!m_oLightReader.MoveToNextAttribute())
return false;
std::wstring sIntoType = m_oLightReader.GetText();
if(!m_oLightReader.MoveToElement())
return false;
std::wstring sCustomInfo = content();
if(sCustomInfo == L"")
return false;
m_mCustomInfo.insert(std::make_pair(sIntoType, sCustomInfo));
}
// Читает publish-info
bool getPublishInfo()
{
// Читаем до body
while(!isSection(L"body"))
{
if(m_oLightReader.GetDepth() == 0)
return false;
std::wstring sName = m_oLightReader.GetName();
// Читаем book-name (ноль или один)
if(sName == L"book-name")
{
if(m_pPublishInfo->m_pBookName)
return false;
m_pPublishInfo->m_pBookName = new std::wstring[1];
*m_pPublishInfo->m_pBookName = content();
}
// Читаем publisher (ноль или один)
else if(sName == L"publisher")
{
if(m_pPublishInfo->m_pPublisher)
return false;
m_pPublishInfo->m_pPublisher = new std::wstring[1];
*m_pPublishInfo->m_pPublisher = content();
}
// Читаем city (ноль или один)
else if(sName == L"city")
{
if(m_pPublishInfo->m_pCity)
return false;
m_pPublishInfo->m_pCity = new std::wstring[1];
*m_pPublishInfo->m_pCity = content();
}
// Читаем year (ноль или один)
else if(sName == L"year")
{
if(m_pPublishInfo->m_pYear)
return false;
m_pPublishInfo->m_pYear = new std::wstring[1];
*m_pPublishInfo->m_pYear = content();
}
// Читаем isbn (ноль или один)
else if(sName == L"isbn")
{
if(m_pPublishInfo->m_pIsbn)
return false;
m_pPublishInfo->m_pIsbn = new std::wstring[1];
*m_pPublishInfo->m_pIsbn = content();
}
// Читаем sequence (любое)
else if(sName == L"sequence")
{
if(!m_oLightReader.MoveToNextAttribute())
return false;
std::wstring sSName = m_oLightReader.GetText();
std::wstring sSNumber = L"";
if(m_oLightReader.MoveToNextAttribute())
sSNumber = m_oLightReader.GetText();
m_pPublishInfo->m_mSequence.insert(std::make_pair(sSName, sSNumber));
}
else if(sName == L"custom-info")
{
break;
}
}
return true;
}
// Читает document-info
bool getDocumentInfo()
{
// Читаем author (один или более)
if(!isSection(L"author"))
return false;
do
{
if(!getAuthor(m_oDocumentInfo.m_arAuthors))
return false;
} while(isSection(L"author"));
// Читаем program-used (ноль или один)
if(m_oLightReader.GetName() == L"program-used")
{
m_oDocumentInfo.m_pProgramUsed = new std::wstring[1];
*m_oDocumentInfo.m_pProgramUsed = content();
}
// Читаем date
if(m_oLightReader.GetName() != L"date")
if(!isSection(L"date"))
return false;
std::wstring sDate = L"";
if(m_oLightReader.MoveToNextAttribute())
{
sDate = m_oLightReader.GetText();
m_oLightReader.MoveToElement();
}
m_oDocumentInfo.m_pDate = make_pair(sDate, content());
// Читаем до id
while(!isSection(L"id"))
{
if(m_oLightReader.GetDepth() == 0)
return false;
std::wstring sName = m_oLightReader.GetName();
// Читаем src-url (любое)
if(sName == L"src-url")
{
m_oDocumentInfo.m_arSrcUrl.push_back(content());
}
// Читаем src-ocr (ноль или один)
else if(sName == L"src-ocr")
{
if(m_oDocumentInfo.m_pSrcOcr)
return false;
m_oDocumentInfo.m_pSrcOcr = new std::wstring[1];
*m_oDocumentInfo.m_pSrcOcr = content();
}
}
// Читаем id
if(m_oLightReader.GetName() != L"id")
return false;
m_oDocumentInfo.m_sId = content();
// Читаем version
if(!isSection(L"version"))
return false;
m_oDocumentInfo.m_sVersion = content();
// Читаем до body
while(!isSection(L"body"))
{
if(m_oLightReader.GetDepth() == 0)
return false;
std::wstring sName = m_oLightReader.GetName();
// Читаем history (ноль или один)
if(sName == L"history")
{
// Содержит форматированный текст - НЕ РЕАЛИЗОВАНО
if(m_oDocumentInfo.m_pHistory)
return false;
m_oDocumentInfo.m_pHistory = new std::wstring[1];
*m_oDocumentInfo.m_pHistory = L"";
int nDepth = m_oLightReader.GetDepth();
while(m_oLightReader.ReadNextSiblingNode(nDepth))
{
*m_oDocumentInfo.m_pHistory += content();
}
}
else if(sName == L"publish-info")
{
break;
}
else if(sName == L"custom-info")
{
break;
}
}
return true;
}
// Читает title-info и src-title-info
bool getTitleInfo(STitleInfo& oTitleInfo)
{
// Читаем genre (один или более)
if(!isSection(L"genre"))
return false;
do
{
oTitleInfo.m_arGenres.push_back(content());
} while(isSection(L"genre"));
// Читаем author (один или более)
if(m_oLightReader.GetName() != L"author")
return false;
do
{
if(!getAuthor(oTitleInfo.m_arAuthors))
return false;
} while(isSection(L"author"));
// Читаем book-title
if(m_oLightReader.GetName() != L"book-title")
return false;
oTitleInfo.m_sBookTitle = content();
// Читаем до lang
while(!isSection(L"lang"))
{
if(m_oLightReader.GetDepth() == 0)
return false;
std::wstring sName = m_oLightReader.GetName();
// Читаем annotation (ноль или один)
if(sName == L"annotation")
{
// Содержит форматированный текст - НЕ РЕАЛИЗОВАНО
if(oTitleInfo.m_pAnnotation)
return false;
oTitleInfo.m_pAnnotation = new std::wstring[1];
*oTitleInfo.m_pAnnotation = L"";
int nDepth = m_oLightReader.GetDepth();
while(m_oLightReader.ReadNextSiblingNode(nDepth))
{
*oTitleInfo.m_pAnnotation += content();
}
}
// Читаем keywords (ноль или один)
else if(sName == L"keywords")
{
if(oTitleInfo.m_pKeywords)
return false;
oTitleInfo.m_pKeywords = new std::wstring[1];
*oTitleInfo.m_pKeywords = content();
}
// Читаем date (ноль или один)
else if(sName == L"date")
{
if(oTitleInfo.m_pDate)
return false;
oTitleInfo.m_pDate = new std::pair<std::wstring, std::wstring>[1];
std::wstring sDate = L"";
if(m_oLightReader.MoveToNextAttribute())
{
sDate = m_oLightReader.GetText();
m_oLightReader.MoveToElement();
}
*oTitleInfo.m_pDate = make_pair(sDate, content());
}
// Читаем coverpage (ноль или один)
else if(sName == L"coverpage")
{
if(oTitleInfo.m_pCoverpage)
return false;
oTitleInfo.m_pCoverpage = new std::wstring[1];
if(!m_oLightReader.ReadNextSiblingNode(m_oLightReader.GetDepth()))
return false;
if(!m_oLightReader.MoveToNextAttribute())
return false;
*oTitleInfo.m_pCoverpage = m_oLightReader.GetText();
m_oLightReader.MoveToElement();
}
}
// Читаем lang
if(m_oLightReader.GetName() != L"lang")
return false;
oTitleInfo.m_sLang = content();
// Читаем до document-info
while(!isSection(L"document-info"))
{
if(m_oLightReader.GetDepth() == 0)
return false;
std::wstring sName = m_oLightReader.GetName();
// Читаем src-lang (ноль или один)
if(sName == L"src-lang")
{
if(oTitleInfo.m_pSrcLang)
return false;
oTitleInfo.m_pSrcLang = new std::wstring[1];
*oTitleInfo.m_pSrcLang = content();
}
// Читаем translator (любое)
else if(sName == L"translator")
{
if(!getAuthor(oTitleInfo.m_arTranslator))
return false;
}
// Читаем sequence (любое)
else if(sName == L"sequence")
{
if(!m_oLightReader.MoveToNextAttribute())
return false;
std::wstring sSName = m_oLightReader.GetText();
std::wstring sSNumber = L"";
if(m_oLightReader.MoveToNextAttribute())
sSNumber = m_oLightReader.GetText();
oTitleInfo.m_mSequence.insert(std::make_pair(sSName, sSNumber));
}
else if(sName == L"src-title-info")
{
break;
}
}
return true;
}
// Возвращает содержание узла
std::wstring content()
{
std::wstring sRes = L"";
if(m_oLightReader.ReadNextSiblingNode2(m_oLightReader.GetDepth()))
sRes = m_oLightReader.GetText();
return sRes;
}
std::string contentA()
{
std::string sRes = "";
if(m_oLightReader.ReadNextSiblingNode2(m_oLightReader.GetDepth()))
sRes = m_oLightReader.GetTextA();
return sRes;
}
};
CFb2File::CFb2File()
{
m_internal = new CFb2File_Private();
}
CFb2File::~CFb2File()
{
RELEASEOBJECT(m_internal);
}
// Проверяет, соответствует ли fb2 файл формату
bool CFb2File::IsFb2File(const std::wstring& sFile)
{
if (!m_internal->m_oLightReader.FromFile(sFile))
return false;
// Читаем FictionBook
if(!m_internal->isSection(L"FictionBook"))
return false;
while(m_internal->m_oLightReader.MoveToNextAttribute())
m_internal->m_mXmlns.insert(std::make_pair(m_internal->m_oLightReader.GetName(), m_internal->m_oLightReader.GetText()));
m_internal->m_sFile = sFile;
return true;
}
// Выставление временной (рабочей) папки
void CFb2File::SetTmpDirectory(const std::wstring& sFolder)
{
m_internal->m_sDstFolder = sFolder;
}
// Функция для теста. Возвращает содержание body
std::wstring CFb2File::GetText()
{
return m_internal->m_sBody;
}
// Проверяет, соответствует ли fb2 файл формату
// sPath - путь к сохраненному файлу, sDirectory - путь к сохраненным картинкам
int CFb2File::Convert(const std::wstring& sPath, const std::wstring& sDirectory)
{
// Читаем description
if(!m_internal->isSection(L"description"))
return false;
// Читаем title-info
if(!m_internal->isSection(L"title-info"))
return false;
if(!m_internal->getTitleInfo(m_internal->m_oTitleInfo))
return false;
// Читаем src-title-info (ноль или один)
if(m_internal->m_oLightReader.GetName() == L"src-title-info")
{
m_internal->m_pSrcTitleInfo = new STitleInfo();
if(!m_internal->getTitleInfo(*m_internal->m_pSrcTitleInfo))
return false;
}
// Читаем document-info
if(m_internal->m_oLightReader.GetName() != L"document-info")
return false;
if(!m_internal->getDocumentInfo())
return false;
// Читаем publish-info (ноль или один)
if(m_internal->m_oLightReader.GetName() == L"publish-info")
{
m_internal->m_pPublishInfo = new SPublishInfo();
if(!m_internal->getPublishInfo())
return false;
}
// Читаем custom-info (любое)
if(m_internal->m_oLightReader.GetName() == L"custom-info")
{
do
{
if(!m_internal->getCustomInfo())
return false;
} while(m_internal->isSection(L"custom-info"));
}
// Создаем файл для записи
if (!m_internal->m_oDocumentXmlWriter.CreateFileW(sDirectory + L"/document.xml"))
return false;
m_internal->m_oDocumentXmlWriter.WriteStringUTF8(L"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><w:document xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:wp14=\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\" xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" xmlns:w10=\"urn:schemas-microsoft-com:office:word\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\" xmlns:w15=\"http://schemas.microsoft.com/office/word/2012/wordml\" xmlns:wpg=\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\" xmlns:wpi=\"http://schemas.microsoft.com/office/word/2010/wordprocessingInk\" xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" xmlns:wne=\"http://schemas.microsoft.com/office/word/2006/wordml\" xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\" mc:Ignorable=\"w14 w15 wp14\">");
// Читаем body
if(m_internal->m_oLightReader.GetName() != L"body")
return false;
do
{
if(!m_internal->readBody())
return false;
} while(m_internal->isSection(L"body"));
// Закрываем файл для записи
m_internal->m_oDocumentXmlWriter.WriteStringUTF8(L"</w:document>");
m_internal->m_oDocumentXmlWriter.CloseFile();
std::wstring sMediaDirectory = sDirectory + L"/media";
NSDirectory::CreateDirectory(sMediaDirectory);
while(m_internal->m_oLightReader.ReadNextNode())
{
// Читает картинки
if(m_internal->m_oLightReader.GetName() == L"binary")
{
std::wstring sId;
std::wstring sContentType;
// Читает первый атрибут
if(!m_internal->m_oLightReader.MoveToNextAttribute())
return false;
std::wstring sName = m_internal->m_oLightReader.GetName();
// Читает id
if(sName == L"id")
sId = m_internal->m_oLightReader.GetText();
// Читает content-type
else if(sName == L"content-type")
sContentType = m_internal->m_oLightReader.GetText();
else
return false;
// Читает второй атрибут
if(!m_internal->m_oLightReader.MoveToNextAttribute())
return false;
sName = m_internal->m_oLightReader.GetName();
// Читает id
if(sName == L"id")
sId = m_internal->m_oLightReader.GetText();
// Читает content-type
else if(sName == L"content-type")
sContentType = m_internal->m_oLightReader.GetText();
else
return false;
m_internal->m_mImage.insert(std::make_pair(sId, sContentType));
m_internal->m_oLightReader.MoveToElement();
// Пишет картинку в файл
NSFile::CFileBinary oImageWriter;
if (!oImageWriter.CreateFileW(sMediaDirectory + L"/" + sId))
return false;
std::string sBase64 = m_internal->contentA();
int nSrcLen = (int)sBase64.length();
int nDecodeLen = NSBase64::Base64DecodeGetRequiredLength(nSrcLen);
BYTE* pImageData = new BYTE[nDecodeLen];
if (TRUE == NSBase64::Base64Decode(sBase64.c_str(), nSrcLen, pImageData, &nDecodeLen))
oImageWriter.WriteFile(pImageData, (DWORD)nDecodeLen);
RELEASEARRAYOBJECTS(pImageData);
oImageWriter.CloseFile();
}
}
return TRUE;
}