Actually uudecode attachments when extracting them

Closes #1653.
This commit is contained in:
Thomas Goyne 2013-10-24 08:53:33 -07:00
parent b1ecefe0f2
commit 50f92ef573
5 changed files with 34 additions and 25 deletions

View file

@ -26,27 +26,6 @@
namespace agi { namespace ass {
std::vector<char> UUDecode(std::string const& str) {
std::vector<char> ret;
ret.reserve(str.size() * 3 / 4);
for(size_t pos = 0; pos + 1 < str.size(); pos += 4) {
size_t bytes = std::min<size_t>(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<char> const& data) {
std::string ret;
ret.reserve((data.size() * 4 + 2) / 3 + data.size() / 80 * 2);

View file

@ -22,7 +22,33 @@ namespace agi {
/// Encode a blob of data, using ASS's nonstandard variant
std::string UUEncode(std::vector<char> const& data);
/// Decode an ASS uuencoded string which has had its newlines stripped
std::vector<char> UUDecode(std::string const& str);
/// Decode an ASS uuencoded string
template<typename String>
std::vector<char> UUDecode(String const& str) {
std::vector<char> 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;
}
}
}

View file

@ -22,6 +22,7 @@
#include <libaegisub/io.h>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/range/iterator_range.hpp>
#include <fstream>
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 {

View file

@ -19,6 +19,8 @@
#include "main.h"
#include "util.h"
#include <fstream>
class lagi_option : public libagi {
protected:
std::string default_opt;

View file

@ -48,7 +48,7 @@ TEST(lagi_uuencode, random_blobs_roundtrip) {
std::vector<char> 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());
}
}