X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fio%2FSVNReportParser.cxx;h=72b6169310338b65a3a07800f7feca5c3671dbf2;hb=70c5d605641b628039f75cb8761ce783a17a5bdf;hp=a6f80224e4e71d5aa947affcb5db97ce1f8ef463;hpb=acf86be516cb7b3b6883aa261af90a263ed52837;p=simgear.git diff --git a/simgear/io/SVNReportParser.cxx b/simgear/io/SVNReportParser.cxx index a6f80224..72b61693 100644 --- a/simgear/io/SVNReportParser.cxx +++ b/simgear/io/SVNReportParser.cxx @@ -16,6 +16,10 @@ // 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 +#endif + #include "SVNReportParser.hxx" #include @@ -30,11 +34,16 @@ #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 +#else +# include "sg_expat.h" +#endif + #include "SVNDirectory.hxx" #include "SVNRepository.hxx" #include "DAVMultiStatus.hxx" @@ -97,12 +106,13 @@ namespace { const char* SVN_ADD_FILE_TAG = SVN_NS "add-file"; const char* SVN_TXDELTA_TAG = SVN_NS "txdelta"; const char* SVN_SET_PROP_TAG = SVN_NS "set-prop"; + const char* SVN_PROP_TAG = SVN_NS "prop"; const char* SVN_DELETE_ENTRY_TAG = SVN_NS "delete-entry"; const char* SVN_DAV_MD5_CHECKSUM = SUBVERSION_DAV_NS ":md5-checksum"; const char* DAV_HREF_TAG = DAV_NS "href"; - const char* DAV_CHECKED_IN_TAG = SVN_NS "checked-in"; + const char* DAV_CHECKED_IN_TAG = DAV_NS "checked-in"; const int svn_txdelta_source = 0; @@ -156,7 +166,7 @@ namespace { _ptr = p; } - bool apply(std::vector& output, std::istream& source) + bool apply(std::vector& output, std::istream& source) { unsigned char* pEnd = _ptr + instructionLength; unsigned char* newData = pEnd; @@ -164,7 +174,7 @@ namespace { while (_ptr < pEnd) { int op = ((*_ptr >> 6) & 0x3); if (op >= 3) { - SG_LOG(SG_IO, SG_INFO, "SVNDeltaWindow: bad opcode:" << op); + SG_LOG(SG_IO, SG_INFO, "SVNDeltaWindow: bad opcode:" << op); return false; } @@ -186,12 +196,14 @@ namespace { } if (op == svn_txdelta_target) { - while (length > 0) { - output.push_back(output[offset++]); - --length; - } + // this is inefficent, but ranges can overlap. + while (length > 0) { + output.push_back(output[offset++]); + --length; + } } else if (op == svn_txdelta_new) { output.insert(output.end(), newData, newData + length); + newData += length; } else if (op == svn_txdelta_source) { source.seekg(offset); char* sourceBuf = (char*) malloc(length); @@ -199,6 +211,9 @@ namespace { source.read(sourceBuf, length); output.insert(output.end(), sourceBuf, sourceBuf + length); free(sourceBuf); + } else { + SG_LOG(SG_IO, SG_WARN, "bad opcode logic"); + return false; } } // of instruction loop @@ -260,12 +275,12 @@ public: string fileName(attrs.getValue("name")); SGPath filePath(Dir(currentPath).file(fileName)); currentPath = filePath; - - DAVResource* res = currentDir->collection()->childWithName(fileName); - if (!res || !filePath.exists()) { - // set error condition + + if (!filePath.exists()) { + fail(SVNRepository::SVN_ERROR_FILE_NOT_FOUND); + return; } - + inFile = true; } else if (!strcmp(name, SVN_ADD_DIRECTORY_TAG)) { string dirName(attrs.getValue("name")); @@ -293,10 +308,12 @@ public: } else if (!strcmp(name, SVN_DELETE_ENTRY_TAG)) { string entryName(attrs.getValue("name")); deleteEntry(entryName); - } else if (!strcmp(name, DAV_CHECKED_IN_TAG) || !strcmp(name, DAV_HREF_TAG)) { + } else if (!strcmp(name, DAV_CHECKED_IN_TAG) || + !strcmp(name, DAV_HREF_TAG) || + !strcmp(name, SVN_PROP_TAG)) { // don't warn on these ones } else { - //std::cerr << "unhandled element:" << name << std::endl; + //SG_LOG(SG_IO, SG_WARN, "SVNReportParser: unhandled tag:" << name); } } // of startElement @@ -321,11 +338,12 @@ public: } bool decodeTextDelta(const SGPath& outputPath) - { - string decoded = strutils::decodeBase64(txDeltaData); + { + std::vector output, decoded; + strutils::decodeBase64(txDeltaData, decoded); size_t bytesToDecode = decoded.size(); - std::vector output; - unsigned char* p = (unsigned char*) decoded.data(); + + unsigned char* p = decoded.data(); if (memcmp(p, "SVN\0", DELTA_HEADER_SIZE) != 0) { return false; // bad header } @@ -337,9 +355,9 @@ public: while (bytesToDecode > 0) { if (!SVNDeltaWindow::isWindowComplete(p, bytesToDecode)) { - SG_LOG(SG_IO, SG_WARN, "SVN txdelta broken window"); - return false; - } + SG_LOG(SG_IO, SG_WARN, "SVN txdelta broken window"); + return false; + } SVNDeltaWindow window(p); assert(bytesToDecode >= window.size()); @@ -353,14 +371,15 @@ public: 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 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); + unsigned char digest[MD5_DIGEST_LENGTH]; + SG_MD5Final(digest, &md5Context); + decodedFileMd5 = strutils::encodeHex(digest, MD5_DIGEST_LENGTH); return true; } @@ -379,11 +398,9 @@ public: fail(SVNRepository::SVN_ERROR_TXDELTA); } } else if (!strcmp(name, SVN_ADD_FILE_TAG)) { - finishFile(currentDir->addChildFile(currentPath.file())); + finishFile(currentPath); } else if (!strcmp(name, SVN_OPEN_FILE_TAG)) { - DAVResource* res = currentDir->collection()->childWithName(currentPath.file()); - assert(res); - finishFile(res); + finishFile(currentPath); } else if (!strcmp(name, SVN_ADD_DIRECTORY_TAG)) { // pop directory currentPath = currentPath.dir(); @@ -406,23 +423,21 @@ public: 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 finishFile(DAVResource* res) + void finishFile(const SGPath& path) { - res->setVersionName(currentVersionName); - res->setMD5(md5Sum); - currentPath = currentPath.dir(); + currentPath = path.dir(); inFile = false; } @@ -433,11 +448,11 @@ public: } 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); } }