/src/libreoffice/writerperfect/source/common/DocumentHandler.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
6 | | * |
7 | | * For further information visit http://libwpd.sourceforge.net |
8 | | */ |
9 | | |
10 | | #include <DocumentHandler.hxx> |
11 | | |
12 | | #include <string.h> |
13 | | |
14 | | #include <com/sun/star/uno/Reference.hxx> |
15 | | #include <com/sun/star/xml/sax/XDocumentHandler.hpp> |
16 | | #include <com/sun/star/xml/sax/XAttributeList.hpp> |
17 | | #include <comphelper/attributelist.hxx> |
18 | | #include <xmloff/xmlimp.hxx> |
19 | | |
20 | | namespace writerperfect |
21 | | { |
22 | | const unsigned char librvng_utf8_skip_data[256] |
23 | | = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
24 | | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
25 | | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
26 | | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
27 | | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
28 | | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
29 | | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
30 | | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, |
31 | | 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1 }; |
32 | | |
33 | | static const char* librvng_utf8_next_char(const char* p) |
34 | 0 | { |
35 | 0 | return p + librvng_utf8_skip_data[*reinterpret_cast<unsigned char const*>(p)]; |
36 | 0 | } |
37 | | |
38 | | static void unescapeXML(const char* s, const unsigned long sz, librevenge::RVNGString& res) |
39 | 0 | { |
40 | 0 | const char* p = s; |
41 | 0 | const char* const end = p + sz; |
42 | 0 | while (p != end) |
43 | 0 | { |
44 | 0 | const char* const next = librvng_utf8_next_char(p); |
45 | 0 | if (next > end) |
46 | 0 | { |
47 | | // oops, the string is invalid |
48 | 0 | break; |
49 | 0 | } |
50 | 0 | if (p + 4 <= end && p + 1 == next && *p == '&') |
51 | 0 | { |
52 | | // look for & , < , > , ' , " |
53 | 0 | bool escapedChar = false; |
54 | 0 | switch (*(p + 1)) |
55 | 0 | { |
56 | 0 | case 'a': |
57 | 0 | if (p + 5 <= end && strncmp(p, "&", 5) == 0) |
58 | 0 | { |
59 | 0 | res.append('&'); |
60 | 0 | p += 5; |
61 | 0 | escapedChar = true; |
62 | 0 | } |
63 | 0 | else if (p + 6 <= end && strncmp(p, "'", 6) == 0) |
64 | 0 | { |
65 | 0 | res.append('\''); |
66 | 0 | p += 6; |
67 | 0 | escapedChar = true; |
68 | 0 | } |
69 | 0 | break; |
70 | 0 | case 'g': |
71 | 0 | if (strncmp(p, ">", 4) == 0) |
72 | 0 | { |
73 | 0 | res.append('>'); |
74 | 0 | p += 4; |
75 | 0 | escapedChar = true; |
76 | 0 | } |
77 | 0 | break; |
78 | 0 | case 'l': |
79 | 0 | if (strncmp(p, "<", 4) == 0) |
80 | 0 | { |
81 | 0 | res.append('<'); |
82 | 0 | p += 4; |
83 | 0 | escapedChar = true; |
84 | 0 | } |
85 | 0 | break; |
86 | 0 | case 'q': |
87 | 0 | if (p + 6 <= end && strncmp(p, """, 6) == 0) |
88 | 0 | { |
89 | 0 | res.append('"'); |
90 | 0 | p += 6; |
91 | 0 | escapedChar = true; |
92 | 0 | } |
93 | 0 | break; |
94 | 0 | default: |
95 | 0 | break; |
96 | 0 | } |
97 | 0 | if (escapedChar) |
98 | 0 | continue; |
99 | 0 | } |
100 | | |
101 | 0 | while (p != next) |
102 | 0 | { |
103 | 0 | res.append(*p); |
104 | 0 | ++p; |
105 | 0 | } |
106 | 0 | p = next; |
107 | 0 | } |
108 | 0 | } |
109 | | |
110 | | using com::sun::star::uno::Reference; |
111 | | using com::sun::star::xml::sax::XDocumentHandler; |
112 | | |
113 | | DocumentHandler::DocumentHandler(Reference<XDocumentHandler> const& xHandler) |
114 | 0 | : mxHandler(xHandler) |
115 | 0 | { |
116 | 0 | if (SvXMLImport* pFastHandler = dynamic_cast<SvXMLImport*>(mxHandler.get())) |
117 | 0 | mxHandler.set(new SvXMLLegacyToFastDocHandler(pFastHandler)); |
118 | 0 | } |
119 | | |
120 | 0 | void DocumentHandler::startDocument() { mxHandler->startDocument(); } |
121 | | |
122 | 0 | void DocumentHandler::endDocument() { mxHandler->endDocument(); } |
123 | | |
124 | | void DocumentHandler::startElement(const char* psName, |
125 | | const librevenge::RVNGPropertyList& xPropList) |
126 | 0 | { |
127 | 0 | rtl::Reference<comphelper::AttributeList> pAttrList = new comphelper::AttributeList(); |
128 | 0 | librevenge::RVNGPropertyList::Iter i(xPropList); |
129 | 0 | for (i.rewind(); i.next();) |
130 | 0 | { |
131 | | // filter out librevenge elements |
132 | 0 | if (strncmp(i.key(), "librevenge", 10) != 0) |
133 | 0 | { |
134 | 0 | size_t keyLength = strlen(i.key()); |
135 | 0 | OUString sName(i.key(), keyLength, RTL_TEXTENCODING_UTF8); |
136 | 0 | OUString sValue(i()->getStr().cstr(), i()->getStr().len(), RTL_TEXTENCODING_UTF8); |
137 | | |
138 | | // libodfgen xml-encodes some attribute's value, so check if the value is encoded or not |
139 | 0 | for (int j = 0; j < 9; ++j) |
140 | 0 | { |
141 | | // list of the encoded attributes followed by their lengths |
142 | 0 | static char const* const listEncoded[9] |
143 | 0 | = { "draw:name", "svg:font-family", "style:condition", |
144 | 0 | "style:num-prefix", "style:num-suffix", "table:formula", |
145 | 0 | "text:bullet-char", "text:label", "xlink:href" }; |
146 | 0 | static size_t const listEncodedLength[9] = { 9, 15, 15, 16, 16, 13, 16, 10, 10 }; |
147 | 0 | if (keyLength == listEncodedLength[j] |
148 | 0 | && strncmp(i.key(), listEncoded[j], keyLength) == 0) |
149 | 0 | { |
150 | 0 | librevenge::RVNGString decodedValue(""); |
151 | 0 | unescapeXML(i()->getStr().cstr(), |
152 | 0 | static_cast<unsigned long>(i()->getStr().len()), decodedValue); |
153 | 0 | sValue |
154 | 0 | = OUString(decodedValue.cstr(), decodedValue.len(), RTL_TEXTENCODING_UTF8); |
155 | 0 | break; |
156 | 0 | } |
157 | 0 | } |
158 | 0 | pAttrList->AddAttribute(sName, sValue); |
159 | 0 | } |
160 | 0 | } |
161 | |
|
162 | 0 | OUString sElementName(psName, strlen(psName), RTL_TEXTENCODING_UTF8); |
163 | 0 | mxHandler->startElement(sElementName, pAttrList); |
164 | 0 | } |
165 | | |
166 | | void DocumentHandler::endElement(const char* psName) |
167 | 0 | { |
168 | 0 | OUString sElementName(psName, strlen(psName), RTL_TEXTENCODING_UTF8); |
169 | 0 | mxHandler->endElement(sElementName); |
170 | 0 | } |
171 | | |
172 | | void DocumentHandler::characters(const librevenge::RVNGString& sCharacters) |
173 | 0 | { |
174 | 0 | OUString sCharU16(sCharacters.cstr(), strlen(sCharacters.cstr()), RTL_TEXTENCODING_UTF8); |
175 | 0 | mxHandler->characters(sCharU16); |
176 | 0 | } |
177 | | } |
178 | | |
179 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |