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

Generated by: LCOV version 1.10