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

Generated by: LCOV version 1.10