// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
#include "SVNReportParser.hxx"
#include <iostream>
#include "simgear/misc/sg_path.hxx"
#include "simgear/misc/sg_dir.hxx"
#include "simgear/debug/logstream.hxx"
-#include "simgear/xml/xmlparse.h"
#include "simgear/xml/easyxml.hxx"
#include "simgear/misc/strutils.hxx"
#include "simgear/package/md5.h"
+#ifdef SYSTEM_EXPAT
+# include <expat.h>
+#else
+# include "sg_expat.h"
+#endif
+
#include "SVNDirectory.hxx"
#include "SVNRepository.hxx"
#include "DAVMultiStatus.hxx"
headerLength = p - _ptr;
_ptr = p;
-
- if (sourceViewOffset != 0) {
- cout << "sourceViewOffset:" << sourceViewOffset << endl;
- }
}
- bool apply(std::vector<char>& output, std::istream& source)
+ bool apply(std::vector<unsigned char>& output, std::istream& source)
{
unsigned char* pEnd = _ptr + instructionLength;
unsigned char* newData = pEnd;
while (_ptr < pEnd) {
int op = ((*_ptr >> 6) & 0x3);
if (op >= 3) {
- std::cerr << "weird opcode" << endl;
+ SG_LOG(SG_IO, SG_INFO, "SVNDeltaWindow: bad opcode:" << op);
return false;
}
}
if (length == 0) {
- std::cerr << "malformed stream, 0 length" << std::endl;
+ SG_LOG(SG_IO, SG_INFO, "SVNDeltaWindow: malformed stream, 0 length" << op);
return false;
}
public:
SVNReportParserPrivate(SVNRepository* repo) :
tree(repo),
- status(SVNRepository::NO_ERROR),
+ status(SVNRepository::SVN_NO_ERROR),
parserInited(false),
currentPath(repo->fsBase())
{
void startElement (const char * name, const char** attributes)
{
- if (status != SVNRepository::NO_ERROR) {
+ if (status != SVNRepository::SVN_NO_ERROR) {
return;
}
bool decodeTextDelta(const SGPath& outputPath)
{
- string decoded = strutils::decodeBase64(txDeltaData);
+ std::vector<unsigned char> output, decoded;
+ strutils::decodeBase64(txDeltaData, decoded);
size_t bytesToDecode = decoded.size();
- std::vector<char> output;
- unsigned char* p = (unsigned char*) decoded.data();
- if (memcmp(decoded.data(), "SVN\0", DELTA_HEADER_SIZE) != 0) {
+
+ unsigned char* p = decoded.data();
+ if (memcmp(p, "SVN\0", DELTA_HEADER_SIZE) != 0) {
return false; // bad header
}
source.open(outputPath.c_str(), std::ios::in | std::ios::binary);
while (bytesToDecode > 0) {
+ if (!SVNDeltaWindow::isWindowComplete(p, bytesToDecode)) {
+ SG_LOG(SG_IO, SG_WARN, "SVN txdelta broken window");
+ return false;
+ }
+
SVNDeltaWindow window(p);
assert(bytesToDecode >= window.size());
window.apply(output, source);
}
source.close();
+
std::ofstream f;
f.open(outputPath.c_str(),
std::ios::out | std::ios::trunc | std::ios::binary);
- f.write(output.data(), output.size());
-
+ f.write((char*) output.data(), output.size());
+
// compute MD5 while we have the file in memory
- MD5_CTX md5;
- memset(&md5, 0, sizeof(MD5_CTX));
- MD5Init(&md5);
- MD5Update(&md5, (unsigned char*) output.data(), output.size());
- MD5Final(&md5);
- decodedFileMd5 = strutils::encodeHex(md5.digest, 16);
+ memset(&md5Context, 0, sizeof(SG_MD5_CTX));
+ SG_MD5Init(&md5Context);
+ SG_MD5Update(&md5Context, (unsigned char*) output.data(), output.size());
+ SG_MD5Final(&md5Context);
+ decodedFileMd5 = strutils::encodeHex(md5Context.digest, 16);
+
return true;
}
void endElement (const char * name)
{
- if (status != SVNRepository::NO_ERROR) {
+ if (status != SVNRepository::SVN_NO_ERROR) {
return;
}
assert(tagStack.back() == name);
tagStack.pop_back();
+
if (!strcmp(name, SVN_TXDELTA_TAG)) {
if (!decodeTextDelta(currentPath)) {
- fail(SVNRepository::ERROR_TXDELTA);
+ fail(SVNRepository::SVN_ERROR_TXDELTA);
}
} else if (!strcmp(name, SVN_ADD_FILE_TAG)) {
finishFile(currentDir->addChildFile(currentPath.file()));
} else if (!strcmp(name, SVN_OPEN_FILE_TAG)) {
DAVResource* res = currentDir->collection()->childWithName(currentPath.file());
- assert(res);
+ if (!res) {
+ SG_LOG(SG_IO, SG_WARN, "SVN open-file: unknown: " << currentPath);
+ fail(SVNRepository::SVN_ERROR_IO);
+ return;
+ }
finishFile(res);
} else if (!strcmp(name, SVN_ADD_DIRECTORY_TAG)) {
// pop directory
} else if (!strcmp(name, SVN_DAV_MD5_CHECKSUM)) {
// validate against (presumably) just written file
if (decodedFileMd5 != md5Sum) {
- fail(SVNRepository::ERROR_CHECKSUM);
+ SG_LOG(SG_GENERAL, SG_INFO, "checksum fail on:" << currentPath);
+ fail(SVNRepository::SVN_ERROR_CHECKSUM);
}
} else if (!strcmp(name, SVN_OPEN_DIRECTORY_TAG)) {
+ currentDir->updateReportComplete();
if (currentDir->parent()) {
// pop the collection stack
currentDir = currentDir->parent();
}
- currentDir->updateReportComplete();
currentPath = currentDir->fsPath();
} else {
// std::cout << "element:" << name;
void data (const char * s, int length)
{
- if (status != SVNRepository::NO_ERROR) {
+ if (status != SVNRepository::SVN_NO_ERROR) {
return;
}
if (tagStack.back() == SVN_SET_PROP_TAG) {
- setPropValue += string(s, length);
+ setPropValue.append(s, length);
} else if (tagStack.back() == SVN_TXDELTA_TAG) {
- txDeltaData += string(s, length);
+ txDeltaData.append(s, length);
} else if (tagStack.back() == SVN_DAV_MD5_CHECKSUM) {
- md5Sum += string(s, length);
+ md5Sum.append(s, length);
}
}
bool inFile;
unsigned int revision;
+ SG_MD5_CTX md5Context;
string md5Sum, decodedFileMd5;
std::string setPropName, setPropValue;
};
SVNRepository::ResultCode
SVNReportParser::innerParseXML(const char* data, int size)
{
- if (_d->status != SVNRepository::NO_ERROR) {
+ if (_d->status != SVNRepository::SVN_NO_ERROR) {
return _d->status;
}
XML_ParserFree(_d->xmlParser);
_d->parserInited = false;
- return SVNRepository::ERROR_XML;
+ return SVNRepository::SVN_ERROR_XML;
} else if (isEnd) {
XML_ParserFree(_d->xmlParser);
_d->parserInited = false;
}
-
+
return _d->status;
}
SVNRepository::ResultCode
SVNReportParser::parseXML(const char* data, int size)
{
- if (_d->status != SVNRepository::NO_ERROR) {
+ if (_d->status != SVNRepository::SVN_NO_ERROR) {
return _d->status;
}
SVNRepository::ResultCode SVNReportParser::finishParse()
{
- if (_d->status != SVNRepository::NO_ERROR) {
+ if (_d->status != SVNRepository::SVN_NO_ERROR) {
return _d->status;
}