diff --git a/aegisub/libaegisub/ass/uuencode.cpp b/aegisub/libaegisub/ass/uuencode.cpp index 8ddb2b334..b899029e2 100644 --- a/aegisub/libaegisub/ass/uuencode.cpp +++ b/aegisub/libaegisub/ass/uuencode.cpp @@ -26,27 +26,6 @@ namespace agi { namespace ass { -std::vector UUDecode(std::string const& str) { - std::vector ret; - ret.reserve(str.size() * 3 / 4); - - for(size_t pos = 0; pos + 1 < str.size(); pos += 4) { - size_t bytes = std::min(str.size() - pos, 4); - - unsigned char src[4] = { '\0', '\0', '\0', '\0' }; - for (size_t i = 0; i < bytes; ++i) - src[i] = str[pos + i] - 33; - - ret.push_back((src[0] << 2) | (src[1] >> 4)); - if (bytes > 2) - ret.push_back(((src[1] & 0xF) << 4) | (src[2] >> 2)); - if (bytes > 3) - ret.push_back(((src[2] & 0x3) << 6) | (src[3])); - } - - return ret; -} - std::string UUEncode(std::vector const& data) { std::string ret; ret.reserve((data.size() * 4 + 2) / 3 + data.size() / 80 * 2); diff --git a/aegisub/libaegisub/include/libaegisub/ass/uuencode.h b/aegisub/libaegisub/include/libaegisub/ass/uuencode.h index 9b61153d8..a6d6b6256 100644 --- a/aegisub/libaegisub/include/libaegisub/ass/uuencode.h +++ b/aegisub/libaegisub/include/libaegisub/ass/uuencode.h @@ -22,7 +22,33 @@ namespace agi { /// Encode a blob of data, using ASS's nonstandard variant std::string UUEncode(std::vector const& data); - /// Decode an ASS uuencoded string which has had its newlines stripped - std::vector UUDecode(std::string const& str); + /// Decode an ASS uuencoded string + template + std::vector UUDecode(String const& str) { + std::vector ret; + size_t len = std::end(str) - std::begin(str); + ret.reserve(len * 3 / 4); + + for (size_t pos = 0; pos + 1 < len; ) { + size_t bytes = 0; + unsigned char src[4] = { '\0', '\0', '\0', '\0' }; + for (size_t i = 0; i < 4 && pos < len; ) { + char c = str[pos++]; + if (c && c != '\n' && c != '\r') { + src[i++] = c - 33; + ++bytes; + } + } + + if (bytes > 1) + ret.push_back((src[0] << 2) | (src[1] >> 4)); + if (bytes > 2) + ret.push_back(((src[1] & 0xF) << 4) | (src[2] >> 2)); + if (bytes > 3) + ret.push_back(((src[2] & 0x3) << 6) | (src[3])); + } + + return ret; + } } } diff --git a/aegisub/src/ass_attachment.cpp b/aegisub/src/ass_attachment.cpp index d8f37b04b..5704956fc 100644 --- a/aegisub/src/ass_attachment.cpp +++ b/aegisub/src/ass_attachment.cpp @@ -22,6 +22,7 @@ #include #include +#include #include AssAttachment::AssAttachment(std::string const& name, AssEntryGroup group) @@ -67,7 +68,8 @@ size_t AssAttachment::GetSize() const { void AssAttachment::Extract(agi::fs::path const& filename) const { auto header_end = entry_data.get().find('\n'); - agi::io::Save(filename, true).Get().write(&entry_data.get()[header_end + 1], entry_data.get().size() - header_end - 1); + auto decoded = agi::ass::UUDecode(boost::make_iterator_range(entry_data.get().begin() + header_end + 1, entry_data.get().end())); + agi::io::Save(filename, true).Get().write(&decoded[0], decoded.size()); } std::string AssAttachment::GetFileName(bool raw) const { diff --git a/aegisub/tests/tests/option.cpp b/aegisub/tests/tests/option.cpp index 3c093730d..a2d93fb5d 100644 --- a/aegisub/tests/tests/option.cpp +++ b/aegisub/tests/tests/option.cpp @@ -19,6 +19,8 @@ #include "main.h" #include "util.h" +#include + class lagi_option : public libagi { protected: std::string default_opt; diff --git a/aegisub/tests/tests/uuencode.cpp b/aegisub/tests/tests/uuencode.cpp index 1591c6d48..26c0c4918 100644 --- a/aegisub/tests/tests/uuencode.cpp +++ b/aegisub/tests/tests/uuencode.cpp @@ -48,7 +48,7 @@ TEST(lagi_uuencode, random_blobs_roundtrip) { std::vector data; for (size_t len = 0; len < 200; ++len) { - EXPECT_EQ(data, UUDecode(boost::replace_all_copy(UUEncode(data), "\r\n", ""))); + EXPECT_EQ(data, UUDecode(UUEncode(data))); data.push_back(rand()); } }