Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svtools/source/svrtf/parrtf.cxx
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
#include <sal/config.h>
21
#include <sal/log.hxx>
22
23
#include <comphelper/scopeguard.hxx>
24
25
#include <o3tl/numeric.hxx>
26
#include <rtl/character.hxx>
27
#include <rtl/strbuf.hxx>
28
#include <rtl/tencinfo.h>
29
#include <rtl/ustrbuf.hxx>
30
#include <tools/stream.hxx>
31
#include <tools/debug.hxx>
32
#include <svtools/rtftoken.h>
33
#include <svtools/parrtf.hxx>
34
35
const int MAX_STRING_LEN = 1024;
36
37
10.7M
#define RTF_ISDIGIT( c ) rtl::isAsciiDigit(c)
38
28.3M
#define RTF_ISALPHA( c ) rtl::isAsciiAlpha(c)
39
40
SvRTFParser::SvRTFParser( SvStream& rIn, sal_uInt8 nStackSize )
41
27.6k
    : SvParser<int>( rIn, nStackSize )
42
27.6k
    , nOpenBrackets(0)
43
27.6k
    , nUPRLevel(0)
44
27.6k
    , eCodeSet(RTL_TEXTENCODING_MS_1252)
45
27.6k
    , nUCharOverread(1)
46
27.6k
{
47
    // default is ANSI-CodeSet
48
27.6k
    SetSrcEncoding( RTL_TEXTENCODING_MS_1252 );
49
27.6k
    bRTF_InTextRead = false;
50
27.6k
}
51
52
SvRTFParser::~SvRTFParser()
53
27.6k
{
54
27.6k
}
55
56
57
int SvRTFParser::GetNextToken_()
58
4.36M
{
59
4.36M
    int nRet = 0;
60
4.64M
    do {
61
4.64M
        bool bNextCh = true;
62
4.64M
        switch( nNextCh )
63
4.64M
        {
64
2.03M
        case '\\':
65
2.03M
            {
66
                // control characters
67
2.03M
                nNextCh = GetNextChar();
68
2.03M
                switch( nNextCh )
69
2.03M
                {
70
11.7k
                case '{':
71
14.2k
                case '}':
72
38.6k
                case '\\':
73
39.2k
                case '+':       // I found it in a RTF-file
74
40.1k
                case '~':       // nonbreaking space
75
41.5k
                case '-':       // optional hyphen
76
42.4k
                case '_':       // nonbreaking hyphen
77
54.8k
                case '\'':      // HexValue
78
54.8k
                    nNextCh = '\\';
79
54.8k
                    rInput.SeekRel( -1 );
80
54.8k
                    ScanText();
81
54.8k
                    nRet = RTF_TEXTTOKEN;
82
54.8k
                    bNextCh = 0 == nNextCh;
83
54.8k
                    break;
84
85
22.7k
                case '*':       // ignoreflag
86
22.7k
                    nRet = RTF_IGNOREFLAG;
87
22.7k
                    break;
88
5.82k
                case ':':       // subentry in an index entry
89
5.82k
                    nRet = RTF_SUBENTRYINDEX;
90
5.82k
                    break;
91
1.45k
                case '|':       // formula-character
92
1.45k
                    nRet = RTF_FORMULA;
93
1.45k
                    break;
94
95
589k
                case 0x0a:
96
610k
                case 0x0d:
97
610k
                    nRet = RTF_PAR;
98
610k
                    break;
99
100
1.34M
                default:
101
1.34M
                    if( RTF_ISALPHA( nNextCh ) )
102
1.15M
                    {
103
1.15M
                        aToken = "\\";
104
1.15M
                        {
105
3.90M
                            do {
106
3.90M
                                aToken.appendUtf32(nNextCh);
107
3.90M
                                nNextCh = GetNextChar();
108
3.90M
                            } while( RTF_ISALPHA( nNextCh ) );
109
1.15M
                        }
110
111
                        // minus before numeric parameters
112
1.15M
                        bool bNegValue = false;
113
1.15M
                        if( '-' == nNextCh )
114
45.5k
                        {
115
45.5k
                            bNegValue = true;
116
45.5k
                            nNextCh = GetNextChar();
117
45.5k
                        }
118
119
                        // possible numeric parameter
120
1.15M
                        if( RTF_ISDIGIT( nNextCh ) )
121
370k
                        {
122
370k
                            OUStringBuffer aNumber;
123
840k
                            do {
124
840k
                                aNumber.append(static_cast<sal_Unicode>(nNextCh));
125
840k
                                nNextCh = GetNextChar();
126
840k
                            } while( RTF_ISDIGIT( nNextCh ) );
127
370k
                            nTokenValue = OUString::unacquired(aNumber).toInt32();
128
370k
                            if( bNegValue )
129
22.9k
                                nTokenValue = -nTokenValue;
130
370k
                            bTokenHasValue=true;
131
370k
                        }
132
788k
                        else if( bNegValue )        // restore minus
133
22.6k
                        {
134
22.6k
                            nNextCh = '-';
135
22.6k
                            rInput.SeekRel( -1 );
136
22.6k
                        }
137
1.15M
                        if( ' ' == nNextCh )        // blank is part of token!
138
76.6k
                            nNextCh = GetNextChar();
139
140
                        // search for the token in the table:
141
1.15M
                        if( 0 == (nRet = GetRTFToken( aToken )) )
142
                            // Unknown Control
143
267k
                            nRet = RTF_UNKNOWNCONTROL;
144
145
                        // bug 76812 - unicode token handled as normal text
146
1.15M
                        bNextCh = false;
147
1.15M
                        switch( nRet )
148
1.15M
                        {
149
5.18k
                        case RTF_UC:
150
5.18k
                            if( 0 <= nTokenValue )
151
4.25k
                            {
152
4.25k
                                nUCharOverread = static_cast<sal_uInt8>(nTokenValue);
153
4.25k
                                if (!aParserStates.empty())
154
3.87k
                                {
155
                                    //cmc: other ifdef breaks #i3584
156
3.87k
                                    aParserStates.top().nUCharOverread = nUCharOverread;
157
3.87k
                                }
158
4.25k
                            }
159
5.18k
                            aToken.setLength( 0 ); // #i47831# erase token to prevent the token from being treated as text
160
                            // read next token
161
5.18k
                            nRet = 0;
162
5.18k
                            break;
163
164
7.03k
                        case RTF_UPR:
165
7.03k
                            if (!_inSkipGroup)
166
6.24k
                            {
167
6.24k
                                if (nUPRLevel > 256) // fairly sure > 1 is probably an error, but provide some leeway
168
235
                                {
169
235
                                    SAL_WARN("svtools", "urp stack too deep");
170
235
                                    eState = SvParserState::Error;
171
235
                                    break;
172
235
                                }
173
174
6.00k
                                ++nUPRLevel;
175
176
                                // UPR - overread the group with the ansi
177
                                //       information
178
6.00k
                                int nNextToken;
179
6.00k
                                do
180
9.13k
                                {
181
9.13k
                                    nNextToken = GetNextToken_();
182
9.13k
                                }
183
9.13k
                                while (nNextToken != '{' && nNextToken != sal_Unicode(EOF) && IsParserWorking());
184
185
6.00k
                                SkipGroup();
186
6.00k
                                GetNextToken_();  // overread the last bracket
187
6.00k
                                nRet = 0;
188
189
6.00k
                                --nUPRLevel;
190
6.00k
                            }
191
6.79k
                            break;
192
193
24.0k
                        case RTF_U:
194
24.0k
                            if( !bRTF_InTextRead )
195
12.8k
                            {
196
12.8k
                                nRet = RTF_TEXTTOKEN;
197
12.8k
                                aToken = OUStringChar( static_cast<sal_Unicode>(nTokenValue) );
198
199
                                // overread the next n "RTF" characters. This
200
                                // can be also \{, \}, \'88
201
34.8k
                                for( sal_uInt8 m = 0; m < nUCharOverread; ++m )
202
21.9k
                                {
203
21.9k
                                    sal_uInt32 cAnsi = nNextCh;
204
23.0k
                                    while( 0xD == cAnsi )
205
1.04k
                                        cAnsi = GetNextChar();
206
23.7k
                                    while( 0xA == cAnsi )
207
1.79k
                                        cAnsi = GetNextChar();
208
209
21.9k
                                    if( '\\' == cAnsi &&
210
4.07k
                                        '\'' == GetNextChar() )
211
                                        // skip HexValue
212
348
                                        GetHexValue();
213
21.9k
                                    nNextCh = GetNextChar();
214
21.9k
                                }
215
12.8k
                                ScanText();
216
12.8k
                                bNextCh = 0 == nNextCh;
217
12.8k
                            }
218
24.0k
                            break;
219
1.15M
                        }
220
1.15M
                    }
221
182k
                    else if( SvParserState::Pending != eState )
222
182k
                    {
223
                        // Bug 34631 - "\ " read on - Blank as character
224
                        // eState = SvParserState::Error;
225
182k
                        bNextCh = false;
226
182k
                    }
227
1.34M
                    break;
228
2.03M
                }
229
2.03M
            }
230
2.03M
            break;
231
232
2.03M
        case sal_Unicode(EOF):
233
32.2k
            eState = SvParserState::Accepted;
234
32.2k
            nRet = nNextCh;
235
32.2k
            break;
236
237
329k
        case '{':
238
329k
            {
239
329k
                if( 0 <= nOpenBrackets )
240
327k
                {
241
327k
                    RtfParserState_Impl aState( nUCharOverread, GetSrcEncoding() );
242
327k
                    aParserStates.push( aState );
243
327k
                }
244
329k
                ++nOpenBrackets;
245
329k
                DBG_ASSERT(
246
329k
                    static_cast<size_t>(nOpenBrackets) == aParserStates.size(),
247
329k
                    "ParserStateStack unequal to bracket count" );
248
329k
                nRet = nNextCh;
249
329k
            }
250
329k
            break;
251
252
119k
        case '}':
253
119k
            --nOpenBrackets;
254
119k
            if( 0 <= nOpenBrackets )
255
108k
            {
256
108k
                aParserStates.pop();
257
108k
                if( !aParserStates.empty() )
258
107k
                {
259
107k
                    const RtfParserState_Impl& rRPS =
260
107k
                            aParserStates.top();
261
107k
                    nUCharOverread = rRPS.nUCharOverread;
262
107k
                    SetSrcEncoding( rRPS.eCodeSet );
263
107k
                }
264
1.45k
                else
265
1.45k
                {
266
1.45k
                    nUCharOverread = 1;
267
1.45k
                    SetSrcEncoding( GetCodeSet() );
268
1.45k
                }
269
108k
            }
270
119k
            DBG_ASSERT(
271
119k
                static_cast<size_t>(nOpenBrackets) == aParserStates.size(),
272
119k
                "ParserStateStack unequal to bracket count" );
273
119k
            nRet = nNextCh;
274
119k
            break;
275
276
20.7k
        case 0x0d:
277
93.8k
        case 0x0a:
278
93.8k
            break;
279
280
2.03M
        default:
281
            // now normal text follows
282
2.03M
            ScanText();
283
2.03M
            nRet = RTF_TEXTTOKEN;
284
2.03M
            bNextCh = 0 == nNextCh;
285
2.03M
            break;
286
4.64M
        }
287
288
4.64M
        if( bNextCh )
289
2.15M
            nNextCh = GetNextChar();
290
291
4.64M
    } while( !nRet && SvParserState::Working == eState );
292
4.36M
    return nRet;
293
4.36M
}
294
295
296
sal_Unicode SvRTFParser::GetHexValue()
297
42.8k
{
298
    // collect Hex values
299
42.8k
    sal_uInt32 nHi = GetNextChar();
300
42.8k
    sal_uInt32 nLo = GetNextChar();
301
42.8k
    nNextCh = nLo;
302
42.8k
    return o3tl::convertToHex<sal_Unicode, 0>(nHi, nLo);
303
42.8k
}
304
305
void SvRTFParser::ScanText()
306
2.10M
{
307
2.10M
    const sal_Unicode cBreak = 0;
308
2.10M
    OUStringBuffer aStrBuffer;
309
2.10M
    bool bContinue = true;
310
10.2M
    while( bContinue && IsParserWorking() && aStrBuffer.getLength() < MAX_STRING_LEN)
311
8.15M
    {
312
8.15M
        bool bNextCh = true;
313
8.15M
        switch( nNextCh )
314
8.15M
        {
315
1.13M
        case '\\':
316
1.13M
            {
317
1.13M
                nNextCh = GetNextChar();
318
1.13M
                switch (nNextCh)
319
1.13M
                {
320
22.6k
                case '\'':
321
22.6k
                    {
322
323
22.6k
                        OStringBuffer aByteString;
324
41.5k
                        while (true)
325
41.5k
                        {
326
41.5k
                            char c = static_cast<char>(GetHexValue());
327
                            /*
328
                             * Note: \'00 is a valid internal character in  a
329
                             * string in RTF. OStringBuffer supports
330
                             * appending nulls fine
331
                             */
332
41.5k
                            aByteString.append(c);
333
334
41.5k
                            bool bBreak = false;
335
41.5k
                            bool bEOF = false;
336
41.5k
                            char nSlash = '\\';
337
301k
                            while (!bBreak)
338
260k
                            {
339
260k
                                auto next = GetNextChar();
340
260k
                                if (sal_Unicode(EOF) == next)
341
979
                                {
342
979
                                    bEOF = true;
343
979
                                    break;
344
979
                                }
345
259k
                                if (next>0xFF) // fix for #i43933# and #i35653#
346
7.61k
                                {
347
7.61k
                                    if (!aByteString.isEmpty())
348
4.78k
                                    {
349
4.78k
                                        aStrBuffer.append( OStringToOUString(aByteString, GetSrcEncoding()) );
350
4.78k
                                        aByteString.setLength(0);
351
4.78k
                                    }
352
7.61k
                                    aStrBuffer.append(static_cast<sal_Unicode>(next));
353
354
7.61k
                                    continue;
355
7.61k
                                }
356
251k
                                nSlash = static_cast<char>(next);
357
254k
                                while (nSlash == 0xD || nSlash == 0xA)
358
2.94k
                                    nSlash = static_cast<char>(GetNextChar());
359
360
251k
                                switch (nSlash)
361
251k
                                {
362
1.40k
                                    case '{':
363
2.16k
                                    case '}':
364
40.5k
                                    case '\\':
365
40.5k
                                        bBreak = true;
366
40.5k
                                        break;
367
211k
                                    default:
368
211k
                                        aByteString.append(nSlash);
369
211k
                                        break;
370
251k
                                }
371
251k
                            }
372
373
41.5k
                            if (bEOF)
374
979
                            {
375
979
                                bContinue = false;        // abort, string together
376
979
                                break;
377
979
                            }
378
379
40.5k
                            nNextCh = GetNextChar();
380
381
40.5k
                            if (nSlash != '\\' || nNextCh != '\'')
382
21.6k
                            {
383
21.6k
                                rInput.SeekRel(-1);
384
21.6k
                                nNextCh = static_cast<unsigned char>(nSlash);
385
21.6k
                                break;
386
21.6k
                            }
387
40.5k
                        }
388
389
22.6k
                        bNextCh = false;
390
391
22.6k
                        if (!aByteString.isEmpty())
392
21.0k
                        {
393
21.0k
                            aStrBuffer.append( OStringToOUString(aByteString, GetSrcEncoding()) );
394
21.0k
                            aByteString.setLength(0);
395
21.0k
                        }
396
22.6k
                    }
397
0
                    break;
398
78.7k
                case '\\':
399
102k
                case '}':
400
142k
                case '{':
401
144k
                case '+':       // I found in a RTF file
402
144k
                    aStrBuffer.append(sal_Unicode(nNextCh));
403
144k
                    break;
404
970
                case '~':       // nonbreaking space
405
970
                    aStrBuffer.append(u'\x00A0');
406
970
                    break;
407
3.02k
                case '-':       // optional hyphen
408
3.02k
                    aStrBuffer.append(u'\x00AD');
409
3.02k
                    break;
410
730
                case '_':       // nonbreaking hyphen
411
730
                    aStrBuffer.append(u'\x2011');
412
730
                    break;
413
414
31.3k
                case 'u':
415
                    // read UNI-Code characters
416
31.3k
                    {
417
31.3k
                        nNextCh = GetNextChar();
418
31.3k
                        rInput.SeekRel( -2 );
419
420
31.3k
                        if( '-' == nNextCh || RTF_ISDIGIT( nNextCh ) )
421
11.1k
                        {
422
11.1k
                            bRTF_InTextRead = true;
423
424
11.1k
                            OUString sSave( aToken ); // GetNextToken_() overwrites this
425
11.1k
                            nNextCh = '\\';
426
11.1k
                            int nToken = GetNextToken_();
427
11.1k
                            DBG_ASSERT( RTF_U == nToken, "still not a UNI-Code character" );
428
                            // don't convert symbol chars
429
11.1k
                            aStrBuffer.append(static_cast< sal_Unicode >(nTokenValue));
430
431
                            // overread the next n "RTF" characters. This
432
                            // can be also \{, \}, \'88
433
24.1k
                            for( sal_uInt8 m = 0; m < nUCharOverread; ++m )
434
13.0k
                            {
435
13.0k
                                sal_Unicode cAnsi = nNextCh;
436
13.3k
                                while( 0xD == cAnsi )
437
278
                                    cAnsi = GetNextChar();
438
15.1k
                                while( 0xA == cAnsi )
439
2.09k
                                    cAnsi = GetNextChar();
440
441
13.0k
                                if( '\\' == cAnsi &&
442
2.73k
                                    '\'' == GetNextChar() )
443
                                    // skip HexValue
444
965
                                    GetHexValue();
445
13.0k
                                nNextCh = GetNextChar();
446
13.0k
                            }
447
11.1k
                            bNextCh = false;
448
11.1k
                            aToken = sSave;
449
11.1k
                            bRTF_InTextRead = false;
450
11.1k
                        }
451
20.1k
                        else if ( 'c' == nNextCh )
452
2.13k
                        {
453
                            // Prevent text breaking into multiple tokens.
454
2.13k
                            rInput.SeekRel( 2 );
455
2.13k
                            nNextCh = GetNextChar();
456
2.13k
                            if (RTF_ISDIGIT( nNextCh ))
457
1.27k
                            {
458
1.27k
                                sal_uInt8 nNewOverread = 0 ;
459
1.84k
                                do {
460
1.84k
                                    nNewOverread *= 10;
461
1.84k
                                    nNewOverread += nNextCh - '0';
462
1.84k
                                    nNextCh = GetNextChar();
463
1.84k
                                } while ( RTF_ISDIGIT( nNextCh ) );
464
1.27k
                                nUCharOverread = nNewOverread;
465
1.27k
                                if (!aParserStates.empty())
466
1.00k
                                    aParserStates.top().nUCharOverread = nNewOverread;
467
1.27k
                            }
468
2.13k
                            bNextCh = 0x20 == nNextCh;
469
2.13k
                        }
470
18.0k
                        else
471
18.0k
                        {
472
18.0k
                            nNextCh = '\\';
473
18.0k
                            bContinue = false;        // abort, string together
474
18.0k
                        }
475
31.3k
                    }
476
31.3k
                    break;
477
478
936k
                default:
479
936k
                    rInput.SeekRel( -1 );
480
936k
                    nNextCh = '\\';
481
936k
                    bContinue = false;        // abort, string together
482
936k
                    break;
483
1.13M
                }
484
1.13M
            }
485
1.13M
            break;
486
487
1.13M
        case sal_Unicode(EOF):
488
1.99k
            eState = SvParserState::Error;
489
1.99k
            [[fallthrough]];
490
100k
        case '{':
491
184k
        case '}':
492
184k
            bContinue = false;
493
184k
            break;
494
495
116k
        case 0x0a:
496
131k
        case 0x0d:
497
131k
            break;
498
499
6.70M
        default:
500
6.70M
            if( nNextCh == cBreak || aStrBuffer.getLength() >= MAX_STRING_LEN)
501
943k
                bContinue = false;
502
5.75M
            else
503
5.75M
            {
504
11.5M
                do {
505
                    // all other characters end up in the text
506
11.5M
                    aStrBuffer.appendUtf32(nNextCh);
507
508
11.5M
                    if (sal_Unicode(EOF) == (nNextCh = GetNextChar()))
509
16.5k
                    {
510
16.5k
                        if (!aStrBuffer.isEmpty())
511
16.5k
                            aToken.append( aStrBuffer );
512
16.5k
                        return;
513
16.5k
                    }
514
11.5M
                } while
515
5.75M
                (
516
11.5M
                    (RTF_ISALPHA(nNextCh) || RTF_ISDIGIT(nNextCh)) &&
517
5.80M
                    (aStrBuffer.getLength() < MAX_STRING_LEN)
518
5.75M
                );
519
5.74M
                bNextCh = false;
520
5.74M
            }
521
8.15M
        }
522
523
8.13M
        if( bContinue && bNextCh )
524
281k
            nNextCh = GetNextChar();
525
8.13M
    }
526
527
2.08M
    if (!aStrBuffer.isEmpty())
528
1.38M
        aToken.append( aStrBuffer );
529
2.08M
}
530
531
532
short SvRTFParser::_inSkipGroup=0;
533
534
void SvRTFParser::SkipGroup()
535
10.9k
{
536
10.9k
    short nBrackets=1;
537
10.9k
    if (_inSkipGroup>0)
538
0
        return;
539
10.9k
    _inSkipGroup++;
540
//#i16185# faking \bin keyword
541
10.9k
    do
542
42.4k
    {
543
42.4k
        switch (nNextCh)
544
42.4k
        {
545
3.08k
            case '{':
546
3.08k
                ++nBrackets;
547
3.08k
                break;
548
7.07k
            case '}':
549
7.07k
                if (!--nBrackets) {
550
5.10k
                    _inSkipGroup--;
551
5.10k
                    return;
552
5.10k
                }
553
1.96k
                break;
554
42.4k
        }
555
37.2k
        int nToken = GetNextToken_();
556
37.2k
        if (nToken == RTF_BIN)
557
524
        {
558
524
            rInput.SeekRel(-1);
559
524
            SAL_WARN_IF(nTokenValue < 0, "svtools", "negative value argument for rtf \\bin keyword");
560
524
            if (nTokenValue > 0)
561
258
                rInput.SeekRel(nTokenValue);
562
524
            nNextCh = GetNextChar();
563
524
        }
564
38.1k
        while (nNextCh==0xa || nNextCh==0xd)
565
810
        {
566
810
            nNextCh = GetNextChar();
567
810
        }
568
37.2k
    } while (sal_Unicode(EOF) != nNextCh && IsParserWorking());
569
570
5.85k
    if( SvParserState::Pending != eState && '}' != nNextCh )
571
5.76k
        eState = SvParserState::Error;
572
5.85k
    _inSkipGroup--;
573
5.85k
}
574
575
1.76k
void SvRTFParser::ReadUnknownData() { SkipGroup(); }
576
28
void SvRTFParser::ReadBitmapData()  { SkipGroup(); }
577
578
579
SvParserState SvRTFParser::CallParser()
580
27.6k
{
581
27.6k
    char cFirstCh(0);
582
27.6k
    nNextChPos = rInput.Tell();
583
27.6k
    rInput.ReadChar( cFirstCh );
584
27.6k
    nNextCh = static_cast<unsigned char>(cFirstCh);
585
27.6k
    eState = SvParserState::Working;
586
27.6k
    nOpenBrackets = 0;
587
27.6k
    eCodeSet = RTL_TEXTENCODING_MS_1252;
588
27.6k
    SetSrcEncoding( eCodeSet );
589
590
    // the first two tokens should be '{' and \\rtf !!
591
27.6k
    if( '{' == GetNextToken() && RTF_RTF == GetNextToken() )
592
27.2k
    {
593
27.2k
        AddFirstRef();
594
        // call ReleaseRef at end of this scope, even in the face of exceptions
595
27.2k
        comphelper::ScopeGuard g([this] {
596
27.2k
            if( SvParserState::Pending != eState )
597
27.2k
                ReleaseRef();       // now parser is not needed anymore
598
27.2k
        });
599
27.2k
        Continue( 0 );
600
27.2k
    }
601
467
    else
602
467
        eState = SvParserState::Error;
603
604
27.6k
    return eState;
605
27.6k
}
606
607
void SvRTFParser::Continue( int nToken )
608
27.2k
{
609
//  DBG_ASSERT( SVPAR_CS_DONTKNOW == GetCharSet(),
610
//              "Characterset was changed." );
611
612
27.2k
    if( !nToken )
613
27.2k
        nToken = GetNextToken();
614
615
27.2k
    bool bLooping = false;
616
617
3.57M
    while (IsParserWorking() && !bLooping)
618
3.54M
    {
619
3.54M
        auto nCurrentTokenIndex = m_nTokenIndex;
620
3.54M
        auto nCurrentToken = nToken;
621
622
3.54M
        SaveState( nToken );
623
3.54M
        switch( nToken )
624
3.54M
        {
625
83.5k
        case '}':
626
83.5k
            if( nOpenBrackets )
627
82.4k
                goto NEXTTOKEN;
628
1.19k
            eState = SvParserState::Accepted;
629
1.19k
            break;
630
631
180k
        case '{':
632
            // an unknown group ?
633
180k
            {
634
180k
                if( RTF_IGNOREFLAG != GetNextToken() )
635
176k
                    nToken = SkipToken();
636
4.76k
                else if( RTF_UNKNOWNCONTROL != GetNextToken() )
637
4.14k
                    nToken = SkipToken( -2 );
638
617
                else
639
617
                {
640
                    // filter immediately
641
617
                    ReadUnknownData();
642
617
                    nToken = GetNextToken();
643
617
                    if( '}' != nToken )
644
121
                        eState = SvParserState::Error;
645
617
                    break;      // move to next token!!
646
617
                }
647
180k
            }
648
180k
            goto NEXTTOKEN;
649
650
240k
        case RTF_UNKNOWNCONTROL:
651
240k
            break;      // skip unknown token
652
0
        case RTF_NEXTTYPE:
653
2.85k
        case RTF_ANSITYPE:
654
2.85k
            eCodeSet = RTL_TEXTENCODING_MS_1252;
655
2.85k
            SetSrcEncoding( eCodeSet );
656
2.85k
            break;
657
1.29k
        case RTF_MACTYPE:
658
1.29k
            eCodeSet = RTL_TEXTENCODING_APPLE_ROMAN;
659
1.29k
            SetSrcEncoding( eCodeSet );
660
1.29k
            break;
661
1.54k
        case RTF_PCTYPE:
662
1.54k
            eCodeSet = RTL_TEXTENCODING_IBM_437;
663
1.54k
            SetSrcEncoding( eCodeSet );
664
1.54k
            break;
665
221
        case RTF_PCATYPE:
666
221
            eCodeSet = RTL_TEXTENCODING_IBM_850;
667
221
            SetSrcEncoding( eCodeSet );
668
221
            break;
669
16.8k
        case RTF_ANSICPG:
670
16.8k
            eCodeSet = rtl_getTextEncodingFromWindowsCodePage(nTokenValue);
671
16.8k
            SetSrcEncoding(eCodeSet);
672
16.8k
            break;
673
3.01M
        default:
674
3.27M
NEXTTOKEN:
675
3.27M
            NextToken( nToken );
676
3.27M
            break;
677
3.54M
        }
678
3.54M
        if( IsParserWorking() )
679
3.53M
            SaveState( 0 );         // processed till here,
680
                                    // continue with new token!
681
3.54M
        nToken = GetNextToken();
682
3.54M
        bLooping = nCurrentTokenIndex == m_nTokenIndex && nToken == nCurrentToken;
683
3.54M
    }
684
27.1k
    if( SvParserState::Accepted == eState && 0 < nOpenBrackets )
685
23.3k
        eState = SvParserState::Error;
686
27.1k
}
687
688
void SvRTFParser::SetEncoding( rtl_TextEncoding eEnc )
689
68.6k
{
690
68.6k
    if (eEnc == RTL_TEXTENCODING_DONTKNOW)
691
53.2k
        eEnc = GetCodeSet();
692
693
68.6k
    if (!aParserStates.empty())
694
67.8k
        aParserStates.top().eCodeSet = eEnc;
695
68.6k
    SetSrcEncoding(eEnc);
696
68.6k
}
697
698
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */