Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <ctype.h>
31 : : #include <stdio.h>
32 : : #include <comphelper/string.hxx>
33 : : #include <tools/stream.hxx>
34 : : #include <tools/debug.hxx>
35 : : #include <tools/color.hxx>
36 : : #include <rtl/ustrbuf.hxx>
37 : : #include <rtl/strbuf.hxx>
38 : :
39 : : #include <tools/tenccvt.hxx>
40 : : #include <tools/datetime.hxx>
41 : : #include <svl/inettype.hxx>
42 : : #include <com/sun/star/beans/PropertyAttribute.hpp>
43 : : #include <com/sun/star/document/XDocumentProperties.hpp>
44 : :
45 : : #include <svtools/parhtml.hxx>
46 : : #include <svtools/htmltokn.h>
47 : : #include <svtools/htmlkywd.hxx>
48 : :
49 : : #include <memory>
50 : :
51 : : using namespace ::com::sun::star;
52 : :
53 : :
54 : : const sal_Int32 MAX_LEN( 1024L );
55 : :
56 : : const sal_Int32 MAX_ENTITY_LEN( 8L );
57 : :
58 : :
59 : : // Tables to convert option values into strings
60 : :
61 : : // <INPUT TYPE=xxx>
62 : : static HTMLOptionEnum const aInputTypeOptEnums[] =
63 : : {
64 : : { OOO_STRING_SVTOOLS_HTML_IT_text, HTML_IT_TEXT },
65 : : { OOO_STRING_SVTOOLS_HTML_IT_password, HTML_IT_PASSWORD },
66 : : { OOO_STRING_SVTOOLS_HTML_IT_checkbox, HTML_IT_CHECKBOX },
67 : : { OOO_STRING_SVTOOLS_HTML_IT_radio, HTML_IT_RADIO },
68 : : { OOO_STRING_SVTOOLS_HTML_IT_range, HTML_IT_RANGE },
69 : : { OOO_STRING_SVTOOLS_HTML_IT_scribble, HTML_IT_SCRIBBLE },
70 : : { OOO_STRING_SVTOOLS_HTML_IT_file, HTML_IT_FILE },
71 : : { OOO_STRING_SVTOOLS_HTML_IT_hidden, HTML_IT_HIDDEN },
72 : : { OOO_STRING_SVTOOLS_HTML_IT_submit, HTML_IT_SUBMIT },
73 : : { OOO_STRING_SVTOOLS_HTML_IT_image, HTML_IT_IMAGE },
74 : : { OOO_STRING_SVTOOLS_HTML_IT_reset, HTML_IT_RESET },
75 : : { OOO_STRING_SVTOOLS_HTML_IT_button, HTML_IT_BUTTON },
76 : : { 0, 0 }
77 : : };
78 : :
79 : : // <TABLE FRAME=xxx>
80 : : static HTMLOptionEnum const aTableFrameOptEnums[] =
81 : : {
82 : : { OOO_STRING_SVTOOLS_HTML_TF_void, HTML_TF_VOID },
83 : : { OOO_STRING_SVTOOLS_HTML_TF_above, HTML_TF_ABOVE },
84 : : { OOO_STRING_SVTOOLS_HTML_TF_below, HTML_TF_BELOW },
85 : : { OOO_STRING_SVTOOLS_HTML_TF_hsides, HTML_TF_HSIDES },
86 : : { OOO_STRING_SVTOOLS_HTML_TF_lhs, HTML_TF_LHS },
87 : : { OOO_STRING_SVTOOLS_HTML_TF_rhs, HTML_TF_RHS },
88 : : { OOO_STRING_SVTOOLS_HTML_TF_vsides, HTML_TF_VSIDES },
89 : : { OOO_STRING_SVTOOLS_HTML_TF_box, HTML_TF_BOX },
90 : : { OOO_STRING_SVTOOLS_HTML_TF_border, HTML_TF_BOX },
91 : : { 0, 0 }
92 : : };
93 : :
94 : : // <TABLE RULES=xxx>
95 : : static HTMLOptionEnum const aTableRulesOptEnums[] =
96 : : {
97 : : { OOO_STRING_SVTOOLS_HTML_TR_none, HTML_TR_NONE },
98 : : { OOO_STRING_SVTOOLS_HTML_TR_groups, HTML_TR_GROUPS },
99 : : { OOO_STRING_SVTOOLS_HTML_TR_rows, HTML_TR_ROWS },
100 : : { OOO_STRING_SVTOOLS_HTML_TR_cols, HTML_TR_COLS },
101 : : { OOO_STRING_SVTOOLS_HTML_TR_all, HTML_TR_ALL },
102 : : { 0, 0 }
103 : : };
104 : :
105 : 0 : sal_uInt16 HTMLOption::GetEnum( const HTMLOptionEnum *pOptEnums, sal_uInt16 nDflt ) const
106 : : {
107 : 0 : sal_uInt16 nValue = nDflt;
108 : :
109 [ # # ]: 0 : while( pOptEnums->pName )
110 [ # # ]: 0 : if( aValue.EqualsIgnoreCaseAscii( pOptEnums->pName ) )
111 : 0 : break;
112 : : else
113 : 0 : pOptEnums++;
114 : :
115 [ # # ]: 0 : if( pOptEnums->pName )
116 : 0 : nValue = pOptEnums->nValue;
117 : :
118 : 0 : return nValue;
119 : : }
120 : :
121 : 8 : bool HTMLOption::GetEnum( sal_uInt16 &rEnum, const HTMLOptionEnum *pOptEnums ) const
122 : : {
123 [ + - ]: 44 : while( pOptEnums->pName )
124 : : {
125 [ + + ]: 44 : if( aValue.EqualsIgnoreCaseAscii( pOptEnums->pName ) )
126 : 8 : break;
127 : : else
128 : 36 : pOptEnums++;
129 : : }
130 : :
131 : 8 : const sal_Char *pName = pOptEnums->pName;
132 [ + - ]: 8 : if( pName )
133 : 8 : rEnum = pOptEnums->nValue;
134 : :
135 : 8 : return (pName != 0);
136 : : }
137 : :
138 : 20 : HTMLOption::HTMLOption( sal_uInt16 nTok, const String& rToken,
139 : : const String& rValue )
140 : : : aValue(rValue)
141 : : , aToken(rToken)
142 [ + - ]: 20 : , nToken( nTok )
143 : : {
144 : : DBG_ASSERT( nToken>=HTML_OPTION_START && nToken<HTML_OPTION_END,
145 : : "HTMLOption: unknown token" );
146 : 20 : }
147 : :
148 : 0 : sal_uInt32 HTMLOption::GetNumber() const
149 : : {
150 : : DBG_ASSERT( (nToken>=HTML_OPTION_NUMBER_START &&
151 : : nToken<HTML_OPTION_NUMBER_END) ||
152 : : (nToken>=HTML_OPTION_CONTEXT_START &&
153 : : nToken<HTML_OPTION_CONTEXT_END) ||
154 : : nToken==HTML_O_VALUE,
155 : : "GetNumber: Option not numerical" );
156 [ # # ][ # # ]: 0 : String aTmp(comphelper::string::stripStart(aValue, ' '));
[ # # ]
157 [ # # ]: 0 : sal_Int32 nTmp = aTmp.ToInt32();
158 [ # # ]: 0 : return nTmp >= 0 ? (sal_uInt32)nTmp : 0;
159 : : }
160 : :
161 : 0 : sal_Int32 HTMLOption::GetSNumber() const
162 : : {
163 : : DBG_ASSERT( (nToken>=HTML_OPTION_NUMBER_START && nToken<HTML_OPTION_NUMBER_END) ||
164 : : (nToken>=HTML_OPTION_CONTEXT_START && nToken<HTML_OPTION_CONTEXT_END),
165 : : "GetSNumber: Option not numerical" );
166 [ # # ][ # # ]: 0 : String aTmp(comphelper::string::stripStart(aValue, ' '));
[ # # ]
167 [ # # ][ # # ]: 0 : return aTmp.ToInt32();
168 : : }
169 : :
170 : 0 : void HTMLOption::GetNumbers( std::vector<sal_uInt32> &rNumbers, bool bSpaceDelim ) const
171 : : {
172 : 0 : rNumbers.clear();
173 : :
174 [ # # ]: 0 : if( bSpaceDelim )
175 : : {
176 : : // This is a very simplified scanner: it only searches all
177 : : // numerals in the string.
178 : 0 : bool bInNum = false;
179 : 0 : sal_uLong nNum = 0;
180 [ # # ]: 0 : for( xub_StrLen i=0; i<aValue.Len(); i++ )
181 : : {
182 : 0 : register sal_Unicode c = aValue.GetChar( i );
183 [ # # ][ # # ]: 0 : if( c>='0' && c<='9' )
184 : : {
185 : 0 : nNum *= 10;
186 : 0 : nNum += (c - '0');
187 : 0 : bInNum = true;
188 : : }
189 [ # # ]: 0 : else if( bInNum )
190 : : {
191 [ # # ]: 0 : rNumbers.push_back( nNum );
192 : 0 : bInNum = false;
193 : 0 : nNum = 0;
194 : : }
195 : : }
196 [ # # ]: 0 : if( bInNum )
197 : : {
198 [ # # ]: 0 : rNumbers.push_back( nNum );
199 : : }
200 : : }
201 : : else
202 : : {
203 : : // Check whether numbers are separated by ',' and
204 : : // insert 0 if necessary
205 : 0 : xub_StrLen nPos = 0;
206 [ # # ]: 0 : while( nPos < aValue.Len() )
207 : : {
208 : : register sal_Unicode c;
209 [ # # ][ # # ]: 0 : while( nPos < aValue.Len() &&
[ # # ][ # # ]
[ # # ][ # # ]
210 : 0 : ((c=aValue.GetChar(nPos)) == ' ' || c == '\t' ||
211 : : c == '\n' || c== '\r' ) )
212 : 0 : nPos++;
213 : :
214 [ # # ]: 0 : if( nPos==aValue.Len() )
215 [ # # ]: 0 : rNumbers.push_back(0);
216 : : else
217 : : {
218 : 0 : xub_StrLen nEnd = aValue.Search( (sal_Unicode)',', nPos );
219 [ # # ]: 0 : if( STRING_NOTFOUND==nEnd )
220 : : {
221 [ # # ]: 0 : sal_Int32 nTmp = aValue.Copy(nPos).ToInt32();
222 [ # # ]: 0 : rNumbers.push_back( nTmp >= 0 ? (sal_uInt32)nTmp : 0 );
223 : 0 : nPos = aValue.Len();
224 : : }
225 : : else
226 : : {
227 : : sal_Int32 nTmp =
228 [ # # ]: 0 : aValue.Copy(nPos,nEnd-nPos).ToInt32();
229 [ # # ]: 0 : rNumbers.push_back( nTmp >= 0 ? (sal_uInt32)nTmp : 0 );
230 : 0 : nPos = nEnd+1;
231 : : }
232 : : }
233 : : }
234 : : }
235 : 0 : }
236 : :
237 : 0 : void HTMLOption::GetColor( Color& rColor ) const
238 : : {
239 : : DBG_ASSERT( (nToken>=HTML_OPTION_COLOR_START && nToken<HTML_OPTION_COLOR_END) || nToken==HTML_O_SIZE,
240 : : "GetColor: Option is not a color." );
241 : :
242 [ # # ]: 0 : String aTmp( aValue );
243 [ # # ]: 0 : aTmp.ToUpperAscii();
244 : 0 : sal_uInt32 nColor = SAL_MAX_UINT32;
245 [ # # ]: 0 : if( '#'!=aTmp.GetChar( 0 ) )
246 [ # # ]: 0 : nColor = GetHTMLColor( aTmp );
247 : :
248 [ # # ]: 0 : if( SAL_MAX_UINT32 == nColor )
249 : : {
250 : 0 : nColor = 0;
251 : 0 : xub_StrLen nPos = 0;
252 [ # # ]: 0 : for( sal_uInt32 i=0; i<6; i++ )
253 : : {
254 : : // Whatever Netscape does to get color values,
255 : : // at maximum three characters < '0' are ignored.
256 : 0 : register sal_Unicode c = nPos<aTmp.Len() ? aTmp.GetChar( nPos++ )
257 [ # # ]: 0 : : '0';
258 [ # # ]: 0 : if( c < '0' )
259 : : {
260 [ # # ]: 0 : c = nPos<aTmp.Len() ? aTmp.GetChar(nPos++) : '0';
261 [ # # ]: 0 : if( c < '0' )
262 [ # # ]: 0 : c = nPos<aTmp.Len() ? aTmp.GetChar(nPos++) : '0';
263 : : }
264 : 0 : nColor *= 16;
265 [ # # ][ # # ]: 0 : if( c >= '0' && c <= '9' )
266 : 0 : nColor += (c - 48);
267 [ # # ][ # # ]: 0 : else if( c >= 'A' && c <= 'F' )
268 : 0 : nColor += (c - 55);
269 : : }
270 : : }
271 : :
272 [ # # ]: 0 : rColor.SetRed( (sal_uInt8)((nColor & 0x00ff0000) >> 16) );
273 [ # # ]: 0 : rColor.SetGreen( (sal_uInt8)((nColor & 0x0000ff00) >> 8));
274 [ # # ][ # # ]: 0 : rColor.SetBlue( (sal_uInt8)(nColor & 0x000000ff) );
275 : 0 : }
276 : :
277 : 0 : HTMLInputType HTMLOption::GetInputType() const
278 : : {
279 : : DBG_ASSERT( nToken==HTML_O_TYPE, "GetInputType: Option not TYPE" );
280 : 0 : return (HTMLInputType)GetEnum( aInputTypeOptEnums, HTML_IT_TEXT );
281 : : }
282 : :
283 : 0 : HTMLTableFrame HTMLOption::GetTableFrame() const
284 : : {
285 : : DBG_ASSERT( nToken==HTML_O_FRAME, "GetTableFrame: Option not FRAME" );
286 : 0 : return (HTMLTableFrame)GetEnum( aTableFrameOptEnums, HTML_TF_VOID );
287 : : }
288 : :
289 : 0 : HTMLTableRules HTMLOption::GetTableRules() const
290 : : {
291 : : DBG_ASSERT( nToken==HTML_O_RULES, "GetTableRules: Option not RULES" );
292 : 0 : return (HTMLTableRules)GetEnum( aTableRulesOptEnums, HTML_TR_NONE );
293 : : }
294 : :
295 : 5 : HTMLParser::HTMLParser( SvStream& rIn, bool bReadNewDoc ) :
296 : : SvParser( rIn ),
297 : : bNewDoc(bReadNewDoc),
298 : : bIsInHeader(true),
299 : : bIsInBody(false),
300 : : bReadListing(false),
301 : : bReadXMP(false),
302 : : bReadPRE(false),
303 : : bReadTextArea(false),
304 : : bReadScript(false),
305 : : bReadStyle(false),
306 : : bEndTokenFound(false),
307 : : bPre_IgnoreNewPara(false),
308 : : bReadNextChar(false),
309 [ + - ][ + - ]: 5 : bReadComment(false)
[ + - ]
310 : : {
311 : : //#i76649, default to UTF-8 for HTML unless we know differently
312 [ + - ]: 5 : SetSrcEncoding(RTL_TEXTENCODING_UTF8);
313 : 5 : }
314 : :
315 [ + - ][ + - ]: 5 : HTMLParser::~HTMLParser()
[ + - ]
316 : : {
317 [ - + ]: 5 : }
318 : :
319 : 5 : SvParserState HTMLParser::CallParser()
320 : : {
321 : 5 : eState = SVPAR_WORKING;
322 : 5 : nNextCh = GetNextChar();
323 : 5 : SaveState( 0 );
324 : :
325 : 5 : nPre_LinePos = 0;
326 : 5 : bPre_IgnoreNewPara = false;
327 : :
328 : 5 : AddRef();
329 : 5 : Continue( 0 );
330 [ + - ]: 5 : if( SVPAR_PENDING != eState )
331 : 5 : ReleaseRef(); // Parser not needed anymore
332 : :
333 : 5 : return eState;
334 : : }
335 : :
336 : 5 : void HTMLParser::Continue( int nToken )
337 : : {
338 [ + - ]: 5 : if( !nToken )
339 : 5 : nToken = GetNextToken();
340 : :
341 [ + + ]: 170 : while( IsParserWorking() )
342 : : {
343 : 165 : SaveState( nToken );
344 : 165 : nToken = FilterToken( nToken );
345 : :
346 [ + + ]: 165 : if( nToken )
347 : 160 : NextToken( nToken );
348 : :
349 [ + - ]: 165 : if( IsParserWorking() )
350 : 165 : SaveState( 0 ); // continue with new token
351 : :
352 : 165 : nToken = GetNextToken();
353 : : }
354 : 5 : }
355 : :
356 : 165 : int HTMLParser::FilterToken( int nToken )
357 : : {
358 [ - + + + : 165 : switch( nToken )
+ + - - -
- - - + ]
359 : : {
360 : : case sal_Unicode(EOF):
361 : 0 : nToken = 0;
362 : 0 : break; // don't pass
363 : :
364 : : case HTML_HEAD_OFF:
365 : 2 : bIsInBody = true;
366 : : case HTML_HEAD_ON:
367 : 4 : bIsInHeader = HTML_HEAD_ON == nToken;
368 : 4 : break;
369 : :
370 : : case HTML_BODY_ON:
371 : : case HTML_FRAMESET_ON:
372 : 5 : bIsInHeader = false;
373 : 5 : bIsInBody = HTML_BODY_ON == nToken;
374 : 5 : break;
375 : :
376 : : case HTML_BODY_OFF:
377 : 5 : bIsInBody = bReadPRE = bReadListing = bReadXMP = false;
378 : 5 : break;
379 : :
380 : : case HTML_HTML_OFF:
381 : 5 : nToken = 0;
382 : 5 : bReadPRE = bReadListing = bReadXMP = false;
383 : 5 : break; // HTML_ON hasn't been passed either !
384 : :
385 : : case HTML_PREFORMTXT_ON:
386 : 0 : StartPRE();
387 : 0 : break;
388 : :
389 : : case HTML_PREFORMTXT_OFF:
390 : 0 : FinishPRE();
391 : 0 : break;
392 : :
393 : : case HTML_LISTING_ON:
394 : 0 : StartListing();
395 : 0 : break;
396 : :
397 : : case HTML_LISTING_OFF:
398 : 0 : FinishListing();
399 : 0 : break;
400 : :
401 : : case HTML_XMP_ON:
402 : 0 : StartXMP();
403 : 0 : break;
404 : :
405 : : case HTML_XMP_OFF:
406 : 0 : FinishXMP();
407 : 0 : break;
408 : :
409 : : default:
410 [ - + ]: 146 : if( bReadPRE )
411 : 0 : nToken = FilterPRE( nToken );
412 [ - + ]: 146 : else if( bReadListing )
413 : 0 : nToken = FilterListing( nToken );
414 [ - + ]: 146 : else if( bReadXMP )
415 : 0 : nToken = FilterXMP( nToken );
416 : :
417 : 146 : break;
418 : : }
419 : :
420 : 165 : return nToken;
421 : : }
422 : :
423 : : #define HTML_ISDIGIT( c ) comphelper::string::isdigitAscii(c)
424 : : #define HTML_ISALPHA( c ) comphelper::string::isalphaAscii(c)
425 : : #define HTML_ISALNUM( c ) comphelper::string::isalnumAscii(c)
426 : : #define HTML_ISSPACE( c ) ( ' ' == c || (c >= 0x09 && c <= 0x0d) )
427 : : #define HTML_ISPRINTABLE( c ) ( c >= 32 && c != 127)
428 : : #define HTML_ISHEXDIGIT( c ) comphelper::string::isxdigitAscii(c)
429 : :
430 : 83 : int HTMLParser::ScanText( const sal_Unicode cBreak )
431 : : {
432 : 83 : ::rtl::OUStringBuffer sTmpBuffer( MAX_LEN );
433 : 83 : int bContinue = true;
434 : 83 : int bEqSignFound = false;
435 : 83 : sal_Unicode cQuote = 0U;
436 : :
437 [ + + ][ + - ]: 509 : while( bContinue && IsParserWorking() )
[ + + ]
438 : : {
439 : 429 : int bNextCh = true;
440 [ - + - + : 429 : switch( nNextCh )
- + - + -
- + + ]
441 : : {
442 : : case '&':
443 : 0 : bEqSignFound = false;
444 [ # # ]: 0 : if( bReadXMP )
445 [ # # ]: 0 : sTmpBuffer.append( (sal_Unicode)'&' );
446 : : else
447 : : {
448 : 0 : sal_uLong nStreamPos = rInput.Tell();
449 : 0 : sal_uLong nLinePos = GetLinePos();
450 : :
451 : 0 : sal_Unicode cChar = 0U;
452 [ # # ][ # # ]: 0 : if( '#' == (nNextCh = GetNextChar()) )
453 : : {
454 [ # # ]: 0 : nNextCh = GetNextChar();
455 : 0 : const bool bIsHex( 'x' == nNextCh );
456 [ # # ][ # # ]: 0 : const bool bIsDecOrHex( bIsHex || HTML_ISDIGIT(nNextCh) );
[ # # ]
457 [ # # ]: 0 : if ( bIsDecOrHex )
458 : : {
459 [ # # ]: 0 : if ( bIsHex )
460 : : {
461 [ # # ]: 0 : nNextCh = GetNextChar();
462 [ # # ][ # # ]: 0 : while ( HTML_ISHEXDIGIT(nNextCh) )
463 : : {
464 : : cChar = cChar * 16U +
465 : : ( nNextCh <= '9'
466 : : ? sal_Unicode( nNextCh - '0' )
467 : : : ( nNextCh <= 'F'
468 : : ? sal_Unicode( nNextCh - 'A' + 10 )
469 [ # # ][ # # ]: 0 : : sal_Unicode( nNextCh - 'a' + 10 ) ) );
470 [ # # ]: 0 : nNextCh = GetNextChar();
471 : : }
472 : : }
473 : : else
474 : : {
475 [ # # ][ # # ]: 0 : do
476 : : {
477 : 0 : cChar = cChar * 10U + sal_Unicode( nNextCh - '0');
478 [ # # ]: 0 : nNextCh = GetNextChar();
479 : : }
480 : 0 : while( HTML_ISDIGIT(nNextCh) );
481 : : }
482 : :
483 [ # # ][ # # ]: 0 : if( RTL_TEXTENCODING_DONTKNOW != eSrcEnc &&
[ # # ][ # # ]
484 : : RTL_TEXTENCODING_UCS2 != eSrcEnc &&
485 : : RTL_TEXTENCODING_UTF8 != eSrcEnc &&
486 : : cChar < 256 )
487 : : {
488 : : const sal_uInt32 convertFlags =
489 : : RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT |
490 : : RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
491 : 0 : RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT;
492 : :
493 : 0 : sal_Char cEncodedChar = static_cast<sal_Char>(cChar);
494 [ # # ]: 0 : cChar = rtl::OUString(&cEncodedChar, 1, eSrcEnc, convertFlags).toChar();
495 [ # # ]: 0 : if( 0U == cChar )
496 : : {
497 : : // If the character could not be
498 : : // converted, because a conversion is not
499 : : // available, do no conversion at all.
500 : 0 : cChar = cEncodedChar;
501 : : }
502 : : }
503 : : }
504 : : else
505 : 0 : nNextCh = 0U;
506 : : }
507 [ # # ][ # # ]: 0 : else if( HTML_ISALPHA( nNextCh ) )
508 : : {
509 : 0 : ::rtl::OUStringBuffer sEntityBuffer( MAX_ENTITY_LEN );
510 : 0 : xub_StrLen nPos = 0L;
511 [ # # ]: 0 : do
[ # # # # ]
[ # # ]
512 : : {
513 [ # # ]: 0 : sEntityBuffer.append( nNextCh );
514 : 0 : nPos++;
515 [ # # ]: 0 : nNextCh = GetNextChar();
516 : : }
517 [ # # ]: 0 : while( nPos < MAX_ENTITY_LEN && HTML_ISALNUM( nNextCh ) &&
518 : 0 : !rInput.IsEof() );
519 : :
520 [ # # ][ # # ]: 0 : if( IsParserWorking() && !rInput.IsEof() )
[ # # ]
521 : : {
522 : 0 : rtl::OUString sEntity(sEntityBuffer.getStr(), nPos);
523 [ # # ][ # # ]: 0 : cChar = GetHTMLCharName( sEntity );
[ # # ]
524 : :
525 : : // not found ( == 0 ): plain text
526 : : // or a character which is inserted as attribute
527 [ # # ][ # # ]: 0 : if( 0U == cChar && ';' != nNextCh )
528 : : {
529 : : DBG_ASSERT( rInput.Tell() - nStreamPos ==
530 : : (sal_uLong)(nPos+1L)*GetCharSize(),
531 : : "UTF-8 is failing here" );
532 [ # # ]: 0 : for( xub_StrLen i=nPos-1L; i>1L; i-- )
533 : : {
534 : 0 : nNextCh = sEntityBuffer[i];
535 [ # # ]: 0 : sEntityBuffer.setLength( i );
536 : 0 : sEntity = rtl::OUString(sEntityBuffer.getStr(), i);
537 [ # # ][ # # ]: 0 : cChar = GetHTMLCharName( sEntity );
[ # # ]
538 [ # # ]: 0 : if( cChar )
539 : : {
540 : : rInput.SeekRel( -(long)
541 [ # # ]: 0 : ((nPos-i)*GetCharSize()) );
542 : 0 : nlLinePos -= sal_uInt32(nPos-i);
543 : 0 : nPos = i;
544 [ # # ]: 0 : ClearTxtConvContext();
545 : 0 : break;
546 : : }
547 : : }
548 : : }
549 : :
550 [ # # ]: 0 : if( !cChar ) // unknown character?
551 : : {
552 : : // back in stream, insert '&'
553 : : // and restart with next character
554 [ # # ]: 0 : sTmpBuffer.append( (sal_Unicode)'&' );
555 : :
556 : : DBG_ASSERT( rInput.Tell()-nStreamPos ==
557 : : (sal_uLong)(nPos+1)*GetCharSize(),
558 : : "Wrong stream position" );
559 : : DBG_ASSERT( nlLinePos-nLinePos ==
560 : : (sal_uLong)(nPos+1),
561 : : "Wrong line position" );
562 [ # # ]: 0 : rInput.Seek( nStreamPos );
563 : 0 : nlLinePos = nLinePos;
564 [ # # ]: 0 : ClearTxtConvContext();
565 : : break;
566 : : }
567 : :
568 : : // 1 == Non Breaking Space
569 : : // 2 == SoftHyphen
570 : :
571 [ # # ]: 0 : if( cChar < 3U )
572 : : {
573 [ # # ]: 0 : if( '>' == cBreak )
574 : : {
575 : : // When reading the content of a tag we have
576 : : // to change it to ' ' or '-'
577 [ # # # ]: 0 : switch( cChar )
578 : : {
579 : 0 : case 1U: cChar = ' '; break;
580 : 0 : case 2U: cChar = '-'; break;
581 : : default:
582 : : DBG_ASSERT( cChar==1U,
583 : : "\0x00 should be handled already!" );
584 : 0 : break;
585 : : }
586 : : }
587 : : else
588 : : {
589 : : // If not scanning a tag return token
590 : : aToken +=
591 [ # # ][ # # ]: 0 : String( sTmpBuffer.makeStringAndClear() );
[ # # ][ # # ]
592 [ # # ]: 0 : if( cChar )
593 : : {
594 [ # # ]: 0 : if( aToken.Len() )
595 : : {
596 : : // restart with character
597 : 0 : nNextCh = '&';
598 : : DBG_ASSERT( rInput.Tell()-nStreamPos ==
599 : : (sal_uLong)(nPos+1)*GetCharSize(),
600 : : "Wrong stream position" );
601 : : DBG_ASSERT( nlLinePos-nLinePos ==
602 : : (sal_uLong)(nPos+1),
603 : : "Wrong line position" );
604 [ # # ]: 0 : rInput.Seek( nStreamPos );
605 : 0 : nlLinePos = nLinePos;
606 [ # # ]: 0 : ClearTxtConvContext();
607 : 0 : return HTML_TEXTTOKEN;
608 : : }
609 : :
610 : : // Hack: _GetNextChar shall not read the
611 : : // next character
612 [ # # ]: 0 : if( ';' != nNextCh )
613 [ # # ]: 0 : aToken += ' ';
614 [ # # ]: 0 : if( 1U == cChar )
615 : 0 : return HTML_NONBREAKSPACE;
616 [ # # ]: 0 : if( 2U == cChar )
617 : 0 : return HTML_SOFTHYPH;
618 : : }
619 [ # # ]: 0 : aToken += (sal_Unicode)'&';
620 : : aToken +=
621 [ # # ][ # # ]: 0 : String(sEntityBuffer.makeStringAndClear());
[ # # ][ # # ]
622 : : break;
623 : : }
624 [ # # # ]: 0 : }
625 : : }
626 : : else
627 [ # # # ]: 0 : nNextCh = 0U;
628 : : }
629 : : // &{...};-JavaScript-Macros are not supported any longer.
630 [ # # ]: 0 : else if( IsParserWorking() )
631 : : {
632 [ # # ]: 0 : sTmpBuffer.append( (sal_Unicode)'&' );
633 : 0 : bNextCh = false;
634 : 0 : break;
635 : : }
636 : :
637 : 0 : bNextCh = (';' == nNextCh);
638 [ # # ][ # # ]: 0 : if( cBreak=='>' && (cChar=='\\' || cChar=='\'' ||
[ # # ][ # # ]
[ # # ]
639 : : cChar=='\"' || cChar==' ') )
640 : : {
641 : : // ' and " have to be escaped withing tags to separate
642 : : // them from ' and " enclosing options.
643 : : // \ has to be escaped as well.
644 : : // Space is protected because it's not a delimiter between
645 : : // options.
646 [ # # ]: 0 : sTmpBuffer.append( (sal_Unicode)'\\' );
647 [ # # ]: 0 : if( MAX_LEN == sTmpBuffer.getLength() )
648 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
649 : : }
650 [ # # ]: 0 : if( IsParserWorking() )
651 : : {
652 [ # # ]: 0 : if( cChar )
653 [ # # ]: 0 : sTmpBuffer.append( cChar );
654 : : }
655 [ # # ][ # # ]: 0 : else if( SVPAR_PENDING==eState && '>'!=cBreak )
656 : : {
657 : : // Restart with '&', the remainder is returned as
658 : : // text token.
659 [ # # ][ # # ]: 0 : if( aToken.Len() || sTmpBuffer.getLength() )
[ # # ]
660 : : {
661 : : // _GetNextChar() returns the previous text and
662 : : // during the next execution a new character is read.
663 : : // Thus we have to position in front of the '&'.
664 : 0 : nNextCh = 0U;
665 [ # # ]: 0 : rInput.Seek( nStreamPos-(sal_uInt32)GetCharSize() );
666 : 0 : nlLinePos = nLinePos-1;
667 [ # # ]: 0 : ClearTxtConvContext();
668 : 0 : bReadNextChar = true;
669 : : }
670 : 0 : bNextCh = false;
671 : : }
672 : : }
673 : 0 : break;
674 : : case '=':
675 [ + - ][ + + ]: 25 : if( '>'==cBreak && !cQuote )
676 : 23 : bEqSignFound = true;
677 [ + - ]: 25 : sTmpBuffer.append( nNextCh );
678 : 25 : break;
679 : :
680 : : case '\\':
681 [ # # ]: 0 : if( '>'==cBreak )
682 : : {
683 : : // Innerhalb von Tags kennzeichnen
684 [ # # ]: 0 : sTmpBuffer.append( (sal_Unicode)'\\' );
685 [ # # ]: 0 : if( MAX_LEN == sTmpBuffer.getLength() )
686 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
687 : : }
688 [ # # ]: 0 : sTmpBuffer.append( (sal_Unicode)'\\' );
689 : 0 : break;
690 : :
691 : : case '\"':
692 : : case '\'':
693 [ + - ]: 50 : if( '>'==cBreak )
694 : : {
695 [ + + ]: 50 : if( bEqSignFound )
696 : 23 : cQuote = nNextCh;
697 [ + + ][ + - ]: 27 : else if( cQuote && (cQuote==nNextCh ) )
698 : 23 : cQuote = 0U;
699 : : }
700 [ + - ]: 50 : sTmpBuffer.append( nNextCh );
701 : 50 : bEqSignFound = false;
702 : 50 : break;
703 : :
704 : : case sal_Unicode(EOF):
705 [ # # ]: 0 : if( rInput.IsEof() )
706 : : {
707 : 0 : bContinue = false;
708 : : }
709 : : else
710 : : {
711 [ # # ]: 0 : sTmpBuffer.append( nNextCh );
712 : : }
713 : 0 : break;
714 : :
715 : : case '<':
716 : 65 : bEqSignFound = false;
717 [ - + ]: 65 : if( '>'==cBreak )
718 [ # # ]: 0 : sTmpBuffer.append( nNextCh );
719 : : else
720 : 65 : bContinue = false; // break, String zusammen
721 : 65 : break;
722 : :
723 : : case '\f':
724 [ # # ]: 0 : if( '>' == cBreak )
725 : : {
726 : : // If scanning options treat it like a space, ...
727 [ # # ]: 0 : sTmpBuffer.append( (sal_Unicode)' ' );
728 : : }
729 : : else
730 : : {
731 : : // otherwise it's a separate token.
732 : 0 : bContinue = false;
733 : : }
734 : 0 : break;
735 : :
736 : : case '\r':
737 : : case '\n':
738 [ - + ]: 50 : if( '>'==cBreak )
739 : : {
740 : : // cr/lf in tag is handled in _GetNextToken()
741 [ # # ]: 0 : sTmpBuffer.append( nNextCh );
742 : 0 : break;
743 : : }
744 [ + - ][ + - ]: 50 : else if( bReadListing || bReadXMP || bReadPRE || bReadTextArea )
[ + - ][ - + ]
745 : : {
746 : 0 : bContinue = false;
747 : 0 : break;
748 : : }
749 : : // Reduce sequence of CR/LF/BLANK/TAB to a single blank
750 : : // no break!!
751 : : case '\t':
752 [ - + ][ # # ]: 50 : if( '\t'==nNextCh && bReadPRE && '>'!=cBreak )
[ # # ]
753 : : {
754 : : // In <PRE>: Tabs nach oben durchreichen
755 : 0 : bContinue = false;
756 : 0 : break;
757 : : }
758 : : // no break
759 : : case '\x0b':
760 [ - + ][ # # ]: 50 : if( '\x0b'==nNextCh && (bReadPRE || bReadXMP ||bReadListing) &&
[ # # ][ # # ]
[ # # ]
761 : : '>'!=cBreak )
762 : : {
763 : 0 : break;
764 : : }
765 : 50 : nNextCh = ' ';
766 : : // no break;
767 : : case ' ':
768 [ + - ]: 111 : sTmpBuffer.append( nNextCh );
769 [ + + ][ + - ]: 111 : if( '>'!=cBreak && (!bReadListing && !bReadXMP &&
[ + - ][ + - ]
[ + - ]
770 : 166 : !bReadPRE && !bReadTextArea) )
771 : : {
772 : : // Reduce sequences of Blanks/Tabs/CR/LF to a single blank
773 [ + + ][ + + ]: 114 : do {
[ + - ][ + - ]
[ - + ][ + + ]
774 [ + - ]: 120 : if( sal_Unicode(EOF) == (nNextCh = GetNextChar()) &&
[ + + + - ]
[ + + ]
775 : 3 : rInput.IsEof() )
776 : : {
777 [ + - ][ - + ]: 3 : if( aToken.Len() || sTmpBuffer.getLength() > 1L )
[ - + ]
778 : : {
779 : : // Have seen s.th. aside from blanks?
780 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
781 : 0 : return HTML_TEXTTOKEN;
782 : : }
783 : : else
784 : : // Only read blanks: no text must be returned
785 : : // and _GetNextToken has to read until EOF
786 : 3 : return 0;
787 : : }
788 : : } while ( ' ' == nNextCh || '\t' == nNextCh ||
789 : : '\r' == nNextCh || '\n' == nNextCh ||
790 : : '\x0b' == nNextCh );
791 : 80 : bNextCh = false;
792 : : }
793 : 108 : break;
794 : :
795 : : default:
796 : 178 : bEqSignFound = false;
797 [ + + ]: 341 : if( (nNextCh==cBreak && !cQuote) ||
[ - + - + ]
[ + + ]
798 : 163 : (sal_uLong(aToken.Len()) + MAX_LEN) > sal_uLong(STRING_MAXLEN & ~1 ))
799 : 15 : bContinue = false;
800 : : else
801 : : {
802 [ + + ][ + + ]: 881 : do {
[ + + ]
803 : : // All remaining characters make their way into the text.
804 [ + - ]: 663 : sTmpBuffer.append( nNextCh );
805 [ - + ]: 663 : if( MAX_LEN == sTmpBuffer.getLength() )
806 : : {
807 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
808 [ # # ]: 0 : if( (sal_uLong(aToken.Len()) + MAX_LEN) >
809 : : sal_uLong(STRING_MAXLEN & ~1 ) )
810 : : {
811 [ # # ]: 0 : nNextCh = GetNextChar();
812 : 0 : return HTML_TEXTTOKEN;
813 : : }
814 : : }
815 [ + - ][ - + : 1326 : if( ( sal_Unicode(EOF) == (nNextCh = GetNextChar()) &&
# # - + ]
[ - + ]
816 : 0 : rInput.IsEof() ) ||
817 : 663 : !IsParserWorking() )
818 : : {
819 [ # # ]: 0 : if( sTmpBuffer.getLength() )
820 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
821 : 0 : return HTML_TEXTTOKEN;
822 : : }
823 [ + - ][ + - ]: 881 : } while( HTML_ISALPHA( nNextCh ) || HTML_ISDIGIT( nNextCh ) );
824 : 163 : bNextCh = false;
825 : : }
826 : : }
827 : :
828 [ - + ]: 426 : if( MAX_LEN == sTmpBuffer.getLength() )
829 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
830 : :
831 [ + + ][ + + ]: 426 : if( bContinue && bNextCh )
832 [ + - ]: 103 : nNextCh = GetNextChar();
833 : : }
834 : :
835 [ + - ]: 80 : if( sTmpBuffer.getLength() )
836 [ + - ][ + - ]: 80 : aToken += String(sTmpBuffer.makeStringAndClear());
[ + - ][ + - ]
837 : :
838 : 83 : return HTML_TEXTTOKEN;
839 : : }
840 : :
841 : 0 : int HTMLParser::_GetNextRawToken()
842 : : {
843 : 0 : ::rtl::OUStringBuffer sTmpBuffer( MAX_LEN );
844 : :
845 [ # # ]: 0 : if( bEndTokenFound )
846 : : {
847 : : // During the last execution we already found the end token,
848 : : // thus we don't have to search it again.
849 : 0 : bReadScript = false;
850 : 0 : bReadStyle = false;
851 [ # # ]: 0 : aEndToken.Erase();
852 : 0 : bEndTokenFound = false;
853 : :
854 : 0 : return 0;
855 : : }
856 : :
857 : : // Default return value: HTML_RAWDATA
858 : 0 : int bContinue = true;
859 : 0 : int nToken = HTML_RAWDATA;
860 [ # # ]: 0 : SaveState( 0 );
861 [ # # ][ # # ]: 0 : while( bContinue && IsParserWorking() )
[ # # ]
862 : : {
863 : 0 : int bNextCh = true;
864 [ # # # # : 0 : switch( nNextCh )
# # ]
865 : : {
866 : : case '<':
867 : : {
868 : : // Maybe we've reached the end.
869 : :
870 : : // Save what we have read previously...
871 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
872 : :
873 : : // and remember position in stream.
874 : 0 : sal_uLong nStreamPos = rInput.Tell();
875 : 0 : sal_uLong nLineNr = GetLineNr();
876 : 0 : sal_uLong nLinePos = GetLinePos();
877 : :
878 : : // Start of an end token?
879 : 0 : int bOffState = false;
880 [ # # ][ # # ]: 0 : if( '/' == (nNextCh = GetNextChar()) )
881 : : {
882 : 0 : bOffState = true;
883 [ # # ]: 0 : nNextCh = GetNextChar();
884 : : }
885 [ # # ]: 0 : else if( '!' == nNextCh )
886 : : {
887 [ # # ]: 0 : sTmpBuffer.append( nNextCh );
888 [ # # ]: 0 : nNextCh = GetNextChar();
889 : : }
890 : :
891 : : // Read following letters
892 [ # # ][ # # ]: 0 : while( (HTML_ISALPHA(nNextCh) || '-'==nNextCh) &&
[ # # # #
# # ][ # # ]
893 : 0 : IsParserWorking() && sTmpBuffer.getLength() < MAX_LEN )
894 : : {
895 [ # # ]: 0 : sTmpBuffer.append( nNextCh );
896 [ # # ]: 0 : nNextCh = GetNextChar();
897 : : }
898 : :
899 [ # # ]: 0 : String aTok( sTmpBuffer.toString() );
900 [ # # ]: 0 : aTok.ToUpperAscii();
901 : 0 : bool bDone = false;
902 [ # # ][ # # ]: 0 : if( bReadScript || aEndToken.Len() )
[ # # ]
903 : : {
904 [ # # ]: 0 : if( !bReadComment )
905 : : {
906 [ # # ][ # # ]: 0 : if( aTok.CompareToAscii( OOO_STRING_SVTOOLS_HTML_comment, 3 )
907 : : == COMPARE_EQUAL )
908 : : {
909 : 0 : bReadComment = true;
910 : : }
911 : : else
912 : : {
913 : : // A script has to end with "</SCRIPT>". But
914 : : // ">" is optional for security reasons
915 : : bDone = bOffState &&
916 : : COMPARE_EQUAL == ( bReadScript
917 [ # # ]: 0 : ? aTok.CompareToAscii(OOO_STRING_SVTOOLS_HTML_script)
918 [ # # ][ # # ]: 0 : : aTok.CompareTo(aEndToken) );
[ # # ][ # # ]
[ # # ]
919 : : }
920 : : }
921 [ # # ][ # # ]: 0 : if( bReadComment && '>'==nNextCh && aTok.Len() >= 2 &&
[ # # ][ # # ]
[ # # ]
922 [ # # ][ # # ]: 0 : aTok.Copy( aTok.Len()-2 ).EqualsAscii( "--" ) )
[ # # ][ # # ]
[ # # ]
923 : : {
924 : : // End of comment of style <!----->
925 : 0 : bReadComment = false;
926 : : }
927 : : }
928 : : else
929 : : {
930 : : // Style sheets can be closed by </STYLE>, </HEAD> or <BODY>
931 [ # # ]: 0 : if( bOffState )
932 [ # # ]: 0 : bDone = aTok.CompareToAscii(OOO_STRING_SVTOOLS_HTML_style)
933 : : == COMPARE_EQUAL ||
934 [ # # ]: 0 : aTok.CompareToAscii(OOO_STRING_SVTOOLS_HTML_head)
935 [ # # ][ # # ]: 0 : == COMPARE_EQUAL;
936 : : else
937 : : bDone =
938 [ # # ]: 0 : aTok.CompareToAscii(OOO_STRING_SVTOOLS_HTML_body) == COMPARE_EQUAL;
939 : : }
940 : :
941 [ # # ]: 0 : if( bDone )
942 : : {
943 : : // Done! Return the previously read string (if requested)
944 : : // and continue.
945 : :
946 : 0 : bContinue = false;
947 : :
948 : : // nToken==0 means, _GetNextToken continues to read
949 [ # # ][ # # ]: 0 : if( !aToken.Len() && (bReadStyle || bReadScript) )
[ # # ][ # # ]
950 : : {
951 : : // Immediately close environment (or context?)
952 : : // and parse the end token
953 : 0 : bReadScript = false;
954 : 0 : bReadStyle = false;
955 [ # # ]: 0 : aEndToken.Erase();
956 : 0 : nToken = 0;
957 : : }
958 : : else
959 : : {
960 : : // Keep bReadScript/bReadStyle alive
961 : : // and parse end token during next execution
962 : 0 : bEndTokenFound = true;
963 : : }
964 : :
965 : : // Move backwards in stream to '<'
966 [ # # ]: 0 : rInput.Seek( nStreamPos );
967 : 0 : SetLineNr( nLineNr );
968 : 0 : SetLinePos( nLinePos );
969 [ # # ]: 0 : ClearTxtConvContext();
970 : 0 : nNextCh = '<';
971 : :
972 : : // Don't append string to token.
973 [ # # ]: 0 : sTmpBuffer.setLength( 0L );
974 : : }
975 : : else
976 : : {
977 : : // remember "</" , everything else we find in the buffer
978 [ # # ]: 0 : aToken += (sal_Unicode)'<';
979 [ # # ]: 0 : if( bOffState )
980 [ # # ]: 0 : aToken += (sal_Unicode)'/';
981 : :
982 : 0 : bNextCh = false;
983 [ # # ]: 0 : }
984 : : }
985 : 0 : break;
986 : : case '-':
987 [ # # ]: 0 : sTmpBuffer.append( nNextCh );
988 [ # # ]: 0 : if( bReadComment )
989 : : {
990 : 0 : bool bTwoMinus = false;
991 [ # # ]: 0 : nNextCh = GetNextChar();
992 [ # # ][ # # ]: 0 : while( '-' == nNextCh && IsParserWorking() )
[ # # ]
993 : : {
994 : 0 : bTwoMinus = true;
995 : :
996 [ # # ]: 0 : if( MAX_LEN == sTmpBuffer.getLength() )
997 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
998 [ # # ]: 0 : sTmpBuffer.append( nNextCh );
999 [ # # ]: 0 : nNextCh = GetNextChar();
1000 : : }
1001 : :
1002 [ # # ][ # # ]: 0 : if( '>' == nNextCh && IsParserWorking() && bTwoMinus )
[ # # ][ # # ]
1003 : 0 : bReadComment = false;
1004 : :
1005 : 0 : bNextCh = false;
1006 : : }
1007 : 0 : break;
1008 : :
1009 : : case '\r':
1010 : : // \r\n? closes the current text token (even if it's empty)
1011 [ # # ]: 0 : nNextCh = GetNextChar();
1012 [ # # ]: 0 : if( nNextCh=='\n' )
1013 [ # # ]: 0 : nNextCh = GetNextChar();
1014 : 0 : bContinue = false;
1015 : 0 : break;
1016 : : case '\n':
1017 : : // \n closes the current text token (even if it's empty)
1018 [ # # ]: 0 : nNextCh = GetNextChar();
1019 : 0 : bContinue = false;
1020 : 0 : break;
1021 : : case sal_Unicode(EOF):
1022 : : // eof closes the current text token and behaves like having read
1023 : : // an end token
1024 [ # # ]: 0 : if( rInput.IsEof() )
1025 : : {
1026 : 0 : bContinue = false;
1027 [ # # ][ # # ]: 0 : if( aToken.Len() || sTmpBuffer.getLength() )
[ # # ]
1028 : : {
1029 : 0 : bEndTokenFound = true;
1030 : : }
1031 : : else
1032 : : {
1033 : 0 : bReadScript = false;
1034 : 0 : bReadStyle = false;
1035 [ # # ]: 0 : aEndToken.Erase();
1036 : 0 : nToken = 0;
1037 : : }
1038 : 0 : break;
1039 : : }
1040 : : // no break
1041 : : default:
1042 : : // all remaining characters are appended to the buffer
1043 [ # # ]: 0 : sTmpBuffer.append( nNextCh );
1044 : 0 : break;
1045 : : }
1046 : :
1047 [ # # ]: 0 : if( (!bContinue && sTmpBuffer.getLength() > 0L) ||
[ # # # # ]
[ # # ]
1048 : 0 : MAX_LEN == sTmpBuffer.getLength() )
1049 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
1050 : :
1051 [ # # ][ # # ]: 0 : if( bContinue && bNextCh )
1052 [ # # ]: 0 : nNextCh = GetNextChar();
1053 : : }
1054 : :
1055 [ # # ]: 0 : if( IsParserWorking() )
1056 [ # # ]: 0 : SaveState( 0 );
1057 : : else
1058 : 0 : nToken = 0;
1059 : :
1060 : 0 : return nToken;
1061 : : }
1062 : :
1063 : : // Scan next token
1064 : 170 : int HTMLParser::_GetNextToken()
1065 : : {
1066 : 170 : int nRet = 0;
1067 : 170 : sSaveToken.Erase();
1068 : :
1069 : : // Delete options
1070 [ + + ]: 170 : if (!maOptions.empty())
1071 : 10 : maOptions.clear();
1072 : :
1073 [ - + ]: 170 : if( !IsParserWorking() ) // Don't continue if already an error occured
1074 : 0 : return 0;
1075 : :
1076 : 170 : bool bReadNextCharSave = bReadNextChar;
1077 [ - + ]: 170 : if( bReadNextChar )
1078 : : {
1079 : : DBG_ASSERT( !bEndTokenFound,
1080 : : "Read a character despite </SCRIPT> was read?" );
1081 : 0 : nNextCh = GetNextChar();
1082 [ # # ]: 0 : if( !IsParserWorking() ) // Don't continue if already an error occured
1083 : 0 : return 0;
1084 : 0 : bReadNextChar = false;
1085 : : }
1086 : :
1087 [ + - ][ + - ]: 170 : if( bReadScript || bReadStyle || aEndToken.Len() )
[ - + ][ - + ]
1088 : : {
1089 : 0 : nRet = _GetNextRawToken();
1090 [ # # ][ # # ]: 0 : if( nRet || !IsParserWorking() )
[ # # ]
1091 : 0 : return nRet;
1092 : : }
1093 : :
1094 [ + + ][ + - ]: 173 : do {
[ + + ]
1095 : 173 : int bNextCh = true;
1096 [ + + - + : 173 : switch( nNextCh )
- + ]
1097 : : {
1098 : : case '<':
1099 : : {
1100 : 100 : sal_uLong nStreamPos = rInput.Tell();
1101 : 100 : sal_uLong nLineNr = GetLineNr();
1102 : 100 : sal_uLong nLinePos = GetLinePos();
1103 : :
1104 : 100 : int bOffState = false;
1105 [ + + ]: 100 : if( '/' == (nNextCh = GetNextChar()) )
1106 : : {
1107 : 43 : bOffState = true;
1108 : 43 : nNextCh = GetNextChar();
1109 : : }
1110 [ + + ][ + - ]: 100 : if( HTML_ISALPHA( nNextCh ) || '!'==nNextCh )
[ + - ]
1111 : : {
1112 : 100 : ::rtl::OUStringBuffer sTmpBuffer;
1113 [ + + ][ + + : 706 : do {
+ - + - ]
[ + + ]
1114 [ + - ]: 302 : sTmpBuffer.append( nNextCh );
1115 [ - + ]: 302 : if( MAX_LEN == sTmpBuffer.getLength() )
1116 [ # # ][ # # ]: 0 : aToken += String(sTmpBuffer.makeStringAndClear());
[ # # ][ # # ]
1117 [ + - ]: 302 : nNextCh = GetNextChar();
1118 [ + - ][ + - ]: 202 : } while( '>' != nNextCh && !HTML_ISSPACE( nNextCh ) &&
1119 : 404 : IsParserWorking() && !rInput.IsEof() );
1120 : :
1121 [ + - ]: 100 : if( sTmpBuffer.getLength() )
1122 [ + - ][ + - ]: 100 : aToken += String(sTmpBuffer.makeStringAndClear());
[ + - ][ + - ]
1123 : :
1124 : : // Skip blanks
1125 [ + + ][ + - ]: 115 : while( HTML_ISSPACE( nNextCh ) && IsParserWorking() )
[ - + ][ + - ]
[ + + ]
1126 [ + - ]: 15 : nNextCh = GetNextChar();
1127 : :
1128 [ - + ]: 100 : if( !IsParserWorking() )
1129 : : {
1130 [ # # ]: 0 : if( SVPAR_PENDING == eState )
1131 : 0 : bReadNextChar = bReadNextCharSave;
1132 : : break;
1133 : : }
1134 : :
1135 : : // Search token in table:
1136 [ + - ]: 100 : sSaveToken = aToken;
1137 [ + - ]: 100 : aToken.ToUpperAscii();
1138 [ + - ][ - + ]: 100 : if( 0 == (nRet = GetHTMLToken( aToken )) )
1139 : : // Unknown control
1140 : 0 : nRet = HTML_UNKNOWNCONTROL_ON;
1141 : :
1142 : : // If it's a token which can be switched off...
1143 [ + + ]: 100 : if( bOffState )
1144 : : {
1145 [ + - ]: 43 : if( HTML_TOKEN_ONOFF & nRet )
1146 : : {
1147 : : // and there is an off token, return off token instead
1148 : 43 : ++nRet;
1149 : : }
1150 [ # # ]: 0 : else if( HTML_LINEBREAK!=nRet )
1151 : : {
1152 : : // and there is no off token, return unknown token.
1153 : : // (except for </BR>, that is treated like <BR>)
1154 : 0 : nRet = HTML_UNKNOWNCONTROL_OFF;
1155 : : }
1156 : : }
1157 : :
1158 [ - + ]: 100 : if( nRet == HTML_COMMENT )
1159 : : {
1160 : : // fix: due to being case sensitive use sSaveToken as start of comment
1161 : : // and append a blank.
1162 [ # # ]: 0 : aToken = sSaveToken;
1163 [ # # ]: 0 : if( '>'!=nNextCh )
1164 [ # # ]: 0 : aToken += (sal_Unicode)' ';
1165 : 0 : sal_uLong nCStreamPos = 0;
1166 : 0 : sal_uLong nCLineNr = 0;
1167 : 0 : sal_uLong nCLinePos = 0;
1168 : 0 : xub_StrLen nCStrLen = 0;
1169 : :
1170 : 0 : bool bDone = false;
1171 : : // Read until closing -->. If not found restart at first >
1172 [ # # ][ # # ]: 0 : while( !bDone && !rInput.IsEof() && IsParserWorking() )
[ # # ][ # # ]
1173 : : {
1174 [ # # ]: 0 : if( '>'==nNextCh )
1175 : : {
1176 [ # # ]: 0 : if( !nCStreamPos )
1177 : : {
1178 : 0 : nCStreamPos = rInput.Tell();
1179 : 0 : nCStrLen = aToken.Len();
1180 : 0 : nCLineNr = GetLineNr();
1181 : 0 : nCLinePos = GetLinePos();
1182 : : }
1183 : 0 : bDone = aToken.Len() >= 2 &&
1184 : 0 : aToken.Copy(aToken.Len()-2,2).
1185 [ # # ][ # # ]: 0 : EqualsAscii( "--" );
[ # # ][ # # ]
[ # # ]
[ # # # # ]
1186 [ # # ]: 0 : if( !bDone )
1187 [ # # ]: 0 : aToken += nNextCh;
1188 : : }
1189 : : else
1190 [ # # ]: 0 : aToken += nNextCh;
1191 [ # # ]: 0 : if( !bDone )
1192 [ # # ]: 0 : nNextCh = GetNextChar();
1193 : : }
1194 [ # # ][ # # ]: 0 : if( !bDone && IsParserWorking() && nCStreamPos )
[ # # ][ # # ]
1195 : : {
1196 [ # # ]: 0 : rInput.Seek( nCStreamPos );
1197 : 0 : SetLineNr( nCLineNr );
1198 : 0 : SetLinePos( nCLinePos );
1199 [ # # ]: 0 : ClearTxtConvContext();
1200 [ # # ]: 0 : aToken.Erase( nCStrLen );
1201 : 0 : nNextCh = '>';
1202 : : }
1203 : : }
1204 : : else
1205 : : {
1206 : : // TokenString not needed anymore
1207 [ + - ]: 100 : aToken.Erase();
1208 : : }
1209 : :
1210 : : // Read until closing '>'
1211 [ + + ][ + - ]: 100 : if( '>' != nNextCh && IsParserWorking() )
[ + + ]
1212 : : {
1213 [ + - ]: 15 : ScanText( '>' );
1214 : :
1215 : : // fdo#34666 fdo#36080 fdo#36390: closing "/>"?:
1216 : : // return HTML_<TOKEN>_OFF instead of HTML_<TOKEN>_ON
1217 [ + + ]: 20 : if ((HTML_TOKEN_ONOFF & nRet) && (aToken.Len() >= 1) &&
[ + - - + ]
[ - + ]
1218 : 5 : ('/' == aToken.GetChar(aToken.Len()-1))) {
1219 : 0 : ++nRet; // HTML_<TOKEN>_ON -> HTML_<TOKEN>_OFF;
1220 : : }
1221 [ - + ][ # # ]: 15 : if( sal_Unicode(EOF) == nNextCh && rInput.IsEof() )
[ - + ]
1222 : : {
1223 : : // Move back in front of < and restart there.
1224 : : // Return < as text.
1225 [ # # ]: 0 : rInput.Seek( nStreamPos );
1226 : 0 : SetLineNr( nLineNr );
1227 : 0 : SetLinePos( nLinePos );
1228 [ # # ]: 0 : ClearTxtConvContext();
1229 : :
1230 [ # # ]: 0 : aToken = '<';
1231 : 0 : nRet = HTML_TEXTTOKEN;
1232 [ # # ]: 0 : nNextCh = GetNextChar();
1233 : 0 : bNextCh = false;
1234 : : break;
1235 : : }
1236 : : }
1237 [ - + ]: 100 : if( SVPAR_PENDING == eState )
1238 [ + - ]: 100 : bReadNextChar = bReadNextCharSave;
1239 : : }
1240 : : else
1241 : : {
1242 [ # # ]: 0 : if( bOffState )
1243 : : {
1244 : : // einfach alles wegschmeissen
1245 : 0 : ScanText( '>' );
1246 [ # # ][ # # ]: 0 : if( sal_Unicode(EOF) == nNextCh && rInput.IsEof() )
[ # # ]
1247 : : {
1248 : : // Move back in front of < and restart there.
1249 : : // Return < as text.
1250 : 0 : rInput.Seek( nStreamPos );
1251 : 0 : SetLineNr( nLineNr );
1252 : 0 : SetLinePos( nLinePos );
1253 : 0 : ClearTxtConvContext();
1254 : :
1255 : 0 : aToken = '<';
1256 : 0 : nRet = HTML_TEXTTOKEN;
1257 : 0 : nNextCh = GetNextChar();
1258 : 0 : bNextCh = false;
1259 : 0 : break;
1260 : : }
1261 [ # # ]: 0 : if( SVPAR_PENDING == eState )
1262 : 0 : bReadNextChar = bReadNextCharSave;
1263 : 0 : aToken.Erase();
1264 : : }
1265 [ # # ]: 0 : else if( '%' == nNextCh )
1266 : : {
1267 : 0 : nRet = HTML_UNKNOWNCONTROL_ON;
1268 : :
1269 : 0 : sal_uLong nCStreamPos = rInput.Tell();
1270 : 0 : sal_uLong nCLineNr = GetLineNr(), nCLinePos = GetLinePos();
1271 : :
1272 : 0 : bool bDone = false;
1273 : : // Read until closing %>. If not found restart at first >.
1274 [ # # ][ # # ]: 0 : while( !bDone && !rInput.IsEof() && IsParserWorking() )
[ # # ][ # # ]
1275 : : {
1276 : 0 : bDone = '>'==nNextCh && aToken.Len() >= 1 &&
1277 [ # # # # ]: 0 : '%' == aToken.GetChar( aToken.Len()-1 );
[ # # ]
1278 [ # # ]: 0 : if( !bDone )
1279 : : {
1280 : 0 : aToken += nNextCh;
1281 : 0 : nNextCh = GetNextChar();
1282 : : }
1283 : : }
1284 [ # # ][ # # ]: 0 : if( !bDone && IsParserWorking() )
[ # # ]
1285 : : {
1286 : 0 : rInput.Seek( nCStreamPos );
1287 : 0 : SetLineNr( nCLineNr );
1288 : 0 : SetLinePos( nCLinePos );
1289 : 0 : ClearTxtConvContext();
1290 : 0 : aToken.AssignAscii( "<%", 2 );
1291 : 0 : nRet = HTML_TEXTTOKEN;
1292 : 0 : break;
1293 : : }
1294 [ # # ]: 0 : if( IsParserWorking() )
1295 : : {
1296 : 0 : sSaveToken = aToken;
1297 : 0 : aToken.Erase();
1298 : : }
1299 : : }
1300 : : else
1301 : : {
1302 : 0 : aToken = '<';
1303 : 0 : nRet = HTML_TEXTTOKEN;
1304 : 0 : bNextCh = false;
1305 : 0 : break;
1306 : : }
1307 : : }
1308 : :
1309 [ + - ]: 100 : if( IsParserWorking() )
1310 : : {
1311 : 100 : bNextCh = '>' == nNextCh;
1312 [ - - - - : 100 : switch( nRet )
- - + ]
1313 : : {
1314 : : case HTML_TEXTAREA_ON:
1315 : 0 : bReadTextArea = true;
1316 : 0 : break;
1317 : : case HTML_TEXTAREA_OFF:
1318 : 0 : bReadTextArea = false;
1319 : 0 : break;
1320 : : case HTML_SCRIPT_ON:
1321 [ # # ]: 0 : if( !bReadTextArea )
1322 : 0 : bReadScript = true;
1323 : 0 : break;
1324 : : case HTML_SCRIPT_OFF:
1325 [ # # ]: 0 : if( !bReadTextArea )
1326 : : {
1327 : 0 : bReadScript = false;
1328 : : // JavaScript might modify the stream,
1329 : : // thus the last character has to be read again.
1330 : 0 : bReadNextChar = true;
1331 : 0 : bNextCh = false;
1332 : : }
1333 : 0 : break;
1334 : :
1335 : : case HTML_STYLE_ON:
1336 : 0 : bReadStyle = true;
1337 : 0 : break;
1338 : : case HTML_STYLE_OFF:
1339 : 0 : bReadStyle = false;
1340 : 100 : break;
1341 : : }
1342 : : }
1343 : : }
1344 : 100 : break;
1345 : :
1346 : : case sal_Unicode(EOF):
1347 [ + - ]: 5 : if( rInput.IsEof() )
1348 : : {
1349 : 5 : eState = SVPAR_ACCEPTED;
1350 : 5 : nRet = nNextCh;
1351 : : }
1352 : : else
1353 : : {
1354 : : // Read normal text.
1355 : 0 : goto scan_text;
1356 : : }
1357 : 5 : break;
1358 : :
1359 : : case '\f':
1360 : : // form feeds are passed upwards separately
1361 : 0 : nRet = HTML_LINEFEEDCHAR; // !!! should be FORMFEEDCHAR
1362 : 0 : break;
1363 : :
1364 : : case '\n':
1365 : : case '\r':
1366 [ + - ][ + - ]: 50 : if( bReadListing || bReadXMP || bReadPRE || bReadTextArea )
[ + - ][ - + ]
1367 : : {
1368 : 0 : sal_Unicode c = GetNextChar();
1369 [ # # ][ # # ]: 0 : if( ( '\n' != nNextCh || '\r' != c ) &&
[ # # ][ # # ]
1370 : : ( '\r' != nNextCh || '\n' != c ) )
1371 : : {
1372 : 0 : bNextCh = false;
1373 : 0 : nNextCh = c;
1374 : : }
1375 : 0 : nRet = HTML_NEWPARA;
1376 : 0 : break;
1377 : : }
1378 : : // no break !
1379 : : case '\t':
1380 [ - + ]: 50 : if( bReadPRE )
1381 : : {
1382 : 0 : nRet = HTML_TABCHAR;
1383 : 0 : break;
1384 : : }
1385 : : // no break !
1386 : : case ' ':
1387 : : // no break !
1388 : : default:
1389 : :
1390 : : scan_text:
1391 : : // "normal" text to come
1392 : 68 : nRet = ScanText();
1393 : 68 : bNextCh = 0 == aToken.Len();
1394 : :
1395 : : // the text should be processed
1396 [ - + ][ + + ]: 68 : if( !bNextCh && eState == SVPAR_PENDING )
1397 : : {
1398 : 0 : eState = SVPAR_WORKING;
1399 : 0 : bReadNextChar = true;
1400 : : }
1401 : :
1402 : 68 : break;
1403 : : }
1404 : :
1405 [ + + ][ + + ]: 173 : if( bNextCh && SVPAR_WORKING == eState )
1406 : : {
1407 : 103 : nNextCh = GetNextChar();
1408 [ # # ][ # # ]: 103 : if( SVPAR_PENDING == eState && nRet && HTML_TEXTTOKEN != nRet )
[ - + ]
1409 : : {
1410 : 0 : bReadNextChar = true;
1411 : 0 : eState = SVPAR_WORKING;
1412 : : }
1413 : : }
1414 : :
1415 : : } while( !nRet && SVPAR_WORKING == eState );
1416 : :
1417 [ - + ]: 170 : if( SVPAR_PENDING == eState )
1418 : 0 : nRet = -1; // s.th. invalid
1419 : :
1420 : 170 : return nRet;
1421 : : }
1422 : :
1423 : 0 : void HTMLParser::UnescapeToken()
1424 : : {
1425 : 0 : xub_StrLen nPos=0;
1426 : :
1427 : 0 : bool bEscape = false;
1428 [ # # ]: 0 : while( nPos < aToken.Len() )
1429 : : {
1430 : 0 : bool bOldEscape = bEscape;
1431 : 0 : bEscape = false;
1432 [ # # ][ # # ]: 0 : if( '\\'==aToken.GetChar(nPos) && !bOldEscape )
[ # # ]
1433 : : {
1434 : 0 : aToken.Erase( nPos, 1 );
1435 : 0 : bEscape = true;
1436 : : }
1437 : : else
1438 : : {
1439 : 0 : nPos++;
1440 : : }
1441 : : }
1442 : 0 : }
1443 : :
1444 : 73 : const HTMLOptions& HTMLParser::GetOptions( sal_uInt16 *pNoConvertToken ) const
1445 : : {
1446 : : // If the options for the current token have already been returned,
1447 : : // return them once again.
1448 [ + + ]: 73 : if (!maOptions.empty())
1449 : 4 : return maOptions;
1450 : :
1451 : 69 : xub_StrLen nPos = 0;
1452 [ + + ]: 99 : while( nPos < aToken.Len() )
1453 : : {
1454 : : // A letter? Option beginning here.
1455 [ + + ]: 30 : if( HTML_ISALPHA( aToken.GetChar(nPos) ) )
1456 : : {
1457 : : int nToken;
1458 [ + - ]: 20 : String aValue;
1459 : 20 : xub_StrLen nStt = nPos;
1460 : 20 : sal_Unicode cChar = 0;
1461 : :
1462 : : // Actually only certain characters allowed.
1463 : : // Netscape only looks for "=" and white space (c.f.
1464 : : // Mozilla: PA_FetchRequestedNameValues in lipparse/pa_mdl.c)
1465 [ + - ][ + + ]: 248 : while( nPos < aToken.Len() && '=' != (cChar=aToken.GetChar(nPos)) &&
[ + - ][ + - ]
[ + - ][ + + ]
1466 [ + - ][ + - ]: 114 : HTML_ISPRINTABLE(cChar) && !HTML_ISSPACE(cChar) )
1467 : 114 : nPos++;
1468 : :
1469 [ + - ]: 20 : String sName( aToken.Copy( nStt, nPos-nStt ) );
1470 : :
1471 : : // PlugIns require original token name. Convert to upper case only for searching.
1472 [ + - ]: 20 : String sNameUpperCase( sName );
1473 [ + - ]: 20 : sNameUpperCase.ToUpperAscii();
1474 : :
1475 [ + - ]: 20 : nToken = GetHTMLOption( sNameUpperCase ); // Name is ready
1476 : : DBG_ASSERTWARNING( nToken!=HTML_O_UNKNOWN,
1477 : : "GetOption: unknown HTML option" );
1478 : : bool bStripCRLF = (nToken < HTML_OPTION_SCRIPT_START ||
1479 : : nToken >= HTML_OPTION_SCRIPT_END) &&
1480 [ - + ][ # # ]: 20 : (!pNoConvertToken || nToken != *pNoConvertToken);
[ + + ][ + + ]
1481 : :
1482 [ + - ][ + - ]: 40 : while( nPos < aToken.Len() &&
[ + - ][ + - ]
[ - + ][ - + ]
1483 [ + - ]: 20 : ( !HTML_ISPRINTABLE( (cChar=aToken.GetChar(nPos)) ) ||
1484 : : HTML_ISSPACE(cChar) ) )
1485 : 0 : nPos++;
1486 : :
1487 : : // Option with value?
1488 [ + - ][ + - ]: 20 : if( nPos!=aToken.Len() && '='==cChar )
[ + - ]
1489 : : {
1490 : 20 : nPos++;
1491 : :
1492 [ + - ][ + - ]: 40 : while( nPos < aToken.Len() &&
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
1493 [ + - ]: 20 : ( !HTML_ISPRINTABLE( (cChar=aToken.GetChar(nPos)) ) ||
1494 : : ' '==cChar || '\t'==cChar || '\r'==cChar || '\n'==cChar ) )
1495 : 0 : nPos++;
1496 : :
1497 [ + - ]: 20 : if( nPos != aToken.Len() )
1498 : : {
1499 : 20 : xub_StrLen nLen = 0;
1500 : 20 : nStt = nPos;
1501 [ - + ][ # # ]: 20 : if( ('"'==cChar) || ('\'')==cChar )
1502 : : {
1503 : 20 : sal_Unicode cEnd = cChar;
1504 : 20 : nPos++; nStt++;
1505 : 20 : bool bDone = false;
1506 : 20 : bool bEscape = false;
1507 [ + - ][ + + ]: 262 : while( nPos < aToken.Len() && !bDone )
[ + + ]
1508 : : {
1509 : 242 : bool bOldEscape = bEscape;
1510 : 242 : bEscape = false;
1511 : 242 : cChar = aToken.GetChar(nPos);
1512 [ - - + + ]: 242 : switch( cChar )
1513 : : {
1514 : : case '\r':
1515 : : case '\n':
1516 [ # # ]: 0 : if( bStripCRLF )
1517 [ # # ]: 0 : ((String &)aToken).Erase( nPos, 1 );
1518 : : else
1519 : 0 : nPos++, nLen++;
1520 : 0 : break;
1521 : : case '\\':
1522 [ # # ]: 0 : if( bOldEscape )
1523 : : {
1524 : 0 : nPos++, nLen++;
1525 : : }
1526 : : else
1527 : : {
1528 [ # # ]: 0 : ((String &)aToken).Erase( nPos, 1 );
1529 : 0 : bEscape = true;
1530 : : }
1531 : 0 : break;
1532 : : case '"':
1533 : : case '\'':
1534 [ + - ][ + - ]: 20 : bDone = !bOldEscape && cChar==cEnd;
1535 [ - + ]: 20 : if( !bDone )
1536 : 0 : nPos++, nLen++;
1537 : 20 : break;
1538 : : default:
1539 : 222 : nPos++, nLen++;
1540 : 222 : break;
1541 : : }
1542 : : }
1543 [ + - ]: 20 : if( nPos!=aToken.Len() )
1544 : 20 : nPos++;
1545 : : }
1546 : : else
1547 : : {
1548 : : // More liberal than the standard: allow all printable characters
1549 : 0 : bool bEscape = false;
1550 : 0 : bool bDone = false;
1551 [ # # ][ # # ]: 0 : while( nPos < aToken.Len() && !bDone )
[ # # ]
1552 : : {
1553 : 0 : bool bOldEscape = bEscape;
1554 : 0 : bEscape = false;
1555 : 0 : sal_Unicode c = aToken.GetChar(nPos);
1556 [ # # # # ]: 0 : switch( c )
1557 : : {
1558 : : case ' ':
1559 : 0 : bDone = !bOldEscape;
1560 [ # # ]: 0 : if( !bDone )
1561 : 0 : nPos++, nLen++;
1562 : 0 : break;
1563 : :
1564 : : case '\t':
1565 : : case '\r':
1566 : : case '\n':
1567 : 0 : bDone = true;
1568 : 0 : break;
1569 : :
1570 : : case '\\':
1571 [ # # ]: 0 : if( bOldEscape )
1572 : : {
1573 : 0 : nPos++, nLen++;
1574 : : }
1575 : : else
1576 : : {
1577 [ # # ]: 0 : ((String &)aToken).Erase( nPos, 1 );
1578 : 0 : bEscape = true;
1579 : : }
1580 : 0 : break;
1581 : :
1582 : : default:
1583 [ # # ][ # # ]: 0 : if( HTML_ISPRINTABLE( c ) )
1584 : 0 : nPos++, nLen++;
1585 : : else
1586 : 0 : bDone = true;
1587 : 0 : break;
1588 : : }
1589 : : }
1590 : : }
1591 : :
1592 [ + - ]: 20 : if( nLen )
1593 [ + - ][ + - ]: 20 : aValue = aToken.Copy( nStt, nLen );
[ + - ]
1594 : : }
1595 : : }
1596 : :
1597 : : // Token is known and can be saved
1598 : : std::auto_ptr<HTMLOption> pOption(
1599 [ + - ][ + - ]: 20 : new HTMLOption(sal::static_int_cast<sal_uInt16>(nToken), sName, aValue));
1600 : :
1601 [ + - ][ + - ]: 20 : maOptions.push_back(pOption);
[ + - ][ + - ]
[ + - ][ + - ]
1602 : :
1603 : : }
1604 : : else
1605 : : // Ignore white space and unexpected characters
1606 : 10 : nPos++;
1607 : : }
1608 : :
1609 : 73 : return maOptions;
1610 : : }
1611 : :
1612 : 0 : int HTMLParser::FilterPRE( int nToken )
1613 : : {
1614 [ # # # # : 0 : switch( nToken )
# # ]
1615 : : {
1616 : : #ifdef HTML_BEHAVIOUR
1617 : : // These become LFs according to the definition
1618 : : case HTML_PARABREAK_ON:
1619 : : case HTML_LINEBREAK:
1620 : : nToken = HTML_NEWPARA;
1621 : : #else
1622 : : // in Netscape they only have impact in not empty paragraphs
1623 : : case HTML_PARABREAK_ON:
1624 : 0 : nToken = HTML_LINEBREAK;
1625 : : case HTML_LINEBREAK:
1626 : : #endif
1627 : : case HTML_NEWPARA:
1628 : 0 : nPre_LinePos = 0;
1629 [ # # ]: 0 : if( bPre_IgnoreNewPara )
1630 : 0 : nToken = 0;
1631 : 0 : break;
1632 : :
1633 : : case HTML_TABCHAR:
1634 : : {
1635 : : xub_StrLen nSpaces = sal::static_int_cast< xub_StrLen >(
1636 : 0 : 8 - (nPre_LinePos % 8));
1637 : : DBG_ASSERT( !aToken.Len(), "Why is the token not empty?" );
1638 : 0 : aToken.Expand( nSpaces, ' ' );
1639 : 0 : nPre_LinePos += nSpaces;
1640 : 0 : nToken = HTML_TEXTTOKEN;
1641 : : }
1642 : 0 : break;
1643 : : // Keep those
1644 : : case HTML_TEXTTOKEN:
1645 : 0 : nPre_LinePos += aToken.Len();
1646 : 0 : break;
1647 : :
1648 : : case HTML_SELECT_ON:
1649 : : case HTML_SELECT_OFF:
1650 : : case HTML_BODY_ON:
1651 : : case HTML_FORM_ON:
1652 : : case HTML_FORM_OFF:
1653 : : case HTML_INPUT:
1654 : : case HTML_OPTION:
1655 : : case HTML_TEXTAREA_ON:
1656 : : case HTML_TEXTAREA_OFF:
1657 : :
1658 : : case HTML_IMAGE:
1659 : : case HTML_APPLET_ON:
1660 : : case HTML_APPLET_OFF:
1661 : : case HTML_PARAM:
1662 : : case HTML_EMBED:
1663 : :
1664 : : case HTML_HEAD1_ON:
1665 : : case HTML_HEAD1_OFF:
1666 : : case HTML_HEAD2_ON:
1667 : : case HTML_HEAD2_OFF:
1668 : : case HTML_HEAD3_ON:
1669 : : case HTML_HEAD3_OFF:
1670 : : case HTML_HEAD4_ON:
1671 : : case HTML_HEAD4_OFF:
1672 : : case HTML_HEAD5_ON:
1673 : : case HTML_HEAD5_OFF:
1674 : : case HTML_HEAD6_ON:
1675 : : case HTML_HEAD6_OFF:
1676 : : case HTML_BLOCKQUOTE_ON:
1677 : : case HTML_BLOCKQUOTE_OFF:
1678 : : case HTML_ADDRESS_ON:
1679 : : case HTML_ADDRESS_OFF:
1680 : : case HTML_HORZRULE:
1681 : :
1682 : : case HTML_CENTER_ON:
1683 : : case HTML_CENTER_OFF:
1684 : : case HTML_DIVISION_ON:
1685 : : case HTML_DIVISION_OFF:
1686 : :
1687 : : case HTML_SCRIPT_ON:
1688 : : case HTML_SCRIPT_OFF:
1689 : : case HTML_RAWDATA:
1690 : :
1691 : : case HTML_TABLE_ON:
1692 : : case HTML_TABLE_OFF:
1693 : : case HTML_CAPTION_ON:
1694 : : case HTML_CAPTION_OFF:
1695 : : case HTML_COLGROUP_ON:
1696 : : case HTML_COLGROUP_OFF:
1697 : : case HTML_COL_ON:
1698 : : case HTML_COL_OFF:
1699 : : case HTML_THEAD_ON:
1700 : : case HTML_THEAD_OFF:
1701 : : case HTML_TFOOT_ON:
1702 : : case HTML_TFOOT_OFF:
1703 : : case HTML_TBODY_ON:
1704 : : case HTML_TBODY_OFF:
1705 : : case HTML_TABLEROW_ON:
1706 : : case HTML_TABLEROW_OFF:
1707 : : case HTML_TABLEDATA_ON:
1708 : : case HTML_TABLEDATA_OFF:
1709 : : case HTML_TABLEHEADER_ON:
1710 : : case HTML_TABLEHEADER_OFF:
1711 : :
1712 : : case HTML_ANCHOR_ON:
1713 : : case HTML_ANCHOR_OFF:
1714 : : case HTML_BOLD_ON:
1715 : : case HTML_BOLD_OFF:
1716 : : case HTML_ITALIC_ON:
1717 : : case HTML_ITALIC_OFF:
1718 : : case HTML_STRIKE_ON:
1719 : : case HTML_STRIKE_OFF:
1720 : : case HTML_STRIKETHROUGH_ON:
1721 : : case HTML_STRIKETHROUGH_OFF:
1722 : : case HTML_UNDERLINE_ON:
1723 : : case HTML_UNDERLINE_OFF:
1724 : : case HTML_BASEFONT_ON:
1725 : : case HTML_BASEFONT_OFF:
1726 : : case HTML_FONT_ON:
1727 : : case HTML_FONT_OFF:
1728 : : case HTML_BLINK_ON:
1729 : : case HTML_BLINK_OFF:
1730 : : case HTML_SPAN_ON:
1731 : : case HTML_SPAN_OFF:
1732 : : case HTML_SUBSCRIPT_ON:
1733 : : case HTML_SUBSCRIPT_OFF:
1734 : : case HTML_SUPERSCRIPT_ON:
1735 : : case HTML_SUPERSCRIPT_OFF:
1736 : : case HTML_BIGPRINT_ON:
1737 : : case HTML_BIGPRINT_OFF:
1738 : : case HTML_SMALLPRINT_OFF:
1739 : : case HTML_SMALLPRINT_ON:
1740 : :
1741 : : case HTML_EMPHASIS_ON:
1742 : : case HTML_EMPHASIS_OFF:
1743 : : case HTML_CITIATION_ON:
1744 : : case HTML_CITIATION_OFF:
1745 : : case HTML_STRONG_ON:
1746 : : case HTML_STRONG_OFF:
1747 : : case HTML_CODE_ON:
1748 : : case HTML_CODE_OFF:
1749 : : case HTML_SAMPLE_ON:
1750 : : case HTML_SAMPLE_OFF:
1751 : : case HTML_KEYBOARD_ON:
1752 : : case HTML_KEYBOARD_OFF:
1753 : : case HTML_VARIABLE_ON:
1754 : : case HTML_VARIABLE_OFF:
1755 : : case HTML_DEFINSTANCE_ON:
1756 : : case HTML_DEFINSTANCE_OFF:
1757 : : case HTML_SHORTQUOTE_ON:
1758 : : case HTML_SHORTQUOTE_OFF:
1759 : : case HTML_LANGUAGE_ON:
1760 : : case HTML_LANGUAGE_OFF:
1761 : : case HTML_AUTHOR_ON:
1762 : : case HTML_AUTHOR_OFF:
1763 : : case HTML_PERSON_ON:
1764 : : case HTML_PERSON_OFF:
1765 : : case HTML_ACRONYM_ON:
1766 : : case HTML_ACRONYM_OFF:
1767 : : case HTML_ABBREVIATION_ON:
1768 : : case HTML_ABBREVIATION_OFF:
1769 : : case HTML_INSERTEDTEXT_ON:
1770 : : case HTML_INSERTEDTEXT_OFF:
1771 : : case HTML_DELETEDTEXT_ON:
1772 : : case HTML_DELETEDTEXT_OFF:
1773 : : case HTML_TELETYPE_ON:
1774 : : case HTML_TELETYPE_OFF:
1775 : :
1776 : 0 : break;
1777 : :
1778 : : // The remainder is treated as an unknown token.
1779 : : default:
1780 [ # # ]: 0 : if( nToken )
1781 : : {
1782 : : nToken =
1783 : : ( ((HTML_TOKEN_ONOFF & nToken) && (1 & nToken))
1784 : : ? HTML_UNKNOWNCONTROL_OFF
1785 [ # # ][ # # ]: 0 : : HTML_UNKNOWNCONTROL_ON );
1786 : : }
1787 : 0 : break;
1788 : : }
1789 : :
1790 : 0 : bPre_IgnoreNewPara = false;
1791 : :
1792 : 0 : return nToken;
1793 : : }
1794 : :
1795 : 0 : int HTMLParser::FilterXMP( int nToken )
1796 : : {
1797 [ # # # ]: 0 : switch( nToken )
1798 : : {
1799 : : case HTML_NEWPARA:
1800 [ # # ]: 0 : if( bPre_IgnoreNewPara )
1801 : 0 : nToken = 0;
1802 : : case HTML_TEXTTOKEN:
1803 : : case HTML_NONBREAKSPACE:
1804 : : case HTML_SOFTHYPH:
1805 : 0 : break; // kept
1806 : :
1807 : : default:
1808 [ # # ]: 0 : if( nToken )
1809 : : {
1810 [ # # ][ # # ]: 0 : if( (HTML_TOKEN_ONOFF & nToken) && (1 & nToken) )
1811 : : {
1812 : 0 : sSaveToken.Insert( '<', 0 );
1813 : 0 : sSaveToken.Insert( '/', 1 );
1814 : : }
1815 : : else
1816 : 0 : sSaveToken.Insert( '<', 0 );
1817 [ # # ]: 0 : if( aToken.Len() )
1818 : : {
1819 : 0 : UnescapeToken();
1820 : 0 : sSaveToken += (sal_Unicode)' ';
1821 : 0 : aToken.Insert( sSaveToken, 0 );
1822 : : }
1823 : : else
1824 : 0 : aToken = sSaveToken;
1825 : 0 : aToken += (sal_Unicode)'>';
1826 : 0 : nToken = HTML_TEXTTOKEN;
1827 : : }
1828 : 0 : break;
1829 : : }
1830 : :
1831 : 0 : bPre_IgnoreNewPara = false;
1832 : :
1833 : 0 : return nToken;
1834 : : }
1835 : :
1836 : 0 : int HTMLParser::FilterListing( int nToken )
1837 : : {
1838 [ # # # ]: 0 : switch( nToken )
1839 : : {
1840 : : case HTML_NEWPARA:
1841 [ # # ]: 0 : if( bPre_IgnoreNewPara )
1842 : 0 : nToken = 0;
1843 : : case HTML_TEXTTOKEN:
1844 : : case HTML_NONBREAKSPACE:
1845 : : case HTML_SOFTHYPH:
1846 : 0 : break; // kept
1847 : :
1848 : : default:
1849 [ # # ]: 0 : if( nToken )
1850 : : {
1851 : : nToken =
1852 : : ( ((HTML_TOKEN_ONOFF & nToken) && (1 & nToken))
1853 : : ? HTML_UNKNOWNCONTROL_OFF
1854 [ # # ][ # # ]: 0 : : HTML_UNKNOWNCONTROL_ON );
1855 : : }
1856 : 0 : break;
1857 : : }
1858 : :
1859 : 0 : bPre_IgnoreNewPara = false;
1860 : :
1861 : 0 : return nToken;
1862 : : }
1863 : :
1864 : 2 : bool HTMLParser::IsHTMLFormat( const sal_Char* pHeader,
1865 : : bool bSwitchToUCS2,
1866 : : rtl_TextEncoding eEnc )
1867 : : {
1868 : : // If the string matches one of the following regular expressions then
1869 : : // the document is a HTML document.
1870 : : //
1871 : : // ^[^<]*<[^ \t]*[> \t]
1872 : : // -------
1873 : : // ^<!
1874 : : //
1875 : : // where the underlined subexpression has to be a HTML token
1876 : 2 : rtl::OString sCmp;
1877 : 2 : bool bUCS2B = false;
1878 [ + - ]: 2 : if( bSwitchToUCS2 )
1879 : : {
1880 [ - + ][ # # ]: 2 : if( 0xfeU == (sal_uChar)pHeader[0] &&
1881 : 0 : 0xffU == (sal_uChar)pHeader[1] )
1882 : : {
1883 : 0 : eEnc = RTL_TEXTENCODING_UCS2;
1884 : 0 : bUCS2B = true;
1885 : : }
1886 [ - + ][ # # ]: 2 : else if( 0xffU == (sal_uChar)pHeader[0] &&
1887 : 0 : 0xfeU == (sal_uChar)pHeader[1] )
1888 : : {
1889 : 2 : eEnc = RTL_TEXTENCODING_UCS2;
1890 : : }
1891 : : }
1892 [ - + ][ # # ]: 2 : if
[ # # ][ # # ]
[ # # ]
1893 : : (
1894 : : RTL_TEXTENCODING_UCS2 == eEnc &&
1895 : : (
1896 : 0 : (0xfe == (sal_uChar)pHeader[0] && 0xff == (sal_uChar)pHeader[1]) ||
1897 : 0 : (0xff == (sal_uChar)pHeader[0] && 0xfe == (sal_uChar)pHeader[1])
1898 : : )
1899 : : )
1900 : : {
1901 [ # # ]: 0 : if( 0xfe == (sal_uChar)pHeader[0] )
1902 : 0 : bUCS2B = true;
1903 : :
1904 : : xub_StrLen nLen;
1905 [ # # ][ # # ]: 0 : for( nLen = 2;
[ # # ]
1906 : 0 : pHeader[nLen] != 0 || pHeader[nLen+1] != 0;
1907 : : nLen+=2 )
1908 : : ;
1909 : :
1910 : 0 : ::rtl::OStringBuffer sTmp( (nLen - 2)/2 );
1911 [ # # ]: 0 : for( xub_StrLen nPos = 2; nPos < nLen; nPos += 2 )
1912 : : {
1913 : : sal_Unicode cUC;
1914 [ # # ]: 0 : if( bUCS2B )
1915 : 0 : cUC = (sal_Unicode(pHeader[nPos]) << 8) | pHeader[nPos+1];
1916 : : else
1917 : 0 : cUC = (sal_Unicode(pHeader[nPos+1]) << 8) | pHeader[nPos];
1918 [ # # ]: 0 : if( 0U == cUC )
1919 : 0 : break;
1920 : :
1921 [ # # ][ # # ]: 0 : sTmp.append( cUC < 256U ? (sal_Char)cUC : '.' );
1922 : : }
1923 : 0 : sCmp = sTmp.makeStringAndClear();
1924 : : }
1925 : : else
1926 : : {
1927 : 2 : sCmp = pHeader;
1928 : : }
1929 : :
1930 : 2 : sCmp = sCmp.toAsciiUpperCase();
1931 : :
1932 : : // A HTML document must have a '<' in the first line
1933 : 2 : sal_Int32 nStart = sCmp.indexOf('<');
1934 [ - + ]: 2 : if (nStart == -1)
1935 : 0 : return false;
1936 : 2 : nStart++;
1937 : :
1938 : : // followed by arbitrary characters followed by a blank or '>'
1939 : : sal_Char c;
1940 : : sal_Int32 nPos;
1941 [ + - ]: 18 : for( nPos = nStart; nPos < sCmp.getLength(); ++nPos )
1942 : : {
1943 [ + - ][ + + ]: 18 : if( '>'==(c=sCmp[nPos]) || HTML_ISSPACE(c) )
[ + - ][ - + ]
[ + + ]
1944 : 2 : break;
1945 : : }
1946 : :
1947 : : // If the document ends after < it's no HTML
1948 [ - + ]: 2 : if( nPos==nStart )
1949 : 0 : return false;
1950 : :
1951 : : // the string following '<' has to be a known HTML token.
1952 : : // <DIR> is not interpreted as HTML. Otherwise the output of the DOS command "DIR"
1953 : : // could be interpreted as HTML.
1954 [ + - ]: 2 : rtl::OUString sTest(rtl::OStringToOUString(sCmp.copy(nStart, nPos-nStart), RTL_TEXTENCODING_ASCII_US));
1955 [ + - ][ + - ]: 2 : int nTok = GetHTMLToken( sTest );
[ + - ]
1956 [ + - ][ + - ]: 2 : if( 0 != nTok && HTML_DIRLIST_ON != nTok )
1957 : 2 : return true;
1958 : :
1959 : : // "<!" at the very beginning of the file?
1960 [ # # ][ # # ]: 0 : if( nStart == 1 && '!' == sCmp[1] )
[ # # ]
1961 : 0 : return true;
1962 : :
1963 : : // <HTML> somewhere in the first 80 characters of the document
1964 : 0 : nStart = sCmp.indexOfL(RTL_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_html));
1965 [ # # # # : 0 : if( nStart>0 && '<'==sCmp[nStart-1] &&
# # ][ # # ]
[ # # ]
1966 : 0 : nStart+4 < sCmp.getLength() && '>'==sCmp[nStart+4] )
1967 : 0 : return true;
1968 : :
1969 : : // Else it's rather not a HTML document
1970 : 2 : return false;
1971 : : }
1972 : :
1973 : 0 : bool HTMLParser::InternalImgToPrivateURL( String& rURL )
1974 : : {
1975 [ # # ]: 0 : if( rURL.Len() < 19 || 'i' != rURL.GetChar(0) ||
[ # # # # ]
[ # # ]
1976 : 0 : rURL.CompareToAscii( OOO_STRING_SVTOOLS_HTML_internal_gopher, 9 ) != COMPARE_EQUAL )
1977 : 0 : return false;
1978 : :
1979 : 0 : bool bFound = false;
1980 : :
1981 [ # # ]: 0 : if( rURL.CompareToAscii( OOO_STRING_SVTOOLS_HTML_internal_gopher,16) == COMPARE_EQUAL )
1982 : : {
1983 [ # # ]: 0 : String aName( rURL.Copy(16) );
1984 [ # # # # : 0 : switch( aName.GetChar(0) )
# # # ]
1985 : : {
1986 : : case 'b':
1987 [ # # ]: 0 : bFound = aName.EqualsAscii( OOO_STRING_SVTOOLS_HTML_INT_GOPHER_binary );
1988 : 0 : break;
1989 : : case 'i':
1990 [ # # ]: 0 : bFound = aName.EqualsAscii( OOO_STRING_SVTOOLS_HTML_INT_GOPHER_image ) ||
1991 [ # # ][ # # ]: 0 : aName.EqualsAscii( OOO_STRING_SVTOOLS_HTML_INT_GOPHER_index );
[ # # ]
1992 : 0 : break;
1993 : : case 'm':
1994 [ # # ]: 0 : bFound = aName.EqualsAscii( OOO_STRING_SVTOOLS_HTML_INT_GOPHER_menu ) ||
1995 [ # # ][ # # ]: 0 : aName.EqualsAscii( OOO_STRING_SVTOOLS_HTML_INT_GOPHER_movie );
[ # # ]
1996 : 0 : break;
1997 : : case 's':
1998 [ # # ]: 0 : bFound = aName.EqualsAscii( OOO_STRING_SVTOOLS_HTML_INT_GOPHER_sound );
1999 : 0 : break;
2000 : : case 't':
2001 [ # # ]: 0 : bFound = aName.EqualsAscii( OOO_STRING_SVTOOLS_HTML_INT_GOPHER_telnet ) ||
2002 [ # # ][ # # ]: 0 : aName.EqualsAscii( OOO_STRING_SVTOOLS_HTML_INT_GOPHER_text );
[ # # ]
2003 : 0 : break;
2004 : : case 'u':
2005 [ # # ]: 0 : bFound = aName.EqualsAscii( OOO_STRING_SVTOOLS_HTML_INT_GOPHER_unknown );
2006 : 0 : break;
2007 [ # # ]: 0 : }
2008 : : }
2009 [ # # ]: 0 : else if( rURL.CompareToAscii( OOO_STRING_SVTOOLS_HTML_internal_icon,14) == COMPARE_EQUAL )
2010 : : {
2011 [ # # ]: 0 : String aName( rURL.Copy(14) );
2012 [ # # # # : 0 : switch( aName.GetChar(0) )
# # ]
2013 : : {
2014 : : case 'b':
2015 [ # # ]: 0 : bFound = aName.EqualsAscii( OOO_STRING_SVTOOLS_HTML_INT_ICON_baddata );
2016 : 0 : break;
2017 : : case 'd':
2018 [ # # ]: 0 : bFound = aName.EqualsAscii( OOO_STRING_SVTOOLS_HTML_INT_ICON_delayed );
2019 : 0 : break;
2020 : : case 'e':
2021 [ # # ]: 0 : bFound = aName.EqualsAscii( OOO_STRING_SVTOOLS_HTML_INT_ICON_embed );
2022 : 0 : break;
2023 : : case 'i':
2024 [ # # ]: 0 : bFound = aName.EqualsAscii( OOO_STRING_SVTOOLS_HTML_INT_ICON_insecure );
2025 : 0 : break;
2026 : : case 'n':
2027 [ # # ]: 0 : bFound = aName.EqualsAscii( OOO_STRING_SVTOOLS_HTML_INT_ICON_notfound );
2028 : 0 : break;
2029 [ # # ]: 0 : }
2030 : : }
2031 [ # # ]: 0 : if( bFound )
2032 : : {
2033 [ # # ]: 0 : String sTmp ( rURL );
2034 [ # # ]: 0 : rURL.AssignAscii( OOO_STRING_SVTOOLS_HTML_private_image );
2035 [ # # ][ # # ]: 0 : rURL.Append( sTmp );
2036 : : }
2037 : :
2038 : 0 : return bFound;
2039 : : }
2040 : :
2041 : : enum eHtmlMetas {
2042 : : HTML_META_NONE = 0,
2043 : : HTML_META_AUTHOR,
2044 : : HTML_META_DESCRIPTION,
2045 : : HTML_META_KEYWORDS,
2046 : : HTML_META_REFRESH,
2047 : : HTML_META_CLASSIFICATION,
2048 : : HTML_META_CREATED,
2049 : : HTML_META_CHANGEDBY,
2050 : : HTML_META_CHANGED,
2051 : : HTML_META_GENERATOR,
2052 : : HTML_META_SDFOOTNOTE,
2053 : : HTML_META_SDENDNOTE,
2054 : : HTML_META_CONTENT_TYPE
2055 : : };
2056 : :
2057 : : // <META NAME=xxx>
2058 : : static HTMLOptionEnum const aHTMLMetaNameTable[] =
2059 : : {
2060 : : { OOO_STRING_SVTOOLS_HTML_META_author, HTML_META_AUTHOR },
2061 : : { OOO_STRING_SVTOOLS_HTML_META_changed, HTML_META_CHANGED },
2062 : : { OOO_STRING_SVTOOLS_HTML_META_changedby, HTML_META_CHANGEDBY },
2063 : : { OOO_STRING_SVTOOLS_HTML_META_classification,HTML_META_CLASSIFICATION},
2064 : : { OOO_STRING_SVTOOLS_HTML_META_content_type, HTML_META_CONTENT_TYPE },
2065 : : { OOO_STRING_SVTOOLS_HTML_META_created, HTML_META_CREATED },
2066 : : { OOO_STRING_SVTOOLS_HTML_META_description, HTML_META_DESCRIPTION },
2067 : : { OOO_STRING_SVTOOLS_HTML_META_keywords, HTML_META_KEYWORDS },
2068 : : { OOO_STRING_SVTOOLS_HTML_META_generator, HTML_META_GENERATOR },
2069 : : { OOO_STRING_SVTOOLS_HTML_META_refresh, HTML_META_REFRESH },
2070 : : { OOO_STRING_SVTOOLS_HTML_META_sdendnote, HTML_META_SDENDNOTE },
2071 : : { OOO_STRING_SVTOOLS_HTML_META_sdfootnote, HTML_META_SDFOOTNOTE },
2072 : : { 0, 0 }
2073 : : };
2074 : :
2075 : :
2076 : 0 : void HTMLParser::AddMetaUserDefined( ::rtl::OUString const & )
2077 : : {
2078 : 0 : }
2079 : :
2080 : 8 : bool HTMLParser::ParseMetaOptionsImpl(
2081 : : const uno::Reference<document::XDocumentProperties> & i_xDocProps,
2082 : : SvKeyValueIterator *i_pHTTPHeader,
2083 : : const HTMLOptions& aOptions,
2084 : : rtl_TextEncoding& o_rEnc )
2085 : : {
2086 [ + - ][ + - ]: 8 : String aName, aContent;
2087 : 8 : sal_uInt16 nAction = HTML_META_NONE;
2088 : 8 : bool bHTTPEquiv = false, bChanged = false;
2089 : :
2090 [ + + ]: 24 : for ( size_t i = aOptions.size(); i; )
2091 : : {
2092 [ + - ]: 16 : const HTMLOption& aOption = aOptions[--i];
2093 [ + + + - ]: 16 : switch ( aOption.GetToken() )
2094 : : {
2095 : : case HTML_O_NAME:
2096 [ + - ]: 6 : aName = aOption.GetString();
2097 [ + - ]: 6 : if ( HTML_META_NONE==nAction )
2098 : : {
2099 [ + - ]: 6 : aOption.GetEnum( nAction, aHTMLMetaNameTable );
2100 : : }
2101 : 6 : break;
2102 : : case HTML_O_HTTPEQUIV:
2103 [ + - ]: 2 : aName = aOption.GetString();
2104 [ + - ]: 2 : aOption.GetEnum( nAction, aHTMLMetaNameTable );
2105 : 2 : bHTTPEquiv = true;
2106 : 2 : break;
2107 : : case HTML_O_CONTENT:
2108 [ + - ]: 8 : aContent = aOption.GetString();
2109 : 8 : break;
2110 : : }
2111 : : }
2112 : :
2113 [ + + ][ + - ]: 8 : if ( bHTTPEquiv || HTML_META_DESCRIPTION != nAction )
2114 : : {
2115 : : // if it is not a Description, remove CRs and LFs from CONTENT
2116 [ + - ][ + - ]: 8 : aContent = comphelper::string::remove(aContent, _CR);
2117 [ + - ][ + - ]: 8 : aContent = comphelper::string::remove(aContent, _LF);
2118 : : }
2119 : : else
2120 : : {
2121 : : // convert line endings for Description
2122 [ # # ][ # # ]: 0 : aContent = convertLineEnd(aContent, GetSystemLineEnd());
[ # # ]
2123 : : }
2124 : :
2125 : :
2126 [ + + ][ + - ]: 8 : if ( bHTTPEquiv && i_pHTTPHeader )
2127 : : {
2128 : : // Netscape seems to just ignore a closing ", so we do too
2129 [ + - ][ - + ]: 2 : if ( aContent.Len() && '"' == aContent.GetChar( aContent.Len()-1 ) )
[ - + ]
2130 : : {
2131 [ # # ]: 0 : aContent.Erase( aContent.Len() - 1 );
2132 : : }
2133 [ + - ]: 2 : SvKeyValue aKeyValue( aName, aContent );
2134 [ + - ][ + - ]: 2 : i_pHTTPHeader->Append( aKeyValue );
2135 : : }
2136 : :
2137 [ - - - - : 8 : switch ( nAction )
- + - + -
+ ]
2138 : : {
2139 : : case HTML_META_AUTHOR:
2140 [ # # ]: 0 : if (i_xDocProps.is()) {
2141 [ # # ][ # # ]: 0 : i_xDocProps->setAuthor( aContent );
[ # # ]
2142 : 0 : bChanged = true;
2143 : : }
2144 : 0 : break;
2145 : : case HTML_META_DESCRIPTION:
2146 [ # # ]: 0 : if (i_xDocProps.is()) {
2147 [ # # ][ # # ]: 0 : i_xDocProps->setDescription( aContent );
[ # # ]
2148 : 0 : bChanged = true;
2149 : : }
2150 : 0 : break;
2151 : : case HTML_META_KEYWORDS:
2152 [ # # ]: 0 : if (i_xDocProps.is()) {
2153 [ # # ]: 0 : i_xDocProps->setKeywords(
2154 [ # # ][ # # ]: 0 : ::comphelper::string::convertCommaSeparated(aContent));
[ # # ][ # # ]
2155 : 0 : bChanged = true;
2156 : : }
2157 : 0 : break;
2158 : : case HTML_META_CLASSIFICATION:
2159 [ # # ]: 0 : if (i_xDocProps.is()) {
2160 [ # # ][ # # ]: 0 : i_xDocProps->setSubject( aContent );
[ # # ]
2161 : 0 : bChanged = true;
2162 : : }
2163 : 0 : break;
2164 : :
2165 : : case HTML_META_CHANGEDBY:
2166 [ # # ]: 0 : if (i_xDocProps.is()) {
2167 [ # # ][ # # ]: 0 : i_xDocProps->setModifiedBy( aContent );
[ # # ]
2168 : : }
2169 : 0 : break;
2170 : :
2171 : : case HTML_META_CREATED:
2172 : : case HTML_META_CHANGED:
2173 [ + - ][ + - ]: 12 : if ( i_xDocProps.is() && aContent.Len() &&
[ + - ][ + - ]
2174 [ + - ][ + - ]: 8 : comphelper::string::getTokenCount(aContent, ';') == 2 )
[ + - ][ # # ]
2175 : : {
2176 [ + - ][ + - ]: 4 : Date aDate( (sal_uLong)aContent.GetToken(0).ToInt32() );
[ + - ]
2177 [ + - ][ + - ]: 4 : Time aTime( (sal_uLong)aContent.GetToken(1).ToInt32() );
[ + - ]
2178 [ + - ]: 4 : DateTime aDateTime( aDate, aTime );
2179 : 4 : ::util::DateTime uDT(aDateTime.Get100Sec(),
2180 : 4 : aDateTime.GetSec(), aDateTime.GetMin(),
2181 : 4 : aDateTime.GetHour(), aDateTime.GetDay(),
2182 : 8 : aDateTime.GetMonth(), aDateTime.GetYear());
2183 [ + + ]: 4 : if ( HTML_META_CREATED==nAction )
2184 [ + - ][ + - ]: 2 : i_xDocProps->setCreationDate( uDT );
2185 : : else
2186 [ + - ][ + - ]: 2 : i_xDocProps->setModificationDate( uDT );
2187 : 4 : bChanged = true;
2188 : : }
2189 : 4 : break;
2190 : :
2191 : : case HTML_META_REFRESH:
2192 : : DBG_ASSERT( !bHTTPEquiv || i_pHTTPHeader,
2193 : : "Reload-URL aufgrund unterlassener MUSS-Aenderung verlorengegangen" );
2194 : 0 : break;
2195 : :
2196 : : case HTML_META_CONTENT_TYPE:
2197 [ + - ]: 2 : if ( aContent.Len() )
2198 : : {
2199 [ + - ]: 2 : o_rEnc = GetEncodingByMIME( aContent );
2200 : : }
2201 : 2 : break;
2202 : :
2203 : : case HTML_META_NONE:
2204 [ # # ]: 0 : if ( !bHTTPEquiv )
2205 : : {
2206 [ # # ]: 0 : if (i_xDocProps.is())
2207 : : {
2208 : : uno::Reference<beans::XPropertyContainer> xUDProps
2209 [ # # ][ # # ]: 0 : = i_xDocProps->getUserDefinedProperties();
2210 : : try {
2211 [ # # ]: 0 : xUDProps->addProperty(aName,
2212 : : beans::PropertyAttribute::REMOVEABLE,
2213 [ # # ][ # # ]: 0 : uno::makeAny(::rtl::OUString(aContent)));
[ # # ][ # # ]
2214 [ # # ][ # # ]: 0 : AddMetaUserDefined(aName);
[ # # ]
2215 : 0 : bChanged = true;
2216 [ # # ]: 0 : } catch (uno::Exception &) {
2217 : : // ignore
2218 : 0 : }
2219 : : }
2220 : : }
2221 : 0 : break;
2222 : : default:
2223 : 2 : break;
2224 : : }
2225 : :
2226 [ + - ][ + - ]: 8 : return bChanged;
2227 : : }
2228 : :
2229 : 8 : bool HTMLParser::ParseMetaOptions(
2230 : : const uno::Reference<document::XDocumentProperties> & i_xDocProps,
2231 : : SvKeyValueIterator *i_pHeader )
2232 : : {
2233 : 8 : sal_uInt16 nContentOption = HTML_O_CONTENT;
2234 : 8 : rtl_TextEncoding eEnc = RTL_TEXTENCODING_DONTKNOW;
2235 : :
2236 : : bool bRet = ParseMetaOptionsImpl( i_xDocProps, i_pHeader,
2237 [ + - ]: 8 : GetOptions(&nContentOption),
2238 [ + - ]: 8 : eEnc );
2239 : :
2240 : : // If the encoding is set by a META tag, it may only overwrite the
2241 : : // current encoding if both, the current and the new encoding, are 1-sal_uInt8
2242 : : // encodings. Everything else cannot lead to reasonable results.
2243 [ + + ][ + - ]: 12 : if (RTL_TEXTENCODING_DONTKNOW != eEnc &&
[ + - ][ + + ]
2244 [ + - ]: 2 : rtl_isOctetTextEncoding( eEnc ) &&
2245 [ + - ]: 2 : rtl_isOctetTextEncoding( GetSrcEncoding() ) )
2246 : : {
2247 [ + - ]: 2 : eEnc = GetExtendedCompatibilityTextEncoding( eEnc );
2248 [ + - ]: 2 : SetSrcEncoding( eEnc );
2249 : : }
2250 : :
2251 : 8 : return bRet;
2252 : : }
2253 : :
2254 : 2 : rtl_TextEncoding HTMLParser::GetEncodingByMIME( const String& rMime )
2255 : : {
2256 [ + - ]: 2 : String sType;
2257 [ + - ]: 2 : String sSubType;
2258 [ + - ]: 2 : INetContentTypeParameterList aParameters;
2259 [ + - ][ + - ]: 2 : if (INetContentTypes::parse(rMime, sType, sSubType, &aParameters))
2260 : : {
2261 : : const INetContentTypeParameter * pCharset
2262 [ + - ]: 2 : = aParameters.find("charset");
2263 [ + - ]: 2 : if (pCharset != 0)
2264 : : {
2265 : : rtl::OString sValue(rtl::OUStringToOString(pCharset->m_sValue,
2266 [ + - ]: 2 : RTL_TEXTENCODING_ASCII_US));
2267 : : return GetExtendedCompatibilityTextEncoding(
2268 [ + - ][ + - ]: 2 : rtl_getTextEncodingFromMimeCharset( sValue.getStr() ) );
2269 : : }
2270 : : }
2271 [ + - ][ + - ]: 2 : return RTL_TEXTENCODING_DONTKNOW;
[ + - ]
2272 : : }
2273 : :
2274 : 5 : rtl_TextEncoding HTMLParser::GetEncodingByHttpHeader( SvKeyValueIterator *pHTTPHeader )
2275 : : {
2276 : 5 : rtl_TextEncoding eRet = RTL_TEXTENCODING_DONTKNOW;
2277 [ + - ]: 5 : if( pHTTPHeader )
2278 : : {
2279 [ + - ]: 5 : SvKeyValue aKV;
2280 [ + - ][ + + ]: 10 : for( bool bCont = pHTTPHeader->GetFirst( aKV ); bCont;
2281 [ + - ]: 5 : bCont = pHTTPHeader->GetNext( aKV ) )
2282 : : {
2283 [ + - ][ + - ]: 5 : if( aKV.GetKey().EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_content_type ) )
2284 : : {
2285 [ - + ]: 5 : if( aKV.GetValue().Len() )
2286 : : {
2287 [ # # ]: 0 : eRet = HTMLParser::GetEncodingByMIME( aKV.GetValue() );
2288 : : }
2289 : : }
2290 [ + - ]: 5 : }
2291 : : }
2292 : 5 : return eRet;
2293 : : }
2294 : :
2295 : 5 : bool HTMLParser::SetEncodingByHTTPHeader( SvKeyValueIterator *pHTTPHeader )
2296 : : {
2297 : 5 : bool bRet = false;
2298 : 5 : rtl_TextEncoding eEnc = HTMLParser::GetEncodingByHttpHeader( pHTTPHeader );
2299 [ - + ]: 5 : if(RTL_TEXTENCODING_DONTKNOW != eEnc)
2300 : : {
2301 : 0 : SetSrcEncoding( eEnc );
2302 : 0 : bRet = true;
2303 : : }
2304 : 5 : return bRet;
2305 : : }
2306 : :
2307 : :
2308 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|