Line data Source code
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 :
18 : #include <xmloff/attrlist.hxx>
19 :
20 : namespace writerperfect
21 : {
22 :
23 : static const unsigned char librvng_utf8_skip_data[256] =
24 : {
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,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,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,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,1,1,1,
29 : 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,1,1,1,
30 : 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,1,1,1,
31 : 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
32 : 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
33 : };
34 :
35 : #define librvng_utf8_next_char(p) ((p) + librvng_utf8_skip_data[*reinterpret_cast<unsigned char const *>(p)])
36 :
37 659 : static void unescapeXML(const char *s, const unsigned long sz, librevenge::RVNGString &res)
38 : {
39 659 : const char *p = s;
40 659 : const char *const end = p + sz;
41 7451 : while (p != end)
42 : {
43 6133 : const char *const next = librvng_utf8_next_char(p);
44 6133 : if (next > end)
45 : {
46 : // oops, the string is invalid
47 0 : break;
48 : }
49 6133 : if (p+4 <= end && p+1==next && *p=='&')
50 : {
51 : // look for & , < , > , ' , "
52 8 : bool escapedChar=false;
53 8 : switch (*(p+1))
54 : {
55 : case 'a':
56 0 : if (p+5 <= end && strncmp(p,"&",5)==0)
57 : {
58 0 : res.append('&');
59 0 : p+=5;
60 0 : escapedChar=true;
61 : }
62 0 : else if (p+6 <= end && strncmp(p,"'",6)==0)
63 : {
64 0 : res.append('\'');
65 0 : p+=6;
66 0 : escapedChar=true;
67 : }
68 0 : break;
69 : case 'g':
70 0 : if (strncmp(p,">",4)==0)
71 : {
72 0 : res.append('>');
73 0 : p+=4;
74 0 : escapedChar=true;
75 : }
76 0 : break;
77 : case 'l':
78 0 : if (strncmp(p,"<",4)==0)
79 : {
80 0 : res.append('<');
81 0 : p+=4;
82 0 : escapedChar=true;
83 : }
84 0 : break;
85 : case 'q':
86 8 : if (p+6 <= end && strncmp(p,""",6)==0)
87 : {
88 8 : res.append('"');
89 8 : p+=6;
90 8 : escapedChar=true;
91 : }
92 8 : break;
93 : default:
94 0 : break;
95 : }
96 8 : if (escapedChar) continue;
97 : }
98 :
99 18385 : while (p != next)
100 : {
101 6135 : res.append(*p);
102 6135 : ++p;
103 : }
104 6125 : p = next;
105 : }
106 659 : }
107 :
108 : using com::sun::star::uno::Reference;
109 : using com::sun::star::xml::sax::XAttributeList;
110 : using com::sun::star::xml::sax::XDocumentHandler;
111 :
112 121 : DocumentHandler::DocumentHandler(Reference < XDocumentHandler > &xHandler) :
113 121 : mxHandler(xHandler)
114 : {
115 121 : }
116 :
117 120 : void DocumentHandler::startDocument()
118 : {
119 120 : mxHandler->startDocument();
120 120 : }
121 :
122 120 : void DocumentHandler::endDocument()
123 : {
124 120 : mxHandler->endDocument();
125 120 : }
126 :
127 27804 : void DocumentHandler::startElement(const char *psName, const librevenge::RVNGPropertyList &xPropList)
128 : {
129 27804 : SvXMLAttributeList *pAttrList = new SvXMLAttributeList();
130 27804 : Reference < XAttributeList > xAttrList(pAttrList);
131 55608 : librevenge::RVNGPropertyList::Iter i(xPropList);
132 119535 : for (i.rewind(); i.next();)
133 : {
134 : // filter out librevenge elements
135 63927 : if (strncmp(i.key(), "librevenge", 10) != 0)
136 : {
137 63927 : size_t keyLength=strlen(i.key());
138 63927 : OUString sName(i.key(), keyLength, RTL_TEXTENCODING_UTF8);
139 127854 : OUString sValue(i()->getStr().cstr(), strlen(i()->getStr().cstr()), RTL_TEXTENCODING_UTF8);
140 :
141 : // libodfgen xml-encodes some attribute's value, so check if the value is encoded or not
142 633959 : for (int j=0; j<9; ++j)
143 : {
144 : // list of the encoded attributes followed by their lengths
145 : static char const *(listEncoded[9])=
146 : {
147 : "draw:name", "svg:font-family", "style:condition", "style:num-prefix", "style:num-suffix",
148 : "table:formula", "text:bullet-char", "text:label", "xlink:href"
149 : };
150 : static size_t const(listEncodedLength[9])= {9,15,15,16,16,13,16,10,10};
151 570691 : if (keyLength==listEncodedLength[j] && strncmp(i.key(), listEncoded[j], keyLength)==0)
152 : {
153 659 : librevenge::RVNGString decodedValue("");
154 659 : unescapeXML(i()->getStr().cstr(), (unsigned long) strlen(i()->getStr().cstr()), decodedValue);
155 659 : sValue=OUString(decodedValue.cstr(), strlen(decodedValue.cstr()), RTL_TEXTENCODING_UTF8);
156 659 : break;
157 : }
158 : }
159 127854 : pAttrList->AddAttribute(sName, sValue);
160 : }
161 : }
162 :
163 55608 : OUString sElementName(psName, strlen(psName), RTL_TEXTENCODING_UTF8);
164 55608 : mxHandler->startElement(sElementName, xAttrList);
165 27804 : }
166 :
167 27804 : void DocumentHandler::endElement(const char *psName)
168 : {
169 27804 : OUString sElementName(psName, strlen(psName), RTL_TEXTENCODING_UTF8);
170 27804 : mxHandler->endElement(sElementName);
171 27804 : }
172 :
173 5406 : void DocumentHandler::characters(const librevenge::RVNGString &sCharacters)
174 : {
175 5406 : OUString sCharU16(sCharacters.cstr(), strlen(sCharacters.cstr()), RTL_TEXTENCODING_UTF8);
176 5406 : mxHandler->characters(sCharU16);
177 5406 : }
178 :
179 : }
180 :
181 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|