/* * (c) Copyright Ascensio System SIA 2010-2023 * * This program is a free software product. You can redistribute it and/or * modify it under the terms of the GNU Affero General Public License (AGPL) * version 3 as published by the Free Software Foundation. In accordance with * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect * that Ascensio System SIA expressly excludes the warranty of non-infringement * of any third-party rights. * * This program is distributed WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html * * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish * street, Riga, Latvia, EU, LV-1050. * * The interactive user interfaces in modified source and object code versions * of the Program must display Appropriate Legal Notices, as required under * Section 5 of the GNU AGPL version 3. * * Pursuant to Section 7(b) of the License you must retain the original Product * logo when distributing the program. Pursuant to Section 7(e) we decline to * grant you any rights under trademark law for use of our trademarks. * * All the Product's GUI elements, including illustrations and icon sets, as * well as technical writing content are licensed under the terms of the * Creative Commons Attribution-ShareAlike 4.0 International. See the License * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode * */ #include #include "docx_package.h" #include "docx_conversion_context.h" #include "headers_footers.h" namespace cpdoccore { namespace oox { namespace package { docx_content_types_file::docx_content_types_file() { content()->add_default(L"rels", L"application/vnd.openxmlformats-package.relationships+xml"); content()->add_default(L"xml", L"application/xml"); // content()->add_default(L"jpg", L"image/jpeg"); content()->add_default(L"png", L"image/png"); // content()->add_override(L"/word/document.xml", L"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"); content()->add_override(L"/word/settings.xml", L"application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"); content()->add_override(L"/word/styles.xml", L"application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"); content()->add_override(L"/word/fontTable.xml", L"application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"); //content()->add_override(L"/word/_rels/document.xml.rels", L"application/vnd.openxmlformats-package.relationships+xml"); //content()->add_override(L"/_rels/.rels", L"application/vnd.openxmlformats-package.relationships+xml"); content()->add_override(L"/docProps/app.xml", L"application/vnd.openxmlformats-officedocument.extended-properties+xml"); content()->add_override(L"/docProps/core.xml", L"application/vnd.openxmlformats-package.core-properties+xml"); } //////////////////////////////////////////////////////////////////////////////////////// word_files::word_files() { rels_file_ptr relFile = rels_file_ptr( new rels_file(L"document.xml.rels") ); rels_files_.add_rel_file( relFile ); } void word_files::write(const std::wstring & RootPath) { std::wstring path = RootPath + FILE_SEPARATOR_STR + L"word"; NSDirectory::CreateDirectory(path.c_str()); if (document_) document_->write( path ); if (styles_) { rels_files_.add( relationship(L"rId1", L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles", L"styles.xml" ) ); styles_->write( path ); } if (fontTable_) { rels_files_.add( relationship(L"rId2", L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable", L"fontTable.xml" ) ); fontTable_->write( path ); } if (numbering_) { rels_files_.add( relationship(L"rId3", L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering", L"numbering.xml" ) ); numbering_->write( path ); } if (media_) { media_->write( path ); } if (embeddings_) { embeddings_->write( path ); } if (drawings_) { drawings_->set_main_document(get_main_document()); drawings_->write( path ); } if (headers_footers_) { headers_footers_->write( path ); } if (settings_) { rels_files_.add( relationship(L"rId4", L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings", L"settings.xml" ) ); settings_->write( path ); } if (comments_) { rels_files_.add( relationship(L"rId5", L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments", L"comments.xml" ) ); comments_->write( path ); } { charts_files_.set_main_document(get_main_document()); charts_files_.write(path); } if (jsaProject_) { rels_files_.add( relationship(L"jsaId", L"http://schemas.onlyoffice.com/jsaProject", L"jsaProject.bin" ) ); jsaProject_->write( path ); } if (notes_) { notes_->write( path ); } rels_files_.write(path); } void word_files::update_rels(docx_conversion_context & Context) { Context.get_mediaitems()->dump_rels(rels_files_.get_rel_file()->get_rels(), oox::document_place); Context.dump_hyperlinks (rels_files_.get_rel_file()->get_rels(), oox::document_place); Context.dump_headers_footers(rels_files_.get_rel_file()->get_rels()); Context.dump_notes (rels_files_.get_rel_file()->get_rels()); } void word_files::set_media(mediaitems_ptr & _mediaitems) { if (_mediaitems->count_image + _mediaitems->count_media > 0) { media_ = element_ptr( new media(_mediaitems, _mediaitems->applicationFonts()) ); } if (_mediaitems->count_object > 0) { embeddings_ = element_ptr( new embeddings(_mediaitems) ); embeddings_->set_main_document( get_main_document() ); } } void word_files::set_styles(element_ptr Element) { styles_ = Element; } void word_files::set_document(element_ptr Element) { document_ = Element; } void word_files::set_fontTable(element_ptr Element) { fontTable_ = Element; } void word_files::set_numbering(element_ptr Element) { numbering_ = Element; } void word_files::set_settings(element_ptr Element) { settings_ = Element; } void word_files::add_charts(chart_content_ptr chart) { charts_files_.add_chart(chart); } bool word_files::has_numbering() { return numbering_ ? true : false; } void word_files::add_jsaProject(const std::string &content) { jsaProject_ = package::simple_element::create(L"jsaProject.bin", content); } void word_files::set_drawings(element_ptr Element) { drawings_ = Element; } void word_files::set_headers_footers(headers_footers & HeadersFooters) { headers_footers_elements * elm = new headers_footers_elements(HeadersFooters); elm->set_main_document( get_main_document() ); headers_footers_ = element_ptr( elm ); } void word_files::set_notes(notes_context & notesContext) { notes_elements * elm = new notes_elements(notesContext); elm->set_main_document( get_main_document() ); notes_ = element_ptr( elm ); } void word_files::set_comments(comments_context & commentsContext) { if (commentsContext.comments_.size()<1)return; comments_elements * elm = new comments_elements(commentsContext); elm->set_main_document( get_main_document() ); comments_ = element_ptr( elm ); } void word_files::add_rels(relationship const & r) { rels_files_.add(r); } //---------------------------------------------------------- int customXml_files::add_customXml(customXml_content_ptr customXml) { customXmls_.push_back(customXml); return customXmls_.size(); } void customXml_files::write(const std::wstring & RootPath) { std::wstring path = RootPath + FILE_SEPARATOR_STR + L"customXml"; NSDirectory::CreateDirectory(path.c_str()); std::wstring path_rels = path + FILE_SEPARATOR_STR + L"_rels"; NSDirectory::CreateDirectory(path_rels.c_str()); for (size_t i = 0 ; i < customXmls_.size(); i++) { if (!customXmls_[i]) continue; const std::wstring fileNameItem = std::wstring(L"item") + std::to_wstring(i+1) + L".xml"; const std::wstring fileNameProps = std::wstring(L"itemProps") + std::to_wstring(i+1) + L".xml"; content_type * contentTypes = get_main_document()->get_content_types_file().content(); contentTypes->add_override(std::wstring(L"/customXml/") + fileNameProps, L"application/vnd.openxmlformats-officedocument.customXmlProperties+xml"); package::simple_element(fileNameItem, customXmls_[i]->item()).write(path); package::simple_element(fileNameProps, customXmls_[i]->props()).write(path); rels_file_ptr rels_file = rels_file::create(fileNameItem + L".rels"); rels_file->get_rels().add(relationship(L"rId1", L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXmlProps", fileNameProps)); rels_file->write(path_rels); } } //---------------------------------------------------------- void docx_charts_files::add_chart(chart_content_ptr chart) { charts_.push_back(chart); } void docx_charts_files::write(const std::wstring & RootPath) { std::wstring path = RootPath + FILE_SEPARATOR_STR + L"charts"; NSDirectory::CreateDirectory(path.c_str()); size_t count = 0; for (size_t i = 0 ; i < charts_.size(); i++) { if (!charts_[i]) continue; count++; const std::wstring fileName = std::wstring(L"chart") + std::to_wstring(count) + L".xml"; const std::wstring kWSConType = L"application/vnd.openxmlformats-officedocument.drawingml.chart+xml"; content_type * contentTypes = get_main_document()->get_content_types_file().content(); contentTypes->add_override(std::wstring(L"/word/charts/") + fileName, kWSConType); package::simple_element(fileName, charts_[i]->str()).write(path); rels_files relFiles; charts_[i]->get_rel_file()->set_file_name(fileName + L".rels"); relFiles.add_rel_file(charts_[i]->get_rel_file()); relFiles.write(path); } } /////////////////////////// headers_footers_elements::headers_footers_elements(headers_footers & HeadersFooters) : headers_footers_(HeadersFooters) { } void headers_footers_elements::write(const std::wstring & RootPath) { BOOST_FOREACH(const headers_footers::instances_map::value_type & instAr, headers_footers_.instances()) { BOOST_FOREACH(const headers_footers::instance_ptr & inst, instAr.second) { if (inst->type_ == headers_footers::none) continue; simple_element(inst->name_, inst->content_).write(RootPath); if (document * doc = this->get_main_document()) { const std::wstring ContentType = (inst->type_ == headers_footers::header || inst->type_ == headers_footers::headerLeft || inst->type_ == headers_footers::headerFirst) ? L"application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml" : L"application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml"; doc->get_content_types_file().content()->add_override(std::wstring(L"/word/") + inst->name_, ContentType); } //нужно сформировать релсы с объектов if (!inst->rels_.empty()) { rels_files relFiles; rels_file_ptr rels_elem = rels_file::create(inst->name_ + L".rels"); relFiles.add_rel_file(rels_elem); BOOST_FOREACH(relationship const & r, inst->rels_.relationships()) { relFiles.add(r); } relFiles.write(RootPath); } } } } /////////////////// notes_elements::notes_elements(notes_context & notesContext) : notes_context_(notesContext) { } namespace { void process_notes(const notes_context::instances_map & Instances, const std::wstring & Node, const std::wstring & Name, const std::wstring & ContentType, const std::wstring & RootPath, rels & Rels, document * doc ) { if (Instances.size()) { std::wstringstream content; // внимание! L"s - это не ошибка content << L""; //mc:Ignorable=\"w14 wp14\" //xmlns:v=\"urn:schemas-microsoft-com:vml\" BOOST_FOREACH(const notes_context::instances_map::value_type & elm, Instances) { content << L"id << L"\">"; content << elm.second->content; content << L""; } content << L""; simple_element(Name, content.str()).write(RootPath); if (doc) { doc->get_content_types_file().content()->add_override(std::wstring(L"/word/") + Name, ContentType); } if (false == Rels.relationships().empty()) { rels_files relFiles; rels_file_ptr rels_elem = rels_file::create( Node + L"s.xml.rels"); relFiles.add_rel_file(rels_elem); BOOST_FOREACH(relationship & r, Rels.relationships()) { relFiles.add(r); } relFiles.write(RootPath); } } } } void notes_elements::write(const std::wstring & RootPath) { process_notes(notes_context_.footnotes(), L"footnote", L"footnotes.xml", L"application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml", RootPath, notes_context_.footnotesRels(), get_main_document()); process_notes(notes_context_.endnotes(), L"endnote", L"endnotes.xml", L"application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml", RootPath, notes_context_.endnotesRels(), get_main_document()); } /////////////////// comments_elements::comments_elements(comments_context & commentsContext) : comments_context_(commentsContext) { } void comments_elements::write(const std::wstring & RootPath) { if (comments_context_.comments_.size()) { std::wstringstream content; content << L""; BOOST_FOREACH(const comments_context::_comment_desc & elm, comments_context_.comments_) { content << L"0) content << L"w:author=\""<< XmlUtils::EncodeXmlString(elm.author) << "\" "; if (elm.date.length()>0) content << L"w:date=\""<< elm.date << "\" "; content<< L">"; content << elm.content; content << L""; } content << L""; simple_element(L"comments.xml", content.str()).write(RootPath); if (get_main_document()) get_main_document()->get_content_types_file().content()->add_override(L"/word/comments.xml", L"application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml"); } if (!comments_context_.get_rels().empty()) { rels_files relFiles; rels_file_ptr rels_elem = rels_file::create(L"comments.xml.rels"); relFiles.add_rel_file(rels_elem); BOOST_FOREACH(relationship const & r, comments_context_.get_rels().relationships()) { relFiles.add(r); } relFiles.write(RootPath); } } //////////////////////////////////////////////////////////////////////////////////////// docx_document::docx_document() { this->set_main_document(this); word_files_.set_main_document(this); customXml_files_.set_main_document(this); rels_file_ptr relFile = rels_file_ptr( new rels_file(L".rels") ); relFile->get_rels().relationships().push_back( relationship(L"rId1", L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties", L"docProps/app.xml" ) ); relFile->get_rels().relationships().push_back( relationship(L"rId2", L"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties", L"docProps/core.xml" ) ); relFile->get_rels().relationships().push_back( relationship(L"rId3", L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument", L"word/document.xml" ) ); get_rels_files().add_rel_file( relFile ); } int docx_document::add_customXml(customXml_content_ptr customXml) { return customXml_files_.add_customXml(customXml); } void docx_document::write(const std::wstring & RootPath) { if (word_files_.has_numbering()) { content_type_file_.content()->get_override().push_back( override_content_type(L"/word/numbering.xml", L"application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml") ); } customXml_files_.write (RootPath); word_files_.write (RootPath); get_rels_files().write (RootPath); get_docProps_files().write (RootPath); content_type_file_.write(RootPath); } } } }