LCOV - code coverage report
Current view: top level - svtools/source/svhtml - parhtml.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 445 968 46.0 %
Date: 2014-11-03 Functions: 21 31 67.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10