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 <writerperfect/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) (char const *)((p) + librvng_utf8_skip_data[*((unsigned char const *)p)])
36 :
37 1232 : static void unescapeXML(const char *s, const unsigned long sz, librevenge::RVNGString &res)
38 : {
39 1232 : const char *p = s;
40 1232 : const char *const end = p + sz;
41 13898 : while (p != end)
42 : {
43 11434 : const char *const next = librvng_utf8_next_char(p);
44 11434 : if (next > end)
45 : {
46 : // oops, the string is invalid
47 0 : break;
48 : }
49 11434 : if (p+4 <= end && p+1==next && *p=='&')
50 : {
51 : // look for & , < , > , ' , "
52 16 : bool escapedChar=false;
53 16 : 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 16 : if (p+6 <= end && strncmp(p,""",6)==0)
87 : {
88 16 : res.append('"');
89 16 : p+=6;
90 16 : escapedChar=true;
91 : }
92 16 : break;
93 : default:
94 0 : break;
95 : }
96 16 : if (escapedChar) continue;
97 : }
98 :
99 34274 : while (p != next)
100 : {
101 11438 : res.append(*p);
102 11438 : ++p;
103 : }
104 11418 : p = next;
105 : }
106 1232 : }
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 226 : DocumentHandler::DocumentHandler(Reference < XDocumentHandler > &xHandler) :
113 226 : mxHandler(xHandler)
114 : {
115 226 : }
116 :
117 226 : void DocumentHandler::startDocument()
118 : {
119 226 : mxHandler->startDocument();
120 226 : }
121 :
122 226 : void DocumentHandler::endDocument()
123 : {
124 226 : mxHandler->endDocument();
125 226 : }
126 :
127 53384 : void DocumentHandler::startElement(const char *psName, const librevenge::RVNGPropertyList &xPropList)
128 : {
129 53384 : SvXMLAttributeList *pAttrList = new SvXMLAttributeList();
130 53384 : Reference < XAttributeList > xAttrList(pAttrList);
131 106768 : librevenge::RVNGPropertyList::Iter i(xPropList);
132 229206 : for (i.rewind(); i.next();)
133 : {
134 : // filter out librevenge elements
135 122438 : if (strncmp(i.key(), "librevenge", 10) != 0)
136 : {
137 122118 : size_t keyLength=strlen(i.key());
138 122118 : OUString sName(i.key(), keyLength, RTL_TEXTENCODING_UTF8);
139 244236 : 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 1211292 : 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 1090406 : if (keyLength==listEncodedLength[j] && strncmp(i.key(), listEncoded[j], keyLength)==0)
152 : {
153 1232 : librevenge::RVNGString decodedValue("");
154 1232 : unescapeXML(i()->getStr().cstr(), (unsigned long) strlen(i()->getStr().cstr()), decodedValue);
155 1232 : sValue=OUString(decodedValue.cstr(), strlen(decodedValue.cstr()), RTL_TEXTENCODING_UTF8);
156 1232 : break;
157 : }
158 : }
159 244236 : pAttrList->AddAttribute(sName, sValue);
160 : }
161 : }
162 :
163 106768 : OUString sElementName(psName, strlen(psName), RTL_TEXTENCODING_UTF8);
164 106768 : mxHandler->startElement(sElementName, xAttrList);
165 53384 : }
166 :
167 53384 : void DocumentHandler::endElement(const char *psName)
168 : {
169 53384 : OUString sElementName(psName, strlen(psName), RTL_TEXTENCODING_UTF8);
170 53384 : mxHandler->endElement(sElementName);
171 53384 : }
172 :
173 10420 : void DocumentHandler::characters(const librevenge::RVNGString &sCharacters)
174 : {
175 10420 : OUString sCharU16(sCharacters.cstr(), strlen(sCharacters.cstr()), RTL_TEXTENCODING_UTF8);
176 10420 : mxHandler->characters(sCharU16);
177 10420 : }
178 :
179 : }
180 :
181 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|