diff --git a/LaunchAPPL/Launcher.cc b/LaunchAPPL/Launcher.cc index 3f21a2ec47..c2567e5b69 100644 --- a/LaunchAPPL/Launcher.cc +++ b/LaunchAPPL/Launcher.cc @@ -1,6 +1,7 @@ #include "Launcher.h" #include #include +#include #include #include #include @@ -14,10 +15,22 @@ using std::vector; Launcher::Launcher(boost::program_options::variables_map &options) : options(options) { - app.assign(options["application"].as()); - if(!app.read()) - throw std::runtime_error("Could not load application file."); - + string fn = options["application"].as(); + + if(fn == "-") + { + std::stringstream tmp; + tmp << std::cin.rdbuf(); + if(!app.read(tmp, ResourceFile::Format::macbin)) + throw std::runtime_error("Could not load application from stdin."); + } + else + { + app.assign(fn); + if(!app.read()) + throw std::runtime_error("Could not load application file."); + } + tempDir = fs::absolute(fs::unique_path()); fs::create_directories(tempDir); diff --git a/ResourceFiles/ResourceFile.cc b/ResourceFiles/ResourceFile.cc index 4ce0dd1032..003b3d62d9 100644 --- a/ResourceFiles/ResourceFile.cc +++ b/ResourceFiles/ResourceFile.cc @@ -150,6 +150,7 @@ bool ResourceFile::assign(std::string pathstring, ResourceFile::Format f) this->pathstring = pathstring; fs::path path(pathstring); + this->filename = path.stem().string(); fs::path rsrcPath = path.parent_path() / ".rsrc" / path.filename(); fs::path finfPath = path.parent_path() / ".finf" / path.filename(); @@ -208,12 +209,91 @@ bool ResourceFile::assign(std::string pathstring, ResourceFile::Format f) return true; } +bool ResourceFile::read(std::istream& in, Format f) +{ + switch(f) + { + case Format::applesingle: + { + if(longword(in) != 0x00051600) + return false; + if(longword(in) != 0x00020000) + return false; + in.seekg(24); + int n = word(in); + for(int i = 0; i < n; i++) + { + in.seekg(26 + i * 12); + int what = longword(in); + int off = longword(in); + int len = longword(in); + in.seekg(off); + switch(what) + { + case 1: + { + std::vector buf(len); + in.read(buf.data(), len); + data = std::string(buf.begin(), buf.end()); + } + break; + case 2: + resources = Resources(in); + break; + case 9: + type = ostype(in); + creator = ostype(in); + break; + } + } + } + break; + case Format::macbin: + { + if(byte(in) != 0) + return false; + if(byte(in) > 63) + return false; + in.seekg(65); + type = ostype(in); + creator = ostype(in); + in.seekg(83); + int datasize = longword(in); + //int rsrcsize = longword(in); + + in.seekg(0); + char header[124]; + in.read(header, 124); + unsigned short crc = CalculateCRC(0,header,124); + if(word(in) != crc) + return false; + in.seekg(128); + std::vector buf(datasize); + in.read(buf.data(), datasize); + data = std::string(buf.begin(), buf.end()); + datasize = ((int)datasize + 0x7F) & ~0x7F; + in.seekg(128 + datasize); + resources = Resources(in); + } + break; + default: + return false; + } + return true; +} + bool ResourceFile::read() { fs::path path(pathstring); type = creator = 0x3F3F3F3F; + if(isSingleFork(format)) + { + fs::ifstream in(path); + return read(in, format); + } + switch(format) { case Format::basilisk: @@ -259,42 +339,7 @@ bool ResourceFile::read() } break; #endif - case Format::applesingle: - { - fs::ifstream in(path); - if(longword(in) != 0x00051600) - return false; - if(longword(in) != 0x00020000) - return false; - in.seekg(24); - int n = word(in); - for(int i = 0; i < n; i++) - { - in.seekg(26 + i * 12); - int what = longword(in); - int off = longword(in); - int len = longword(in); - in.seekg(off); - switch(what) - { - case 1: - { - std::vector buf(len); - in.read(buf.data(), len); - data = std::string(buf.begin(), buf.end()); - } - break; - case 2: - resources = Resources(in); - break; - case 9: - type = ostype(in); - creator = ostype(in); - break; - } - } - } - break; + case Format::underscore_appledouble: case Format::percent_appledouble: { @@ -333,33 +378,50 @@ bool ResourceFile::read() } } break; + default: + return false; + } + return true; +} + +bool ResourceFile::write(std::ostream& out, Format f) +{ + switch(f) + { case Format::macbin: { - fs::ifstream in(path); - if(byte(in) != 0) - return false; - if(byte(in) > 63) - return false; - in.seekg(65); - type = ostype(in); - creator = ostype(in); - in.seekg(83); - int datasize = longword(in); - //int rsrcsize = longword(in); - - in.seekg(0); - char header[124]; - in.read(header, 124); - unsigned short crc = CalculateCRC(0,header,124); - if(word(in) != crc) - return false; - in.seekg(128); - std::vector buf(datasize); - in.read(buf.data(), datasize); - data = std::string(buf.begin(), buf.end()); - datasize = ((int)datasize + 0x7F) & ~0x7F; - in.seekg(128 + datasize); - resources = Resources(in); + writeMacBinary(out, filename, type, creator, resources, data); + } + break; + case Format::applesingle: + { + longword(out, 0x00051600); + longword(out, 0x00020000); + for(int i = 0; i < 16; i++) + byte(out, 0); + word(out, 3); + std::streampos entries = out.tellp(); + for(int i = 0; i < 3*3; i++) + longword(out, 0); + std::streampos dataStart = out.tellp(); + out << data; + std::streampos rsrcStart = out.tellp(); + resources.writeFork(out); + std::streampos finfStart = out.tellp(); + ostype(out, type); + ostype(out, creator); + for(int i = 8; i < 32; i++) + byte(out, 0); + out.seekp(entries); + longword(out, 1); + longword(out, dataStart); + longword(out, rsrcStart - dataStart); + longword(out, 2); + longword(out, rsrcStart); + longword(out, finfStart - rsrcStart); + longword(out, 9); + longword(out, finfStart); + longword(out, 32); } break; default: @@ -372,6 +434,12 @@ bool ResourceFile::write() { fs::path path(pathstring); + if(isSingleFork(format)) + { + fs::ofstream out(path); + return write(out, format); + } + switch(format) { case Format::basilisk: @@ -411,46 +479,7 @@ bool ResourceFile::write() } break; #endif - case Format::macbin: - { - fs::ofstream out(path); - writeMacBinary(out, path.stem().string(), type, creator, resources, data); - } - break; - case Format::applesingle: - { - fs::ofstream out(path); - longword(out, 0x00051600); - longword(out, 0x00020000); - for(int i = 0; i < 16; i++) - byte(out, 0); - word(out, 3); - std::streampos entries = out.tellp(); - for(int i = 0; i < 3*3; i++) - longword(out, 0); - std::streampos dataStart = out.tellp(); - out << data; - std::streampos rsrcStart = out.tellp(); - resources.writeFork(out); - std::streampos finfStart = out.tellp(); - ostype(out, type); - ostype(out, creator); - for(int i = 8; i < 32; i++) - byte(out, 0); - out.seekp(entries); - longword(out, 1); - longword(out, dataStart); - longword(out, rsrcStart - dataStart); - longword(out, 2); - longword(out, rsrcStart); - longword(out, finfStart - rsrcStart); - longword(out, 9); - longword(out, finfStart); - longword(out, 32); - } - break; - - // TODO: case Format::underscore_appledouble + case Format::underscore_appledouble: case Format::percent_appledouble: { @@ -548,3 +577,14 @@ bool ResourceFile::hasPlainDataFork() return hasPlainDataFork(format); } +bool ResourceFile::isSingleFork(Format f) +{ + switch(f) + { + case Format::macbin: + case Format::applesingle: + return true; + default: + return false; + } +} diff --git a/ResourceFiles/ResourceFile.h b/ResourceFiles/ResourceFile.h index 00cea3f0f6..cc0f520d7e 100644 --- a/ResourceFiles/ResourceFile.h +++ b/ResourceFiles/ResourceFile.h @@ -2,6 +2,9 @@ #define RESOURCEFILE_H #include +#include +#include + #include "ResType.h" #include "ResourceFork.h" @@ -28,13 +31,19 @@ public: bool assign(std::string path, Format f = Format::autodetect); + bool read(std::istream& in, Format f); + bool write(std::ostream& in, Format f); + bool read(); bool write(); static bool hasPlainDataFork(Format f); bool hasPlainDataFork(); + static bool isSingleFork(Format f); + std::string pathstring; + std::string filename; Format format; ResType type; ResType creator;