From 58db06d845db4b8dfc90a7e98914f9d1c3ae79a4 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sun, 9 Oct 2016 14:58:07 +0000 Subject: [PATCH] DXF: update to use Unicode-aware file open routines on Windows. --- extlib/libdxfrw | 2 +- src/exportvector.cpp | 12 ++++++++++-- src/importdxf.cpp | 30 ++++++++++++++++++++++-------- src/platform/unixutil.cpp | 7 +++++++ src/platform/w32util.cpp | 16 ++++++++++++++-- src/solvespace.h | 2 ++ 6 files changed, 56 insertions(+), 13 deletions(-) diff --git a/extlib/libdxfrw b/extlib/libdxfrw index e389be82..8f958955 160000 --- a/extlib/libdxfrw +++ b/extlib/libdxfrw @@ -1 +1 @@ -Subproject commit e389be82d060ee923b17b9bc574438f3272ef2ad +Subproject commit 8f958955f54668c142ded760dc951ffd16d9c71b diff --git a/src/exportvector.cpp b/src/exportvector.cpp index 6bf83aed..ebf71b17 100644 --- a/src/exportvector.cpp +++ b/src/exportvector.cpp @@ -696,11 +696,19 @@ void DxfFileWriter::Bezier(SBezier *sb) { } void DxfFileWriter::FinishAndCloseFile() { - dxfRW dxf(filename.c_str()); + dxfRW dxf; + DxfWriteInterface interface = {}; interface.writer = this; interface.dxf = &dxf; - dxf.write(&interface, DRW::AC1021, /*bin=*/false); + + std::fstream stream = ssfstream(filename, std::ios_base::out); + if(!stream.good()) { + Error("Couldn't write to '%s'", filename.c_str()); + return; + } + + dxf.write(stream, &interface, DRW::AC1021, /*bin=*/false); paths.clear(); constraint = NULL; diff --git a/src/importdxf.cpp b/src/importdxf.cpp index af0d9e2a..048537b8 100644 --- a/src/importdxf.cpp +++ b/src/importdxf.cpp @@ -900,13 +900,20 @@ public: }; void ImportDxf(const std::string &filename) { - SS.UndoRemember(); - dxfRW dxf(filename.c_str()); DxfReadInterface interface; interface.clearBlockTransform(); - if(!dxf.read(&interface, /*ext=*/false)) { - Error("Corrupted DXF file!"); + + std::fstream stream = ssfstream(filename, std::ios_base::in); + if(!stream.good()) { + Error("Couldn't read from '%s'", filename.c_str()); + return; } + + SS.UndoRemember(); + if(!dxfRW().read(stream, &interface, /*ext=*/false)) { + Error("Corrupted DXF file."); + } + if(interface.unknownEntities > 0) { Message(ssprintf("%u DXF entities of unknown type were ignored.", interface.unknownEntities).c_str()); @@ -914,13 +921,20 @@ void ImportDxf(const std::string &filename) { } void ImportDwg(const std::string &filename) { - SS.UndoRemember(); - dwgR dwg(filename.c_str()); DxfReadInterface interface; interface.clearBlockTransform(); - if(!dwg.read(&interface, /*ext=*/false)) { - Error("Corrupted DWG file!"); + + std::fstream stream = ssfstream(filename, std::ios_base::in); + if(!stream.good()) { + Error("Couldn't read from '%s'", filename.c_str()); + return; } + + SS.UndoRemember(); + if(!dwgR().read(stream, &interface, /*ext=*/false)) { + Error("Corrupted DWG file."); + } + if(interface.unknownEntities > 0) { Message(ssprintf("%u DWG entities of unknown type were ignored.", interface.unknownEntities).c_str()); diff --git a/src/platform/unixutil.cpp b/src/platform/unixutil.cpp index f076cc99..812e519d 100644 --- a/src/platform/unixutil.cpp +++ b/src/platform/unixutil.cpp @@ -82,6 +82,13 @@ FILE *ssfopen(const std::string &filename, const char *mode) return fopen(filename.c_str(), mode); } +std::fstream ssfstream(const std::string &filename, std::ios_base::openmode mode) +{ + ssassert(filename.length() == strlen(filename.c_str()), + "Unexpected null byte in middle of a path"); + return std::fstream(filename, mode); +} + void ssremove(const std::string &filename) { ssassert(filename.length() == strlen(filename.c_str()), diff --git a/src/platform/w32util.cpp b/src/platform/w32util.cpp index 7848c504..65423601 100644 --- a/src/platform/w32util.cpp +++ b/src/platform/w32util.cpp @@ -117,7 +117,7 @@ std::string PathSepUnixToPlatform(const std::string &filename) return result; } -FILE *ssfopen(const std::string &filename, const char *mode) +static std::string MakeUNCFilename(const std::string &filename) { // Prepend \\?\ UNC prefix unless already an UNC path. // We never try to fopen paths that are not absolute or @@ -126,10 +126,22 @@ FILE *ssfopen(const std::string &filename, const char *mode) std::string uncFilename = filename; if(uncFilename.substr(0, 2) != "\\\\") uncFilename = "\\\\?\\" + uncFilename; + return uncFilename; +} +FILE *ssfopen(const std::string &filename, const char *mode) +{ ssassert(filename.length() == strlen(filename.c_str()), "Unexpected null byte in middle of a path"); - return _wfopen(Widen(uncFilename).c_str(), Widen(mode).c_str()); + return _wfopen(Widen(MakeUNCFilename(filename)).c_str(), Widen(mode).c_str()); +} + +std::fstream ssfstream(const std::string &filename, std::ios_base::openmode mode) +{ + std::string uncFilename = MakeUNCFilename(filename); + ssassert(filename.length() == strlen(filename.c_str()), + "Unexpected null byte in middle of a path"); + return std::fstream(Widen(MakeUNCFilename(filename)).c_str(), mode); } void ssremove(const std::string &filename) diff --git a/src/solvespace.h b/src/solvespace.h index 9fbe77e4..0fabf053 100644 --- a/src/solvespace.h +++ b/src/solvespace.h @@ -29,6 +29,7 @@ #include #include #include +#include // We declare these in advance instead of simply using FT_Library // (defined as typedef FT_LibraryRec_* FT_Library) because including @@ -154,6 +155,7 @@ bool PathEqual(const std::string &a, const std::string &b); std::string PathSepPlatformToUnix(const std::string &filename); std::string PathSepUnixToPlatform(const std::string &filename); FILE *ssfopen(const std::string &filename, const char *mode); +std::fstream ssfstream(const std::string &filename, std::ios_base::openmode mode); void ssremove(const std::string &filename); const size_t MAX_RECENT = 8;