diff --git a/src/duckx.cpp b/src/duckx.cpp index 2de8be2..63db869 100644 --- a/src/duckx.cpp +++ b/src/duckx.cpp @@ -264,20 +264,65 @@ void duckx::Document::open() { } void duckx::Document::save() { + // minizip only supports appending or writing to new files + // so we must + // - make a new file + // - write any new files + // - copy the old files + // - delete old docx + // - rename new file to old file + // Open file and replace "xml" content - zip_t *zip = zip_open(this->directory.c_str(), ZIP_DEFAULT_COMPRESSION_LEVEL, 'a'); - - zip_entry_open(zip, "word/document.xml"); - - xml_string_writer writer; + std::string original_file = this->directory; + std::string temp_file = this->directory + ".tmp"; + + // Create the new file + zip_t *new_zip = zip_open(temp_file.c_str(), ZIP_DEFAULT_COMPRESSION_LEVEL, 'w'); + + // Write out document.xml + zip_entry_open(new_zip, "word/document.xml"); + xml_string_writer writer; this->document.print(writer); const char *buf = writer.result.c_str(); - zip_entry_write(zip, buf, strlen(buf)); - - zip_entry_close(zip); - zip_close(zip); + zip_entry_write(new_zip, buf, strlen(buf)); + zip_entry_close(new_zip); + + // Open the original zip and copy all files which are not replaced by duckX + zip_t* orig_zip = zip_open(original_file.c_str(), ZIP_DEFAULT_COMPRESSION_LEVEL, 'r'); + // Loop & copy each relevant entry in the original zip + int orig_zip_entry_ct = zip_total_entries(orig_zip); + for (int i = 0; i < orig_zip_entry_ct; i++) + { + zip_entry_openbyindex(orig_zip, i); + const char* name = zip_entry_name(orig_zip); + // Skip copying the original file + if (std::string(name) != std::string("word/document.xml")) + { + // Read the old content + void* entry_buf; + size_t entry_buf_size; + zip_entry_read(orig_zip, &entry_buf, &entry_buf_size); + + // Write into new zip + zip_entry_open(new_zip, name); + zip_entry_write(new_zip, entry_buf, entry_buf_size); + zip_entry_close(new_zip); + + free(entry_buf); + } + + zip_entry_close(orig_zip); + } + + // Close both zips + zip_close(orig_zip); + zip_close(new_zip); + + // Remove original zip, rename new to correct name + remove(original_file.c_str()); + rename(temp_file.c_str(), original_file.c_str()); } duckx::Paragraph &duckx::Document::paragraphs() { diff --git a/src/duckx.hpp b/src/duckx.hpp index 76eee95..c98f817 100644 --- a/src/duckx.hpp +++ b/src/duckx.hpp @@ -8,6 +8,7 @@ #define DUCKX_H #include +#include #include #include "pugixml.hpp"