Mercurial > hg > orthanc
changeset 4342:52166629239f
SystemToolbox::ReadFileRange()
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 03 Dec 2020 18:48:06 +0100 |
parents | 977c2759eb0a |
children | e1e918e790e8 |
files | OrthancFramework/Sources/SystemToolbox.cpp OrthancFramework/Sources/SystemToolbox.h OrthancFramework/Sources/TemporaryFile.cpp OrthancFramework/Sources/TemporaryFile.h OrthancFramework/UnitTestsSources/FrameworkTests.cpp |
diffstat | 5 files changed, 125 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancFramework/Sources/SystemToolbox.cpp Thu Dec 03 18:15:47 2020 +0100 +++ b/OrthancFramework/Sources/SystemToolbox.cpp Thu Dec 03 18:48:06 2020 +0100 @@ -224,6 +224,13 @@ std::streamsize size = GetStreamSize(f); content.resize(static_cast<size_t>(size)); + + if (static_cast<std::streamsize>(content.size()) != size) + { + throw OrthancException(ErrorCode_InternalError, + "Reading a file that is too large for a 32bit architecture"); + } + if (size != 0) { f.read(&content[0], size); @@ -807,4 +814,68 @@ return (base / relative).string(); } } + + + void SystemToolbox::ReadFileRange(std::string& content, + const std::string& path, + uint64_t start, // Inclusive + uint64_t end, // Exclusive + bool throwIfOverflow) + { + if (start > end) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + if (!IsRegularFile(path)) + { + throw OrthancException(ErrorCode_RegularFileExpected, + "The path does not point to a regular file: " + path); + } + + boost::filesystem::ifstream f; + f.open(path, std::ifstream::in | std::ifstream::binary); + if (!f.good()) + { + throw OrthancException(ErrorCode_InexistentFile, + "File not found: " + path); + } + + uint64_t fileSize = static_cast<uint64_t>(GetStreamSize(f)); + if (end > fileSize) + { + if (throwIfOverflow) + { + throw OrthancException(ErrorCode_ParameterOutOfRange, + "Reading beyond the end of a file"); + } + else + { + end = fileSize; + } + } + + if (start <= end) + { + content.resize(static_cast<size_t>(end - start)); + + if (static_cast<uint64_t>(content.size()) != (end - start)) + { + throw OrthancException(ErrorCode_InternalError, + "Reading a file that is too large for a 32bit architecture"); + } + + if (!content.empty()) + { + f.seekg(start, std::ios::beg); + f.read(&content[0], static_cast<std::streamsize>(content.size())); + } + } + else + { + content.clear(); + } + + f.close(); + } }
--- a/OrthancFramework/Sources/SystemToolbox.h Thu Dec 03 18:15:47 2020 +0100 +++ b/OrthancFramework/Sources/SystemToolbox.h Thu Dec 03 18:48:06 2020 +0100 @@ -113,5 +113,11 @@ static std::string InterpretRelativePath(const std::string& baseDirectory, const std::string& relativePath); + + static void ReadFileRange(std::string& content, + const std::string& path, + uint64_t start, // Inclusive + uint64_t end, // Exclusive + bool throwIfOverflow); }; }
--- a/OrthancFramework/Sources/TemporaryFile.cpp Thu Dec 03 18:15:47 2020 +0100 +++ b/OrthancFramework/Sources/TemporaryFile.cpp Thu Dec 03 18:48:06 2020 +0100 @@ -138,4 +138,13 @@ { return SystemToolbox::GetFileSize(path_); } + + + void TemporaryFile::ReadRange(std::string& content, + uint64_t start, + uint64_t end, + bool throwIfOverflow) const + { + SystemToolbox::ReadFileRange(content, path_, start, end, throwIfOverflow); + } }
--- a/OrthancFramework/Sources/TemporaryFile.h Thu Dec 03 18:15:47 2020 +0100 +++ b/OrthancFramework/Sources/TemporaryFile.h Thu Dec 03 18:48:06 2020 +0100 @@ -60,5 +60,10 @@ void Touch(); uint64_t GetFileSize() const; + + void ReadRange(std::string& content, + uint64_t start, + uint64_t end, + bool throwIfOverflow) const; }; }
--- a/OrthancFramework/UnitTestsSources/FrameworkTests.cpp Thu Dec 03 18:15:47 2020 +0100 +++ b/OrthancFramework/UnitTestsSources/FrameworkTests.cpp Thu Dec 03 18:48:06 2020 +0100 @@ -1373,3 +1373,37 @@ } } #endif + + +#if ORTHANC_SANDBOXED != 1 +TEST(Toolbox, ReadFileRange) +{ + TemporaryFile tmp; + std::string s; + + tmp.Write(""); + tmp.Read(s); ASSERT_TRUE(s.empty()); + tmp.ReadRange(s, 0, 0, true); ASSERT_TRUE(s.empty()); + tmp.ReadRange(s, 0, 10, false); ASSERT_TRUE(s.empty()); + + ASSERT_THROW(tmp.ReadRange(s, 0, 1, true), OrthancException); + + tmp.Write("Hello"); + tmp.Read(s); ASSERT_EQ("Hello", s); + tmp.ReadRange(s, 0, 5, true); ASSERT_EQ("Hello", s); + tmp.ReadRange(s, 0, 1, true); ASSERT_EQ("H", s); + tmp.ReadRange(s, 1, 2, true); ASSERT_EQ("e", s); + tmp.ReadRange(s, 2, 3, true); ASSERT_EQ("l", s); + tmp.ReadRange(s, 3, 4, true); ASSERT_EQ("l", s); + tmp.ReadRange(s, 4, 5, true); ASSERT_EQ("o", s); + tmp.ReadRange(s, 2, 5, true); ASSERT_EQ("llo", s); + tmp.ReadRange(s, 2, 50, false); ASSERT_EQ("llo", s); + tmp.ReadRange(s, 2, 2, false); ASSERT_TRUE(s.empty()); + tmp.ReadRange(s, 10, 50, false); ASSERT_TRUE(s.empty()); + + ASSERT_THROW(tmp.ReadRange(s, 5, 10, true), OrthancException); + ASSERT_THROW(tmp.ReadRange(s, 10, 50, true), OrthancException); + ASSERT_THROW(tmp.ReadRange(s, 50, 10, true), OrthancException); + ASSERT_THROW(tmp.ReadRange(s, 2, 1, true), OrthancException); +} +#endif