-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathodf_document.cpp
More file actions
103 lines (84 loc) · 3.34 KB
/
Copy pathodf_document.cpp
File metadata and controls
103 lines (84 loc) · 3.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include <odr/internal/odf/odf_document.hpp>
#include <odr/exceptions.hpp>
#include <odr/internal/abstract/filesystem.hpp>
#include <odr/internal/common/file.hpp>
#include <odr/internal/odf/odf_parser.hpp>
#include <odr/internal/util/file_util.hpp>
#include <odr/internal/util/xml_util.hpp>
#include <odr/internal/zip/zip_archive.hpp>
#include <fstream>
#include <sstream>
namespace odr::internal::odf {
Document::Document(const FileType file_type, const DocumentType document_type,
std::shared_ptr<abstract::ReadableFilesystem> files)
: TemplateDocument(file_type, document_type, std::move(files)) {
m_content_xml = util::xml::parse(*m_filesystem, AbsPath("/content.xml"));
if (m_filesystem->exists(AbsPath("/styles.xml"))) {
m_styles_xml = util::xml::parse(*m_filesystem, AbsPath("/styles.xml"));
}
m_root_element = parse_tree(
*this,
m_content_xml.document_element().child("office:body").first_child());
m_style_registry = StyleRegistry(*this, m_content_xml.document_element(),
m_styles_xml.document_element());
}
bool Document::is_editable() const noexcept {
// TODO fix spreadsheet editability
return m_document_type == DocumentType::text ||
m_document_type == DocumentType::presentation ||
m_document_type == DocumentType::drawing;
}
bool Document::is_savable(const bool encrypted) const noexcept {
return !encrypted;
}
void Document::save(const Path &path) const {
// TODO this would decrypt/inflate and encrypt/deflate again
zip::ZipArchive archive;
// `mimetype` has to be the first file and uncompressed
if (m_filesystem->is_file(AbsPath("/mimetype"))) {
archive.insert_file(std::end(archive), RelPath("mimetype"),
m_filesystem->open(AbsPath("/mimetype")), 0);
}
for (auto walker = m_filesystem->file_walker(AbsPath("/")); !walker->end();
walker->next()) {
const AbsPath &abs_path = walker->path();
RelPath rel_path = abs_path.rebase(AbsPath("/"));
if (abs_path == Path("/mimetype")) {
continue;
}
if (walker->is_directory()) {
archive.insert_directory(std::end(archive), rel_path);
continue;
}
if (abs_path == Path("/content.xml")) {
// TODO stream
std::stringstream out;
m_content_xml.print(out, "", pugi::format_raw);
auto tmp = std::make_shared<MemoryFile>(out.str());
archive.insert_file(std::end(archive), rel_path, tmp);
continue;
}
if (abs_path == Path("/META-INF/manifest.xml")) {
// TODO
auto manifest =
util::xml::parse(*m_filesystem, AbsPath("/META-INF/manifest.xml"));
for (auto &&node : manifest.select_nodes("//manifest:encryption-data")) {
node.node().parent().remove_child(node.node());
}
std::stringstream out;
manifest.print(out, "", pugi::format_raw);
auto tmp = std::make_shared<MemoryFile>(out.str());
archive.insert_file(std::end(archive), rel_path, tmp);
continue;
}
archive.insert_file(std::end(archive), rel_path,
m_filesystem->open(abs_path));
}
std::ofstream ostream = util::file::create(path.string());
archive.save(ostream);
}
void Document::save(const Path & /*path*/, const char * /*password*/) const {
// TODO throw if not savable
throw UnsupportedOperation();
}
} // namespace odr::internal::odf