summaryrefslogtreecommitdiff
path: root/shared/xml_base.cpp
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:11:56 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:11:56 +0200
commit98ecf620f7de377dc8ae9ad7fbd1e3b24477e138 (patch)
treefaadc6d8822c20cd3bc6f50b2a98e6c580585949 /shared/xml_base.cpp
parent3.16 (diff)
downloadFreeFileSync-98ecf620f7de377dc8ae9ad7fbd1e3b24477e138.tar.gz
FreeFileSync-98ecf620f7de377dc8ae9ad7fbd1e3b24477e138.tar.bz2
FreeFileSync-98ecf620f7de377dc8ae9ad7fbd1e3b24477e138.zip
3.17
Diffstat (limited to 'shared/xml_base.cpp')
-rw-r--r--shared/xml_base.cpp190
1 files changed, 60 insertions, 130 deletions
diff --git a/shared/xml_base.cpp b/shared/xml_base.cpp
index 3f2a9e48..efed738a 100644
--- a/shared/xml_base.cpp
+++ b/shared/xml_base.cpp
@@ -9,30 +9,10 @@
#include "i18n.h"
#include "string_conv.h"
#include "system_constants.h"
-#include <boost/scoped_array.hpp>
#include "file_handling.h"
-using namespace ffs3;
-
-
-std::string getTypeName(xmlAccess::XmlType type)
-{
- switch (type)
- {
- case xmlAccess::XML_GUI_CONFIG:
- return "GUI";
- case xmlAccess::XML_BATCH_CONFIG:
- return "BATCH";
- case xmlAccess::XML_GLOBAL_SETTINGS:
- return "GLOBAL";
- case xmlAccess::XML_REAL_CONFIG:
- return "REAL";
- case xmlAccess::XML_OTHER:
- break;
- }
- assert(false);
- return "OTHER";
-}
+using namespace zen;
+using namespace xmlAccess;
namespace
@@ -44,9 +24,9 @@ void normalize(std::vector<char>& stream)
for (std::vector<char>::const_iterator i = stream.begin(); i != stream.end(); ++i)
switch (*i)
{
- case 0xD:
- tmp.push_back(0xA);
- if (i + 1 != stream.end() && *(i + 1) == 0xA)
+ case '\xD':
+ tmp.push_back('\xA');
+ if (i + 1 != stream.end() && *(i + 1) == '\xA')
++i;
break;
default:
@@ -57,105 +37,55 @@ void normalize(std::vector<char>& stream)
}
-void loadRawXmlDocument(const wxString& filename, TiXmlDocument& document) //throw XmlError()
+void parseRawXmlDocument(const wxString& filename, TiXmlDocument& document) //throw XmlError()
{
- using xmlAccess::XmlError;
-
- const size_t BUFFER_SIZE = 2 * 1024 * 1024; //maximum size of a valid FreeFileSync XML file!
-
- std::vector<char> inputBuffer;
- inputBuffer.resize(BUFFER_SIZE);
+ const zen::UInt64 fs = zen::getFilesize(wxToZ(filename));
try
{
+ {
+ //quick test whether input is an XML: avoid loading large binary files up front!
+ std::string xmlBegin = "<?xml version=";
+ std::vector<char> buffer(xmlBegin.size());
+
+ FileInput inputFile(wxToZ(filename)); //throw (FileError);
+ const size_t bytesRead = inputFile.read(&buffer[0], buffer.size()); //throw (FileError)
+ if (bytesRead < xmlBegin.size() || !std::equal(buffer.begin(), buffer.end(), xmlBegin.begin()))
+ throw XmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + filename + wxT("\""));
+ }
+
+ std::vector<char> buffer(to<size_t>(fs) + 1); //inc. null-termination (already set!)
+
FileInput inputFile(wxToZ(filename)); //throw (FileError);
- const size_t bytesRead = inputFile.read(&inputBuffer[0], inputBuffer.size()); //throw (FileError)
+ const size_t bytesRead = inputFile.read(&buffer[0], to<size_t>(fs)); //throw (FileError)
+ if (bytesRead < to<size_t>(fs))
+ {
+ wxString errorMessage = wxString(_("Error reading file:")) + wxT("\n\"") + filename + wxT("\"");
+ throw XmlError(errorMessage + wxT("\n\n"));
+ }
- if (bytesRead == 0 || bytesRead >= inputBuffer.size()) //treat XML files larger than 2 MB as erroneous: loading larger files just wastes CPU + memory
- throw XmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + filename + wxT("\""));
+ //convert (0xD, 0xA) and (0xD) to (0xA): just like in TiXmlDocument::LoadFile(); not sure if actually needed
+ normalize(buffer);
- inputBuffer.resize(bytesRead + 1);
- inputBuffer[bytesRead] = 0; //set null-termination!!!!
+ document.Parse(&buffer[0], 0, TIXML_ENCODING_UTF8); //respect null-termination!
}
catch (const FileError& error) //more detailed error messages than with wxWidgets
{
throw XmlError(error.msg());
}
-
- //convert (0xD, 0xA) and (0xD) to (0xA): just like in TiXmlDocument::LoadFile(); not sure if actually needed
- normalize(inputBuffer);
-
- document.Parse(&inputBuffer[0], 0, TIXML_DEFAULT_ENCODING); //respect null-termination!
-
- TiXmlElement* root = document.RootElement();
-
- if (root && (root->ValueStr() == std::string("FreeFileSync"))) //check for FFS configuration xml
- return; //finally... success!
-
- throw XmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + filename + wxT("\""));
}
}
-xmlAccess::XmlType xmlAccess::getXmlType(const wxString& filename) //throw()
-{
- try
- {
- TiXmlDocument doc;
- ::loadRawXmlDocument(filename, doc); //throw XmlError()
-
- TiXmlElement* root = doc.RootElement();
- if (root)
- {
- const char* cfgType = root->Attribute("XmlType");
- if (cfgType)
- {
- const std::string type(cfgType);
-
- if (type == getTypeName(XML_GUI_CONFIG))
- return XML_GUI_CONFIG;
- else if (type == getTypeName(XML_BATCH_CONFIG))
- return XML_BATCH_CONFIG;
- else if (type == getTypeName(XML_GLOBAL_SETTINGS))
- return XML_GLOBAL_SETTINGS;
- else if (type == getTypeName(XML_REAL_CONFIG))
- return XML_REAL_CONFIG;
- }
- }
- }
- catch (const XmlError&) {}
-
- return XML_OTHER;
-}
-
-
-void xmlAccess::loadXmlDocument(const wxString& filename, const xmlAccess::XmlType type, TiXmlDocument& document) //throw XmlError()
+void xmlAccess::loadXmlDocument(const wxString& filename, TiXmlDocument& document) //throw XmlError()
{
TiXmlBase::SetCondenseWhiteSpace(false); //do not condense whitespace characters
- ::loadRawXmlDocument(filename, document); //throw XmlError()
+ ::parseRawXmlDocument(filename, document); //throw XmlError()
TiXmlElement* root = document.RootElement();
- if (root)
- {
- const char* cfgType = root->Attribute("XmlType");
- if (cfgType && std::string(cfgType) == getTypeName(type))
- return; //finally... success!
- }
-
- throw XmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + filename + wxT("\""));
-}
-
-
-void xmlAccess::getDefaultXmlDocument(const XmlType type, TiXmlDocument& document)
-{
- TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "UTF-8", ""); //delete won't be necessary later; ownership passed to TiXmlDocument!
- document.LinkEndChild(decl);
-
- TiXmlElement* root = new TiXmlElement("FreeFileSync");
- root->SetAttribute("XmlType", getTypeName(type)); //xml configuration type
-
- document.LinkEndChild(root);
+ if (!root)
+ throw XmlError(wxString(_("Error parsing configuration file:")) + wxT("\n\"") + filename + wxT("\""));
}
@@ -165,18 +95,18 @@ bool saveNecessary(const Zstring& filename, const std::string& dataToWrite) //th
{
try
{
- if (ffs3::getFilesize(filename) != static_cast<unsigned long>(dataToWrite.size())) //throw (FileError);
+ if (zen::getFilesize(filename) != static_cast<unsigned long>(dataToWrite.size())) //throw (FileError);
return true;
- boost::scoped_array<char> inputBuffer(new char[dataToWrite.size() + 1]); //+ 1 in order to test for end of file!
+ std::vector<char> inputBuffer(dataToWrite.size() + 1); //+ 1 in order to test for end of file!
FileInput inputFile(filename); //throw (FileError);
- const size_t bytesRead = inputFile.read(inputBuffer.get(), dataToWrite.size() + 1); //throw (FileError)
+ const size_t bytesRead = inputFile.read(&inputBuffer[0], inputBuffer.size()); //throw (FileError)
if (bytesRead != dataToWrite.size()) //implicit test for eof!
return true;
- return ::memcmp(inputBuffer.get(), dataToWrite.c_str(), dataToWrite.size()) != 0;
+ return ::memcmp(&inputBuffer[0], dataToWrite.c_str(), dataToWrite.size()) != 0;
}
catch (const FileError&)
{
@@ -260,21 +190,21 @@ bool xmlAccess::readXmlElement(const std::string& name, const TiXmlElement* pare
{
if (parent)
{
- output.clear();
-
//load elements
- const TiXmlElement* element = parent->FirstChildElement(name);
- while (element)
+ const TiXmlElement* xmlList = parent->FirstChildElement(name);
+ if (xmlList)
{
- const char* text = element->GetText();
- if (text) //may be NULL!!
- output.push_back(wxString::FromUTF8(text));
- else
- output.push_back(wxEmptyString);
-
- element = element->NextSiblingElement();
+ output.clear();
+ for (const TiXmlElement* item = xmlList->FirstChildElement("Item"); item != NULL; item = item->NextSiblingElement())
+ {
+ const char* text = item->GetText();
+ if (text) //may be NULL!!
+ output.push_back(wxString::FromUTF8(text));
+ else
+ output.push_back(wxEmptyString);
+ }
+ return true;
}
- return true;
}
return false;
@@ -351,8 +281,14 @@ void xmlAccess::addXmlElement(const std::string& name, const bool value, TiXmlEl
void xmlAccess::addXmlElement(const std::string& name, const std::vector<wxString>& value, TiXmlElement* parent)
{
- for (std::vector<wxString>::const_iterator i = value.begin(); i != value.end(); ++i)
- addXmlElement(name, std::string(i->ToUTF8()), parent);
+ if (parent)
+ {
+ TiXmlElement* xmlList= new TiXmlElement(name);
+ parent->LinkEndChild(xmlList);
+
+ for (std::vector<wxString>::const_iterator i = value.begin(); i != value.end(); ++i)
+ addXmlElement("Item", std::string(i->ToUTF8()), xmlList);
+ }
}
@@ -378,21 +314,15 @@ void xmlAccess::addXmlAttribute(const std::string& name, const bool value, TiXml
}
-using xmlAccess::XmlParser;
+using xmlAccess::XmlErrorLogger;
-void XmlParser::logError(const std::string& nodeName)
+void XmlErrorLogger::logError(const std::string& nodeName)
{
failedNodes.push_back(wxString::FromUTF8(nodeName.c_str()));
}
-bool XmlParser::errorsOccurred() const
-{
- return !failedNodes.empty();
-}
-
-
-const wxString XmlParser::getErrorMessageFormatted() const
+const wxString XmlErrorLogger::getErrorMessageFormatted() const
{
wxString errorMessage = wxString(_("Could not read values for the following XML nodes:")) + wxT("\n");
for (std::vector<wxString>::const_iterator i = failedNodes.begin(); i != failedNodes.end(); ++i)
bgstack15