Branch data Line data Source code
1 : : /*
2 : : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
3 : : *
4 : : * The contents of this file are subject to the Mozilla Public License Version
5 : : * 1.1 (the "License"); you may not use this file except in compliance with
6 : : * the License. You may obtain a copy of the License at
7 : : * http://www.mozilla.org/MPL/
8 : : *
9 : : * Software distributed under the License is distributed on an "AS IS" basis,
10 : : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 : : * for the specific language governing rights and limitations under the
12 : : * License.
13 : : *
14 : : * The Initial Developer of the Original Code is
15 : : * Miklos Vajna <vmiklos@frugalware.org>
16 : : * Portions created by the Initial Developer are Copyright (C) 2011 the
17 : : * Initial Developer. All Rights Reserved.
18 : : *
19 : : * Contributor(s):
20 : : *
21 : : * Alternatively, the contents of this file may be used under the terms of
22 : : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
23 : : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
24 : : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
25 : : * instead of those above.
26 : : */
27 : :
28 : : #include <tools/stream.hxx>
29 : : #include <tools/resmgr.hxx>
30 : : #include <svx/dialogs.hrc>
31 : : #include <vcl/svapp.hxx>
32 : :
33 : : #include <rtftokenizer.hxx>
34 : : #include <rtfskipdestination.hxx>
35 : :
36 : : using rtl::OString;
37 : : using rtl::OStringBuffer;
38 : : using rtl::OUString;
39 : : using rtl::OUStringBuffer;
40 : : using rtl::OUStringToOString;
41 : :
42 : : namespace writerfilter {
43 : : namespace rtftok {
44 : :
45 : 336 : RTFTokenizer::RTFTokenizer(RTFDocumentImpl& rImport, SvStream* pInStream, uno::Reference<task::XStatusIndicator> const& xStatusIndicator)
46 : : : m_rImport(rImport),
47 : : m_pInStream(pInStream),
48 : : m_xStatusIndicator(xStatusIndicator),
49 [ + - ]: 336 : m_aRTFControlWords(std::vector<RTFSymbol>(aRTFControlWords, aRTFControlWords + nRTFControlWords))
50 : : {
51 [ + - ]: 336 : std::sort(m_aRTFControlWords.begin(), m_aRTFControlWords.end());
52 : 336 : }
53 : :
54 : 336 : RTFTokenizer::~RTFTokenizer()
55 : : {
56 [ - + ]: 672 : }
57 : :
58 : 2292714 : SvStream& RTFTokenizer::Strm()
59 : : {
60 : 2292714 : return *m_pInStream;
61 : : }
62 : :
63 : 336 : int RTFTokenizer::resolveParse()
64 : : {
65 : : SAL_INFO( "writerfilter", OSL_THIS_FUNC );
66 : : char ch;
67 : : int ret;
68 : : // for hex chars
69 : 336 : int b = 0, count = 2;
70 : 336 : sal_uInt32 nPercentSize = 0;
71 : 336 : sal_uInt32 nLastPos = 0;
72 : :
73 [ + + ]: 336 : if (m_xStatusIndicator.is())
74 : : {
75 [ + + ][ + - ]: 303 : static ResMgr* pResMgr = ResMgr::CreateResMgr("svx", Application::GetSettings().GetUILocale());
[ + - ][ + - ]
[ + - ][ # # ]
76 [ + - ]: 303 : OUString sDocLoad(ResId(RID_SVXSTR_DOC_LOAD, *pResMgr).toString());
77 : :
78 : 303 : sal_uInt32 nCurrentPos = Strm().Tell();
79 [ + - ]: 303 : Strm().Seek(STREAM_SEEK_TO_END);
80 : 303 : sal_uInt32 nEndPos = Strm().Tell();
81 [ + - ]: 303 : Strm().Seek(nCurrentPos);
82 [ + - ][ + - ]: 303 : m_xStatusIndicator->start(sDocLoad, nEndPos);
83 : 303 : nPercentSize = nEndPos / 100;
84 : :
85 [ + - ][ + - ]: 306 : m_xStatusIndicator->setValue(nLastPos = nCurrentPos);
86 : : }
87 : :
88 [ + - ][ + + ]: 362127 : while ((Strm() >> ch, !Strm().IsEof()))
89 : : {
90 : : //SAL_INFO("writerfilter", OSL_THIS_FUNC << ": parsing character '" << ch << "'");
91 : :
92 : : sal_uInt32 nCurrentPos;
93 [ + + ][ + + ]: 362121 : if (m_xStatusIndicator.is() && (nCurrentPos = Strm().Tell()) > (nLastPos + nPercentSize))
[ + + ]
94 [ + - ][ + - ]: 11697 : m_xStatusIndicator->setValue(nLastPos = nCurrentPos);
95 : :
96 [ + - ][ - + ]: 362121 : if (m_rImport.getGroup() < 0)
97 : 0 : return ERROR_GROUP_UNDER;
98 [ + - ][ + + ]: 362121 : if (m_rImport.getGroup() > 0 && m_rImport.getState().nInternalState == INTERNAL_BIN)
[ + - ][ + + ]
[ + + ]
99 : : {
100 [ + - ]: 3 : ret = m_rImport.resolveChars(ch);
101 [ - + ]: 3 : if (ret)
102 : 0 : return ret;
103 : : }
104 : : else
105 : : {
106 [ + + + + : 362118 : switch (ch)
+ ]
107 : : {
108 : : case '{':
109 [ + - ]: 15081 : ret = m_rImport.pushState();
110 [ - + ]: 15081 : if (ret)
111 : 0 : return ret;
112 : 15081 : break;
113 : : case '}':
114 [ + - ]: 15072 : ret = m_rImport.popState();
115 [ - + ]: 15072 : if (ret)
116 : 0 : return ret;
117 [ + - ][ + + ]: 15072 : if (m_rImport.getGroup() == 0)
118 : : {
119 [ + - ][ + + ]: 327 : if (m_rImport.isSubstream())
120 [ + - ]: 21 : m_rImport.finishSubstream();
121 : 327 : return 0;
122 : : }
123 : 14745 : break;
124 : : case '\\':
125 [ + + ]: 156591 : ret = resolveKeyword();
126 [ - + ]: 156588 : if (ret)
127 : 0 : return ret;
128 : 156588 : break;
129 : : case 0x0d:
130 : : case 0x0a:
131 : 22302 : break; // ignore these
132 : : default:
133 [ + - ][ - + ]: 153072 : if (m_rImport.getGroup() == 0)
134 : 0 : return ERROR_CHAR_OVER;
135 [ + - ][ + + ]: 153072 : if (m_rImport.getState().nInternalState == INTERNAL_NORMAL)
136 : : {
137 [ + - ]: 12930 : ret = m_rImport.resolveChars(ch);
138 [ - + ]: 12930 : if (ret)
139 : 0 : return ret;
140 : : }
141 : : else
142 : : {
143 : : SAL_INFO("writerfilter", OSL_THIS_FUNC << ": hex internal state");
144 : 140142 : b = b << 4;
145 : 140142 : sal_Int8 parsed = asHex(ch);
146 [ - + ]: 140142 : if (parsed == -1)
147 : 0 : return ERROR_HEX_INVALID;
148 : 140142 : b += parsed;
149 : 140142 : count--;
150 [ + + ]: 140142 : if (!count)
151 : : {
152 [ + - ]: 70071 : ret = m_rImport.resolveChars(b);
153 [ - + ]: 70071 : if (ret)
154 : 0 : return ret;
155 : 70071 : count = 2;
156 : 70071 : b = 0;
157 [ + - ]: 70071 : m_rImport.getState().nInternalState = INTERNAL_NORMAL;
158 : : }
159 : : }
160 : 153072 : break;
161 : : }
162 : : }
163 : : }
164 : :
165 [ + - ][ - + ]: 6 : if (m_rImport.getGroup() < 0)
166 : 0 : return ERROR_GROUP_UNDER;
167 [ + - ][ + - ]: 6 : else if (m_rImport.getGroup() > 0)
168 : 6 : return ERROR_GROUP_OVER;
169 : 333 : return 0;
170 : : }
171 : :
172 : 148026 : int RTFTokenizer::asHex(char ch)
173 : : {
174 : 148026 : int ret = 0;
175 [ + + ]: 148026 : if (isdigit(ch))
176 : 125508 : ret = ch - '0';
177 : : else
178 : : {
179 [ + - ]: 22518 : if (islower(ch))
180 : : {
181 [ + - ][ - + ]: 22518 : if (ch < 'a' || ch > 'f')
182 : 0 : return -1;
183 : 22518 : ret = ch - 'a';
184 : : }
185 : : else
186 : : {
187 [ # # ][ # # ]: 0 : if (ch < 'A' || ch > 'F')
188 : 0 : return -1;
189 : 0 : ret = ch - 'A';
190 : : }
191 : 22518 : ret += 10;
192 : : }
193 : 148026 : return ret;
194 : : }
195 : :
196 : 156591 : int RTFTokenizer::resolveKeyword()
197 : : {
198 : : char ch;
199 : 156591 : OStringBuffer aBuf;
200 : 156591 : bool bNeg = false;
201 : 156591 : bool bParam = false;
202 : 156591 : int nParam = 0;
203 : :
204 [ + - ]: 156591 : Strm() >> ch;
205 [ - + ]: 156591 : if (Strm().IsEof())
206 : 0 : return ERROR_EOF;
207 : :
208 [ + + ]: 156591 : if (!isalpha(ch))
209 : : {
210 [ + - ]: 72165 : aBuf.append(ch);
211 : 72165 : OString aKeyword = aBuf.makeStringAndClear();
212 : : // control symbols aren't followed by a space, so we can return here
213 : : // without doing any SeekRel()
214 [ + - ]: 72165 : return dispatchKeyword(aKeyword, bParam, nParam);
215 : : }
216 [ + + ]: 507558 : while(isalpha(ch))
217 : : {
218 [ + - ]: 423135 : aBuf.append(ch);
219 [ + - ]: 423135 : Strm() >> ch;
220 [ + + ]: 423135 : if (Strm().IsEof())
221 : : {
222 : 3 : ch = ' ';
223 : 3 : break;
224 : : }
225 : : }
226 [ + + ]: 84426 : if (aBuf.getLength() > 32)
227 : : // See RTF spec v1.9.1, page 7
228 : : // A control word's name cannot be longer than 32 letters.
229 [ + - ]: 3 : throw io::BufferSizeExceededException();
230 : :
231 [ + + ]: 84423 : if (ch == '-')
232 : : {
233 : : // in case we'll have a parameter, that will be negative
234 : 300 : bNeg = true;
235 [ + - ]: 300 : Strm() >> ch;
236 [ - + ]: 300 : if (Strm().IsEof())
237 : 0 : return ERROR_EOF;
238 : : }
239 [ + + ]: 84423 : if (isdigit(ch))
240 : : {
241 : 47220 : OStringBuffer aParameter;
242 : :
243 : : // we have a parameter
244 : 47220 : bParam = true;
245 [ + + ]: 153543 : while(isdigit(ch))
246 : : {
247 [ + - ]: 106323 : aParameter.append(ch);
248 [ + - ]: 106323 : Strm() >> ch;
249 [ - + ]: 106323 : if (Strm().IsEof())
250 : : {
251 : 0 : ch = ' ';
252 : 0 : break;
253 : : }
254 : : }
255 : 47220 : nParam = aParameter.makeStringAndClear().toInt32();
256 [ + + ]: 47220 : if (bNeg)
257 : 47220 : nParam = -nParam;
258 : : }
259 [ + + ]: 84423 : if (ch != ' ')
260 [ + - ]: 61131 : Strm().SeekRel(-1);
261 : 84423 : OString aKeyword = aBuf.makeStringAndClear();
262 [ + - ]: 156591 : return dispatchKeyword(aKeyword, bParam, nParam);
263 : : }
264 : :
265 : 156588 : int RTFTokenizer::dispatchKeyword(OString& rKeyword, bool bParam, int nParam)
266 : : {
267 [ + - ][ + + ]: 156588 : if (m_rImport.getState().nDestinationState == DESTINATION_SKIP)
268 : 9336 : return 0;
269 : : /*SAL_INFO("writefilter", OSL_THIS_FUNC << ": keyword '\\" << rKeyword.getStr() <<
270 : : "' with param? " << (bParam ? 1 : 0) <<" param val: '" << (bParam ? nParam : 0) << "'");*/
271 : : RTFSymbol aSymbol;
272 : 147252 : aSymbol.sKeyword = rKeyword.getStr();
273 [ + - ]: 147252 : std::vector<RTFSymbol>::iterator low = std::lower_bound(m_aRTFControlWords.begin(), m_aRTFControlWords.end(), aSymbol);
274 [ + - ]: 147252 : int i = low - m_aRTFControlWords.begin();
275 [ + - ][ + - ]: 147252 : if (low == m_aRTFControlWords.end() || aSymbol < *low)
[ + - ][ + + ]
[ + - ]
[ + + # # ]
276 : : {
277 : : SAL_INFO("writerfilter", OSL_THIS_FUNC << ": unknown keyword '\\" << rKeyword.getStr() << "'");
278 [ + - ]: 528 : RTFSkipDestination aSkip(m_rImport);
279 [ + - ]: 528 : aSkip.setParsed(false);
280 [ + - ]: 528 : return 0;
281 : : }
282 : :
283 : : int ret;
284 [ + + + + : 146724 : switch (m_aRTFControlWords[i].nControlType)
+ - ]
285 : : {
286 : : case CONTROL_FLAG:
287 : : // flags ignore any parameter by definition
288 [ + - ]: 23511 : ret = m_rImport.dispatchFlag(m_aRTFControlWords[i].nIndex);
289 [ - + ]: 23511 : if (ret)
290 : 0 : return ret;
291 : 23511 : break;
292 : : case CONTROL_DESTINATION:
293 : : // same for destinations
294 [ + - ]: 8187 : ret = m_rImport.dispatchDestination(m_aRTFControlWords[i].nIndex);
295 [ - + ]: 8187 : if (ret)
296 : 0 : return ret;
297 : 8187 : break;
298 : : case CONTROL_SYMBOL:
299 : : // and symbols
300 [ + - ]: 73734 : ret = m_rImport.dispatchSymbol(m_aRTFControlWords[i].nIndex);
301 [ - + ]: 73734 : if (ret)
302 : 0 : return ret;
303 : 73734 : break;
304 : : case CONTROL_TOGGLE:
305 [ + - ]: 1299 : ret = m_rImport.dispatchToggle(m_aRTFControlWords[i].nIndex, bParam, nParam);
306 [ - + ]: 1299 : if (ret)
307 : 0 : return ret;
308 : 1299 : break;
309 : : case CONTROL_VALUE:
310 : : // values require a parameter by definition
311 [ + + ]: 39993 : if (bParam) {
312 [ + - ]: 39879 : ret = m_rImport.dispatchValue(m_aRTFControlWords[i].nIndex, nParam);
313 [ - + ]: 39879 : if (ret)
314 : 0 : return ret;
315 : : }
316 : 39993 : break;
317 : : }
318 : :
319 : 156588 : return 0;
320 : : }
321 : :
322 : : } // namespace rtftok
323 [ + - ][ + - ]: 60 : } // namespace writerfilter
324 : :
325 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|