/src/libvisio/src/lib/VSDXMLHelper.cpp
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* |
3 | | * This file is part of the libvisio project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | */ |
9 | | |
10 | | #include "VSDXMLHelper.h" |
11 | | |
12 | | #include <memory> |
13 | | #include <sstream> |
14 | | #include <istream> |
15 | | #include <vector> |
16 | | #include <boost/algorithm/string.hpp> |
17 | | #include <librevenge-stream/librevenge-stream.h> |
18 | | #include "libvisio_utils.h" |
19 | | #include "libvisio_xml.h" |
20 | | |
21 | | // VSDXRelationship |
22 | | |
23 | | libvisio::VSDXRelationship::VSDXRelationship(xmlTextReaderPtr reader) |
24 | 30.5k | : m_id(), m_type(), m_target() |
25 | 30.5k | { |
26 | 30.5k | if (reader) |
27 | | // TODO: check whether we are actually parsing "Relationship" element |
28 | 30.5k | { |
29 | 121k | while (xmlTextReaderMoveToNextAttribute(reader)) |
30 | 90.5k | { |
31 | 90.5k | const xmlChar *name = xmlTextReaderConstName(reader); |
32 | 90.5k | const xmlChar *value = xmlTextReaderConstValue(reader); |
33 | 90.5k | if (xmlStrEqual(name, BAD_CAST("Id"))) |
34 | 30.2k | m_id = (const char *)value; |
35 | 60.3k | else if (xmlStrEqual(name, BAD_CAST("Type"))) |
36 | 29.9k | m_type = (const char *)value; |
37 | 30.3k | else if (xmlStrEqual(name, BAD_CAST("Target"))) |
38 | 29.5k | m_target = (const char *)value; |
39 | 90.5k | } |
40 | | // VSD_DEBUG_MSG(("Relationship : %s type: %s target: %s\n", m_id.c_str(), m_type.c_str(), m_target.c_str())); |
41 | 30.5k | } |
42 | 30.5k | } |
43 | | |
44 | | libvisio::VSDXRelationship::VSDXRelationship() |
45 | 57.1k | : m_id(), m_type(), m_target() |
46 | 57.1k | { |
47 | 57.1k | } |
48 | | |
49 | | libvisio::VSDXRelationship::~VSDXRelationship() |
50 | 87.6k | { |
51 | 87.6k | } |
52 | | |
53 | | void libvisio::VSDXRelationship::rebaseTarget(const char *baseDir) |
54 | 27.3k | { |
55 | 27.3k | std::string target(baseDir ? baseDir : ""); |
56 | 27.3k | if (!target.empty()) |
57 | 26.9k | target += "/"; |
58 | 27.3k | target += m_target; |
59 | | |
60 | | // normalize path by resolving any ".." or "." segments |
61 | | // and eliminating duplicate path separators |
62 | 27.3k | std::vector<std::string> segments; |
63 | 27.3k | boost::split(segments, target, boost::is_any_of("/\\")); |
64 | 27.3k | std::vector<std::string> normalizedSegments; |
65 | | |
66 | 27.3k | for (auto &segment : segments) |
67 | 107k | { |
68 | 107k | if (segment == "..") |
69 | 1.86k | { |
70 | | // guard against a malformed Target with excess ".." segments |
71 | 1.86k | if (!normalizedSegments.empty()) |
72 | 1.86k | normalizedSegments.pop_back(); |
73 | 1.86k | } |
74 | 105k | else if (segment != "." && !segment.empty()) |
75 | 77.9k | normalizedSegments.push_back(segment); |
76 | 107k | } |
77 | | |
78 | 27.3k | target.clear(); |
79 | 27.3k | for (const auto &normalizedSegment : normalizedSegments) |
80 | 76.0k | { |
81 | 76.0k | if (!target.empty()) |
82 | 49.0k | target.append("/"); |
83 | 76.0k | target.append(normalizedSegment); |
84 | 76.0k | } |
85 | | |
86 | | // VSD_DEBUG_MSG(("VSDXRelationship::rebaseTarget %s -> %s\n", m_target.c_str(), target.c_str())); |
87 | 27.3k | m_target = target; |
88 | 27.3k | } |
89 | | |
90 | | |
91 | | // VSDXRelationships |
92 | | |
93 | | libvisio::VSDXRelationships::VSDXRelationships(librevenge::RVNGInputStream *input) |
94 | 11.2k | : m_relsByType(), m_relsById() |
95 | 11.2k | { |
96 | 11.2k | if (input) |
97 | 9.60k | { |
98 | 9.60k | auto reader = xmlReaderForStream(input); |
99 | 9.60k | if (reader) |
100 | 9.60k | { |
101 | 9.60k | bool inRelationships = false; |
102 | 9.60k | int ret = xmlTextReaderRead(reader.get()); |
103 | 58.4k | while (ret == 1) |
104 | 48.8k | { |
105 | 48.8k | const xmlChar *name = xmlTextReaderConstName(reader.get()); |
106 | 48.8k | if (name) |
107 | 48.8k | { |
108 | 48.8k | if (xmlStrEqual(name, BAD_CAST("Relationships"))) |
109 | 17.8k | { |
110 | 17.8k | if (xmlTextReaderNodeType(reader.get()) == 1) |
111 | 9.08k | { |
112 | | // VSD_DEBUG_MSG(("Relationships ON\n")); |
113 | 9.08k | inRelationships = true; |
114 | 9.08k | } |
115 | 8.76k | else if (xmlTextReaderNodeType(reader.get()) == 15) |
116 | 8.76k | { |
117 | | // VSD_DEBUG_MSG(("Relationships OFF\n")); |
118 | 8.76k | inRelationships = false; |
119 | 8.76k | } |
120 | 17.8k | } |
121 | 30.9k | else if (xmlStrEqual(name, BAD_CAST("Relationship"))) |
122 | 30.5k | { |
123 | 30.5k | if (inRelationships) |
124 | 30.5k | { |
125 | 30.5k | VSDXRelationship relationship(reader.get()); |
126 | 30.5k | m_relsByType[relationship.getType()] = relationship; |
127 | 30.5k | m_relsById[relationship.getId()] = relationship; |
128 | 30.5k | } |
129 | 30.5k | } |
130 | 48.8k | } |
131 | 48.8k | ret = xmlTextReaderRead(reader.get()); |
132 | 48.8k | } |
133 | 9.60k | } |
134 | 9.60k | } |
135 | 11.2k | } |
136 | | |
137 | | libvisio::VSDXRelationships::~VSDXRelationships() |
138 | 11.2k | { |
139 | 11.2k | } |
140 | | |
141 | | void libvisio::VSDXRelationships::rebaseTargets(const char *baseDir) |
142 | 8.02k | { |
143 | 8.02k | std::map<std::string, libvisio::VSDXRelationship>::iterator iter; |
144 | 20.0k | for (iter = m_relsByType.begin(); iter != m_relsByType.end(); ++iter) |
145 | 12.0k | iter->second.rebaseTarget(baseDir); |
146 | 23.3k | for (iter = m_relsById.begin(); iter != m_relsById.end(); ++iter) |
147 | 15.3k | iter->second.rebaseTarget(baseDir); |
148 | 8.02k | } |
149 | | |
150 | | const libvisio::VSDXRelationship *libvisio::VSDXRelationships::getRelationshipByType(const char *type) const |
151 | 13.8k | { |
152 | 13.8k | if (!type) |
153 | 0 | return nullptr; |
154 | 13.8k | auto iter = m_relsByType.find(type); |
155 | 13.8k | if (iter != m_relsByType.end()) |
156 | 11.1k | return &(iter->second); |
157 | 2.65k | return nullptr; |
158 | 13.8k | } |
159 | | |
160 | | const libvisio::VSDXRelationship *libvisio::VSDXRelationships::getRelationshipById(const char *id) const |
161 | 3.64k | { |
162 | 3.64k | if (!id) |
163 | 0 | return nullptr; |
164 | 3.64k | auto iter = m_relsById.find(id); |
165 | 3.64k | if (iter != m_relsById.end()) |
166 | 2.98k | return &(iter->second); |
167 | 654 | return nullptr; |
168 | 3.64k | } |
169 | | |
170 | | /* vim:set shiftwidth=2 softtabstop=2 expandtab: */ |