Coverage Report

Created: 2026-07-10 11:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/svtools/parhtml.hxx
Line
Count
Source
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
#pragma once
21
22
#include <svtools/svtdllapi.h>
23
#include <svtools/svparser.hxx>
24
25
#include <string_view>
26
#include <vector>
27
28
namespace com::sun::star::uno { template <class interface_type> class Reference; }
29
30
namespace com::sun::star {
31
    namespace document {
32
        class XDocumentProperties;
33
    }
34
}
35
36
class Color;
37
enum class HtmlOptionId;
38
enum class HtmlTokenId : sal_Int16;
39
40
#define HTMLFONTSZ1_DFLT 7
41
#define HTMLFONTSZ2_DFLT 10
42
#define HTMLFONTSZ3_DFLT 12
43
#define HTMLFONTSZ4_DFLT 14
44
#define HTMLFONTSZ5_DFLT 18
45
#define HTMLFONTSZ6_DFLT 24
46
#define HTMLFONTSZ7_DFLT 36
47
48
enum class HTMLTableFrame { Void, Above, Below, HSides, LHS, RHS, VSides, Box };
49
50
enum class HTMLTableRules { NONE, Groups, Rows, Cols, All };
51
52
enum class HTMLInputType
53
{
54
    Text =      1,
55
    Password,
56
    Checkbox,
57
    Radio,
58
    Range,
59
    Scribble,
60
    File,
61
    Hidden,
62
    Submit,
63
    Image,
64
    Reset,
65
    Button
66
};
67
68
enum class HTMLScriptLanguage
69
{
70
    StarBasic,
71
    JavaScript,
72
    Unknown
73
};
74
75
template<typename EnumT>
76
struct HTMLOptionEnum
77
{
78
    const char *pName;  // value of an HTML option
79
    EnumT       nValue; // and corresponding value of an enum
80
};
81
82
/** Representation of an HTML option (=attribute in a start tag).
83
 * The values of the options are always stored as strings.
84
 * The methods GetNumber,... may only be called if the option
85
 * is actually numerical,...
86
 */
87
class SVT_DLLPUBLIC HTMLOption
88
{
89
    OUString aValue;          // value of the option (always as string)
90
    OUString aToken;          // name of the option as string
91
    HtmlOptionId nToken;        // and respective token
92
93
public:
94
95
    HTMLOption( HtmlOptionId nTyp, OUString aToken, OUString aValue );
96
97
    // name of the option...
98
1.76M
    HtmlOptionId GetToken() const { return nToken; }  // ... as enum
99
27.5k
    const OUString& GetTokenString() const { return aToken; } // ... as string
100
101
    // value of the option ...
102
941k
    const OUString& GetString() const { return aValue; }  // ... as string
103
104
    sal_uInt32 GetNumber() const;                           // ... as number
105
    sal_Int32 GetSNumber() const;                           // ... as number
106
    void GetNumbers( std::vector<sal_uInt32> &rNumbers ) const; // ... as numbers
107
    void GetColor( Color& ) const;                      // ... as color
108
109
    template<typename EnumT>
110
    EnumT GetEnum( const HTMLOptionEnum<EnumT> *pOptEnums,
111
                        EnumT nDflt = static_cast<EnumT>(0) ) const
112
55.6k
    {
113
182k
        while( pOptEnums->pName )
114
171k
        {
115
171k
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
116
45.0k
                return pOptEnums->nValue;
117
126k
            pOptEnums++;
118
126k
        }
119
10.6k
        return nDflt;
120
55.6k
    }
Unexecuted instantiation: HTMLInputType HTMLOption::GetEnum<HTMLInputType>(HTMLOptionEnum<HTMLInputType> const*, HTMLInputType) const
HTMLTableFrame HTMLOption::GetEnum<HTMLTableFrame>(HTMLOptionEnum<HTMLTableFrame> const*, HTMLTableFrame) const
Line
Count
Source
112
3.23k
    {
113
8.81k
        while( pOptEnums->pName )
114
8.27k
        {
115
8.27k
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
116
2.69k
                return pOptEnums->nValue;
117
5.58k
            pOptEnums++;
118
5.58k
        }
119
542
        return nDflt;
120
3.23k
    }
HTMLTableRules HTMLOption::GetEnum<HTMLTableRules>(HTMLOptionEnum<HTMLTableRules> const*, HTMLTableRules) const
Line
Count
Source
112
695
    {
113
2.12k
        while( pOptEnums->pName )
114
1.98k
        {
115
1.98k
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
116
553
                return pOptEnums->nValue;
117
1.42k
            pOptEnums++;
118
1.42k
        }
119
142
        return nDflt;
120
695
    }
SvxAdjust HTMLOption::GetEnum<SvxAdjust>(HTMLOptionEnum<SvxAdjust> const*, SvxAdjust) const
Line
Count
Source
112
36.1k
    {
113
121k
        while( pOptEnums->pName )
114
116k
        {
115
116k
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
116
30.7k
                return pOptEnums->nValue;
117
85.4k
            pOptEnums++;
118
85.4k
        }
119
5.40k
        return nDflt;
120
36.1k
    }
short HTMLOption::GetEnum<short>(HTMLOptionEnum<short> const*, short) const
Line
Count
Source
112
13.9k
    {
113
46.1k
        while( pOptEnums->pName )
114
41.9k
        {
115
41.9k
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
116
9.72k
                return pOptEnums->nValue;
117
32.2k
            pOptEnums++;
118
32.2k
        }
119
4.22k
        return nDflt;
120
13.9k
    }
SdrTextAniKind HTMLOption::GetEnum<SdrTextAniKind>(HTMLOptionEnum<SdrTextAniKind> const*, SdrTextAniKind) const
Line
Count
Source
112
51
    {
113
155
        while( pOptEnums->pName )
114
141
        {
115
141
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
116
37
                return pOptEnums->nValue;
117
104
            pOptEnums++;
118
104
        }
119
14
        return nDflt;
120
51
    }
SdrTextAniDirection HTMLOption::GetEnum<SdrTextAniDirection>(HTMLOptionEnum<SdrTextAniDirection> const*, SdrTextAniDirection) const
Line
Count
Source
112
112
    {
113
224
        while( pOptEnums->pName )
114
196
        {
115
196
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
116
84
                return pOptEnums->nValue;
117
112
            pOptEnums++;
118
112
        }
119
28
        return nDflt;
120
112
    }
com::sun::star::form::FormSubmitMethod HTMLOption::GetEnum<com::sun::star::form::FormSubmitMethod>(HTMLOptionEnum<com::sun::star::form::FormSubmitMethod> const*, com::sun::star::form::FormSubmitMethod) const
Line
Count
Source
112
651
    {
113
1.36k
        while( pOptEnums->pName )
114
1.23k
        {
115
1.23k
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
116
524
                return pOptEnums->nValue;
117
714
            pOptEnums++;
118
714
        }
119
127
        return nDflt;
120
651
    }
com::sun::star::form::FormSubmitEncoding HTMLOption::GetEnum<com::sun::star::form::FormSubmitEncoding>(HTMLOptionEnum<com::sun::star::form::FormSubmitEncoding> const*, com::sun::star::form::FormSubmitEncoding) const
Line
Count
Source
112
547
    {
113
1.41k
        while( pOptEnums->pName )
114
1.25k
        {
115
1.25k
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
116
389
                return pOptEnums->nValue;
117
863
            pOptEnums++;
118
863
        }
119
158
        return nDflt;
120
547
    }
Unexecuted instantiation: htmlform.cxx:(anonymous namespace)::HTMLWordWrapMode HTMLOption::GetEnum<(anonymous namespace)::HTMLWordWrapMode>(HTMLOptionEnum<(anonymous namespace)::HTMLWordWrapMode> const*, (anonymous namespace)::HTMLWordWrapMode) const
unsigned int HTMLOption::GetEnum<unsigned int>(HTMLOptionEnum<unsigned int> const*, unsigned int) const
Line
Count
Source
112
145
    {
113
152
        while( pOptEnums->pName )
114
151
        {
115
151
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
116
144
                return pOptEnums->nValue;
117
7
            pOptEnums++;
118
7
        }
119
1
        return nDflt;
120
145
    }
ScrollingMode HTMLOption::GetEnum<ScrollingMode>(HTMLOptionEnum<ScrollingMode> const*, ScrollingMode) const
Line
Count
Source
112
115
    {
113
262
        while( pOptEnums->pName )
114
250
        {
115
250
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
116
103
                return pOptEnums->nValue;
117
147
            pOptEnums++;
118
147
        }
119
12
        return nDflt;
120
115
    }
121
122
    template<typename EnumT>
123
    bool GetEnum( EnumT &rEnum, const HTMLOptionEnum<EnumT> *pOptEnums ) const
124
51.7k
    {
125
353k
        while( pOptEnums->pName )
126
339k
        {
127
339k
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
128
38.4k
            {
129
38.4k
                rEnum = pOptEnums->nValue;
130
38.4k
                return true;
131
38.4k
            }
132
301k
            pOptEnums++;
133
301k
        }
134
13.3k
        return false;
135
51.7k
    }
bool HTMLOption::GetEnum<IMapObjectType>(IMapObjectType&, HTMLOptionEnum<IMapObjectType> const*) const
Line
Count
Source
124
1.80k
    {
125
3.92k
        while( pOptEnums->pName )
126
3.64k
        {
127
3.64k
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
128
1.52k
            {
129
1.52k
                rEnum = pOptEnums->nValue;
130
1.52k
                return true;
131
1.52k
            }
132
2.12k
            pOptEnums++;
133
2.12k
        }
134
284
        return false;
135
1.80k
    }
parhtml.cxx:bool HTMLOption::GetEnum<(anonymous namespace)::HtmlMeta>((anonymous namespace)::HtmlMeta&, HTMLOptionEnum<(anonymous namespace)::HtmlMeta> const*) const
Line
Count
Source
124
36.2k
    {
125
267k
        while( pOptEnums->pName )
126
255k
        {
127
255k
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
128
24.9k
            {
129
24.9k
                rEnum = pOptEnums->nValue;
130
24.9k
                return true;
131
24.9k
            }
132
230k
            pOptEnums++;
133
230k
        }
134
11.3k
        return false;
135
36.2k
    }
Unexecuted instantiation: bool HTMLOption::GetEnum<unsigned short>(unsigned short&, HTMLOptionEnum<unsigned short> const*) const
bool HTMLOption::GetEnum<SwFieldIds>(SwFieldIds&, HTMLOptionEnum<SwFieldIds> const*) const
Line
Count
Source
124
6.66k
    {
125
39.2k
        while( pOptEnums->pName )
126
38.5k
        {
127
38.5k
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
128
5.97k
            {
129
5.97k
                rEnum = pOptEnums->nValue;
130
5.97k
                return true;
131
5.97k
            }
132
32.5k
            pOptEnums++;
133
32.5k
        }
134
685
        return false;
135
6.66k
    }
bool HTMLOption::GetEnum<SwExtUserSubType>(SwExtUserSubType&, HTMLOptionEnum<SwExtUserSubType> const*) const
Line
Count
Source
124
470
    {
125
7.46k
        while( pOptEnums->pName )
126
7.02k
        {
127
7.02k
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
128
30
            {
129
30
                rEnum = pOptEnums->nValue;
130
30
                return true;
131
30
            }
132
6.99k
            pOptEnums++;
133
6.99k
        }
134
440
        return false;
135
470
    }
Unexecuted instantiation: bool HTMLOption::GetEnum<SwAuthorFormat>(SwAuthorFormat&, HTMLOptionEnum<SwAuthorFormat> const*) const
Unexecuted instantiation: bool HTMLOption::GetEnum<SwPageNumSubType>(SwPageNumSubType&, HTMLOptionEnum<SwPageNumSubType> const*) const
Unexecuted instantiation: bool HTMLOption::GetEnum<SvxNumType>(SvxNumType&, HTMLOptionEnum<SvxNumType> const*) const
bool HTMLOption::GetEnum<SwDocInfoSubType>(SwDocInfoSubType&, HTMLOptionEnum<SwDocInfoSubType> const*) const
Line
Count
Source
124
3.81k
    {
125
27.6k
        while( pOptEnums->pName )
126
27.2k
        {
127
27.2k
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
128
3.50k
            {
129
3.50k
                rEnum = pOptEnums->nValue;
130
3.50k
                return true;
131
3.50k
            }
132
23.7k
            pOptEnums++;
133
23.7k
        }
134
303
        return false;
135
3.81k
    }
Unexecuted instantiation: bool HTMLOption::GetEnum<SwDocStatSubType>(SwDocStatSubType&, HTMLOptionEnum<SwDocStatSubType> const*) const
Unexecuted instantiation: bool HTMLOption::GetEnum<SwFileNameFormat>(SwFileNameFormat&, HTMLOptionEnum<SwFileNameFormat> const*) const
bool HTMLOption::GetEnum<SvxAdjust>(SvxAdjust&, HTMLOptionEnum<SvxAdjust> const*) const
Line
Count
Source
124
2.28k
    {
125
6.97k
        while( pOptEnums->pName )
126
6.77k
        {
127
6.77k
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
128
2.08k
            {
129
2.08k
                rEnum = pOptEnums->nValue;
130
2.08k
                return true;
131
2.08k
            }
132
4.69k
            pOptEnums++;
133
4.69k
        }
134
206
        return false;
135
2.28k
    }
bool HTMLOption::GetEnum<HTMLScriptLanguage>(HTMLScriptLanguage&, HTMLOptionEnum<HTMLScriptLanguage> const*) const
Line
Count
Source
124
414
    {
125
976
        while( pOptEnums->pName )
126
928
        {
127
928
            if( aValue.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) )
128
366
            {
129
366
                rEnum = pOptEnums->nValue;
130
366
                return true;
131
366
            }
132
562
            pOptEnums++;
133
562
        }
134
48
        return false;
135
414
    }
136
137
    // ... and as a few special enums
138
    HTMLInputType GetInputType() const;                 // <INPUT TYPE=...>
139
    HTMLTableFrame GetTableFrame() const;               // <TABLE FRAME=...>
140
    HTMLTableRules GetTableRules() const;               // <TABLE RULES=...>
141
    //SvxAdjust GetAdjust() const;                      // <P,TH,TD ALIGN=>
142
};
143
144
typedef ::std::vector<HTMLOption> HTMLOptions;
145
146
class SVT_DLLPUBLIC HTMLParser : public SvParser<HtmlTokenId>
147
{
148
private:
149
    mutable HTMLOptions maOptions; // options of the start tag
150
151
    bool bNewDoc        : 1;        // read new Doc?
152
    bool bIsInHeader    : 1;        // scan header section
153
    bool bReadListing   : 1;        // read listings
154
    bool bReadXMP       : 1;        // read XMP
155
    bool bReadPRE       : 1;        // read preformatted text
156
    bool bReadTextArea  : 1;        // read TEXTAREA
157
    bool bReadScript    : 1;        // read <SCRIPT>
158
    bool bReadStyle     : 1;        // read <STYLE>
159
    bool bEndTokenFound : 1;        // found </SCRIPT> or </STYLE>
160
161
    bool bPre_IgnoreNewPara : 1;    // flags for reading of PRE paragraphs
162
    bool bReadNextChar : 1;         // true: read NextChar again(JavaScript!)
163
    bool bReadComment : 1;          // true: read NextChar again (JavaScript!)
164
165
    bool m_bPreserveSpaces : 1 = false;
166
167
    sal_uInt32 nPre_LinePos;            // Pos in the line in the PRE-Tag
168
169
    HtmlTokenId mnPendingOffToken;          ///< OFF token pending for a <XX.../> ON/OFF ON token
170
171
    OUString aEndToken;
172
173
    /// XML namespace, in case of XHTML.
174
    OUString maNamespace;
175
176
protected:
177
    OUString sSaveToken;             // the read tag as string
178
179
    HtmlTokenId ScanText( const sal_Unicode cBreak = 0U );
180
181
    HtmlTokenId GetNextRawToken();
182
183
    // scan next token
184
    virtual HtmlTokenId GetNextToken_() override;
185
186
    virtual ~HTMLParser() override;
187
188
14.6k
    void FinishHeader() { bIsInHeader = false; }
189
190
    void SetNamespace(std::u16string_view rNamespace);
191
192
242k
    bool GetPreserveSpaces() const { return m_bPreserveSpaces; }
193
82.0k
    void SetPreserveSpaces(bool val) { m_bPreserveSpaces = val; }
194
195
public:
196
    HTMLParser( SvStream& rIn, bool bReadNewDoc = true );
197
198
    virtual SvParserState CallParser() override;
199
200
511k
    bool IsNewDoc() const       { return bNewDoc; }
201
231k
    bool IsInHeader() const     { return bIsInHeader; }
202
336k
    bool IsReadListing() const  { return bReadListing; }
203
336k
    bool IsReadXMP() const      { return bReadXMP; }
204
2.27M
    bool IsReadPRE() const      { return bReadPRE; }
205
120k
    bool IsReadScript() const   { return bReadScript; }
206
108k
    bool IsReadStyle() const    { return bReadStyle; }
207
208
    // start PRE-/LISTING or XMP mode or filter tags respectively
209
    inline void StartPRE();
210
1.91k
    void FinishPRE() { bReadPRE = false; }
211
    HtmlTokenId FilterPRE( HtmlTokenId nToken );
212
213
    inline void StartListing();
214
72
    void FinishListing() { bReadListing = false; }
215
    HtmlTokenId FilterListing( HtmlTokenId nToken );
216
217
    inline void StartXMP();
218
285
    void FinishXMP() { bReadXMP = false; }
219
    HtmlTokenId FilterXMP( HtmlTokenId nToken );
220
221
1.24k
    void FinishTextArea() { bReadTextArea = false; }
222
223
    // finish PRE-/LISTING- and XMP mode
224
672k
    void FinishPREListingXMP() { bReadPRE = bReadListing = bReadXMP = false; }
225
226
    // Filter the current token according to the current mode
227
    // (PRE, XMP, ...) and set the flags. Is called by Continue before
228
    // NextToken is called. If you implement own loops or call
229
    // NextToken yourself, you should call this method beforehand.
230
    HtmlTokenId FilterToken( HtmlTokenId nToken );
231
232
29
    void ReadRawData( const OUString &rEndToken ) { aEndToken = rEndToken; }
233
234
    // Token without \-sequences
235
    void UnescapeToken();
236
237
    // Determine the options. pNoConvertToken is the optional token
238
    // of an option, for which the CR/LFs are not deleted from the value
239
    // of the option.
240
    const HTMLOptions& GetOptions( HtmlOptionId const *pNoConvertToken=nullptr );
241
242
    // for asynchronous reading from the SvStream
243
    virtual void Continue( HtmlTokenId nToken ) override;
244
245
246
protected:
247
248
    static rtl_TextEncoding GetEncodingByMIME( const OUString& rMime );
249
250
    /// template method: called when ParseMetaOptions adds a user-defined meta
251
    virtual void AddMetaUserDefined( OUString const & i_rMetaName );
252
253
private:
254
    /// parse meta options into XDocumentProperties and encoding
255
    bool ParseMetaOptionsImpl( const css::uno::Reference< css::document::XDocumentProperties>&,
256
            SvKeyValueIterator*,
257
            const HTMLOptions&,
258
            rtl_TextEncoding& rEnc );
259
260
public:
261
    /// overriding method must call this implementation!
262
    virtual bool ParseMetaOptions( const css::uno::Reference< css::document::XDocumentProperties>&,
263
            SvKeyValueIterator* );
264
265
    void ParseScriptOptions( OUString& rLangString, std::u16string_view rBaseURL, HTMLScriptLanguage& rLang,
266
                             OUString& rSrc, OUString& rLibrary, OUString& rModule );
267
268
    // Remove a comment around the content of <SCRIPT> or <STYLE>.
269
    // The whole line behind a "<!--" might be deleted (for JavaScript).
270
    static void RemoveSGMLComment( OUString &rString );
271
272
    static bool InternalImgToPrivateURL( OUString& rURL );
273
    static rtl_TextEncoding GetEncodingByHttpHeader( SvKeyValueIterator *pHTTPHeader );
274
    bool SetEncodingByHTTPHeader( SvKeyValueIterator *pHTTPHeader );
275
};
276
277
inline void HTMLParser::StartPRE()
278
34.8k
{
279
34.8k
    bReadPRE = true;
280
34.8k
    bPre_IgnoreNewPara = true;
281
34.8k
    nPre_LinePos = 0;
282
34.8k
}
283
284
inline void HTMLParser::StartListing()
285
1.20k
{
286
1.20k
    bReadListing = true;
287
1.20k
    bPre_IgnoreNewPara = true;
288
1.20k
    nPre_LinePos = 0;
289
1.20k
}
290
291
inline void HTMLParser::StartXMP()
292
7.53k
{
293
7.53k
    bReadXMP = true;
294
7.53k
    bPre_IgnoreNewPara = true;
295
7.53k
    nPre_LinePos = 0;
296
7.53k
}
297
298
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */