Coverage Report

Created: 2026-09-28 10:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/gdi/jobset.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 <rtl/ustring.hxx>
21
#include <sal/log.hxx>
22
#include <tools/solar.h>
23
#include <tools/stream.hxx>
24
#include <vcl/jobset.hxx>
25
#include <jobset.h>
26
#include <memory>
27
28
2.10k
#define JOBSET_FILE364_SYSTEM   (sal_uInt16(0xFFFF))
29
1.38k
#define JOBSET_FILE605_SYSTEM   (sal_uInt16(0xFFFE))
30
31
namespace {
32
33
// used only for compatibility with older versions,
34
// printer/driver name are truncated if too long,
35
// device name and port name are completely unused
36
struct ImplOldJobSetupData
37
{
38
    char    cPrinterName[64];
39
    char    cDeviceName[32];
40
    char    cPortName[32];
41
    char    cDriverName[32];
42
};
43
44
struct Impl364JobSetupData
45
{
46
    SVBT16  nSize;
47
    SVBT16  nSystem;
48
    SVBT32  nDriverDataLen;
49
    SVBT16  nOrientation;
50
    SVBT16  nPaperBin;
51
    SVBT16  nPaperFormat;
52
    SVBT32  nPaperWidth;
53
    SVBT32  nPaperHeight;
54
};
55
56
}
57
58
ImplJobSetup::ImplJobSetup()
59
12
{
60
12
    mnSystem            = 0;
61
12
    meOrientation       = Orientation::Portrait;
62
12
    meDuplexMode        = DuplexMode::Unknown;
63
12
    mnPaperBin          = 0;
64
12
    mePaperFormat       = PAPER_USER;
65
12
    mnPaperWidth        = 0;
66
12
    mnPaperHeight       = 0;
67
12
    mnDriverDataLen     = 0;
68
12
    mbPapersizeFromSetup = false;
69
12
    meSetupMode         = PrinterSetupMode::DocumentGlobal;
70
12
}
71
72
ImplJobSetup::ImplJobSetup( const ImplJobSetup& rJobSetup ) :
73
703
    mnSystem( rJobSetup.GetSystem() ),
74
703
    maPrinterName( rJobSetup.GetPrinterName() ),
75
703
    maDriver( rJobSetup.GetDriver() ),
76
703
    meOrientation( rJobSetup.GetOrientation() ),
77
703
    meDuplexMode( rJobSetup.GetDuplexMode() ),
78
703
    mnPaperBin( rJobSetup.GetPaperBin() ),
79
703
    mePaperFormat( rJobSetup.GetPaperFormat() ),
80
703
    mnPaperWidth( rJobSetup.GetPaperWidth() ),
81
703
    mnPaperHeight( rJobSetup.GetPaperHeight() ),
82
703
    mnDriverDataLen( rJobSetup.GetDriverDataLen() ),
83
703
    mpDriverData(),
84
703
    mbPapersizeFromSetup( rJobSetup.GetPapersizeFromSetup() ),
85
703
    meSetupMode( rJobSetup.GetPrinterSetupMode() ),
86
703
    maValueMap( rJobSetup.GetValueMap() )
87
703
 {
88
703
    if ( rJobSetup.GetDriverData() )
89
0
    {
90
0
        mpDriverData.reset( new sal_uInt8[mnDriverDataLen] );
91
0
        memcpy( mpDriverData.get(), rJobSetup.GetDriverData(), mnDriverDataLen );
92
0
    }
93
703
    else
94
703
        mpDriverData = nullptr;
95
703
}
96
97
ImplJobSetup::~ImplJobSetup()
98
712
{
99
712
}
100
101
void ImplJobSetup::SetSystem(sal_uInt16 nSystem)
102
685
{
103
685
    mnSystem = nSystem;
104
685
}
105
106
void ImplJobSetup::SetPrinterName(const OUString& rPrinterName)
107
703
{
108
703
    maPrinterName = rPrinterName;
109
703
}
110
111
void ImplJobSetup::SetDriver(const OUString& rDriver)
112
703
{
113
703
    maDriver = rDriver;
114
703
}
115
116
void ImplJobSetup::SetOrientation(Orientation eOrientation)
117
685
{
118
685
    meOrientation = eOrientation;
119
685
}
120
121
void ImplJobSetup::SetDuplexMode(DuplexMode eDuplexMode)
122
685
{
123
685
    meDuplexMode = eDuplexMode;
124
685
}
125
126
void ImplJobSetup::SetPaperBin(sal_uInt16 nPaperBin)
127
685
{
128
685
    mnPaperBin = nPaperBin;
129
685
}
130
131
void ImplJobSetup::SetPaperFormat(Paper ePaperFormat)
132
359
{
133
359
    mePaperFormat = ePaperFormat;
134
359
}
135
136
void ImplJobSetup::SetPaperWidth(tools::Long nPaperWidth)
137
685
{
138
685
    mnPaperWidth = nPaperWidth;
139
685
}
140
141
void ImplJobSetup::SetPaperHeight(tools::Long nPaperHeight)
142
685
{
143
685
    mnPaperHeight = nPaperHeight;
144
685
}
145
146
void ImplJobSetup::SetDriverData(std::unique_ptr<sal_uInt8[]> pDriverData, sal_uInt32 nDriverDataLen)
147
236
{
148
236
    mpDriverData = std::move(pDriverData);
149
236
    mnDriverDataLen = nDriverDataLen;
150
236
}
151
152
void ImplJobSetup::SetPapersizeFromSetup(bool bPapersizeFromSetup)
153
0
{
154
0
    mbPapersizeFromSetup = bPapersizeFromSetup;
155
0
}
156
157
void ImplJobSetup::SetPrinterSetupMode(PrinterSetupMode eMode)
158
0
{
159
0
    meSetupMode = eMode;
160
0
}
161
162
void ImplJobSetup::SetValueMap( const OUString& rKey, const OUString& rValue )
163
7.85k
{
164
7.85k
    maValueMap [ rKey ] = rValue;
165
7.85k
}
166
167
0
JobSetup& JobSetup::operator=( const JobSetup& ) = default;
168
169
0
JobSetup& JobSetup::operator=( JobSetup&& ) = default;
170
171
bool ImplJobSetup::operator==( const ImplJobSetup& rImplJobSetup ) const
172
0
{
173
0
    return mnSystem          == rImplJobSetup.mnSystem        &&
174
0
         maPrinterName     == rImplJobSetup.maPrinterName   &&
175
0
         maDriver          == rImplJobSetup.maDriver        &&
176
0
         meOrientation     == rImplJobSetup.meOrientation   &&
177
0
         meDuplexMode      == rImplJobSetup.meDuplexMode    &&
178
0
         mnPaperBin        == rImplJobSetup.mnPaperBin      &&
179
0
         mePaperFormat     == rImplJobSetup.mePaperFormat   &&
180
0
         mnPaperWidth      == rImplJobSetup.mnPaperWidth    &&
181
0
         mnPaperHeight     == rImplJobSetup.mnPaperHeight   &&
182
0
         mbPapersizeFromSetup == rImplJobSetup.mbPapersizeFromSetup &&
183
0
         mnDriverDataLen   == rImplJobSetup.mnDriverDataLen &&
184
0
         maValueMap        == rImplJobSetup.maValueMap      &&
185
0
         memcmp( mpDriverData.get(),
186
0
                 rImplJobSetup.mpDriverData.get(),
187
0
                 std::min(mnDriverDataLen, rImplJobSetup.mnDriverDataLen)) == 0;
188
0
}
189
190
namespace
191
{
192
    JobSetup::ImplType& GetGlobalDefault()
193
28.5k
    {
194
28.5k
        static JobSetup::ImplType gDefault;
195
28.5k
        return gDefault;
196
28.5k
    }
197
}
198
199
28.4k
JobSetup::JobSetup() : mpData(GetGlobalDefault())
200
28.4k
{
201
28.4k
}
202
203
0
JobSetup::JobSetup( const JobSetup& ) = default;
204
205
28.4k
JobSetup::~JobSetup() = default;
206
207
bool JobSetup::operator==( const JobSetup& rJobSetup ) const
208
0
{
209
0
    return mpData == rJobSetup.mpData;
210
0
}
211
212
const ImplJobSetup& JobSetup::ImplGetConstData() const
213
1.66k
{
214
1.66k
    return *mpData;
215
1.66k
}
216
217
ImplJobSetup& JobSetup::ImplGetData()
218
703
{
219
703
    return *mpData;
220
703
}
221
222
OUString const & JobSetup::GetPrinterName() const
223
3.18k
{
224
3.18k
    return mpData->GetPrinterName();
225
3.18k
}
226
227
bool JobSetup::IsDefault() const
228
69
{
229
69
    return mpData.same_object(GetGlobalDefault());
230
69
}
231
232
SvStream& ReadJobSetup( SvStream& rIStream, JobSetup& rJobSetup )
233
1.59k
{
234
1.59k
    {
235
1.59k
        sal_uInt16 nLen = 0;
236
1.59k
        rIStream.ReadUInt16( nLen );
237
1.59k
        if (nLen <= 4)
238
0
            return rIStream;
239
240
1.59k
        sal_uInt16 nSystem = 0;
241
1.59k
        rIStream.ReadUInt16( nSystem );
242
1.59k
        size_t nRead = nLen - sizeof(nLen) - sizeof(nSystem);
243
1.59k
        if (nRead > rIStream.remainingSize())
244
888
        {
245
888
            SAL_WARN("vcl", "Parsing error: " << rIStream.remainingSize() <<
246
888
                     " max possible entries, but " << nRead << " claimed, truncating");
247
888
            return rIStream;
248
888
        }
249
704
        sal_uInt64 const nFirstPos = rIStream.Tell();
250
704
        std::unique_ptr<char[]> pTempBuf(new char[nRead]);
251
704
        nRead = rIStream.ReadBytes(pTempBuf.get(), nRead);
252
704
        if (nRead >= sizeof(ImplOldJobSetupData))
253
703
        {
254
703
            ImplOldJobSetupData* pData = reinterpret_cast<ImplOldJobSetupData*>(pTempBuf.get());
255
256
703
            rtl_TextEncoding aStreamEncoding = RTL_TEXTENCODING_UTF8;
257
703
            if( nSystem == JOBSET_FILE364_SYSTEM )
258
0
                aStreamEncoding = rIStream.GetStreamEncoding();
259
260
703
            ImplJobSetup& rJobData = rJobSetup.ImplGetData();
261
262
            // use (potentially truncated) printer/driver name from ImplOldJobSetupData as fallback,
263
            // gets overwritten below if PRINTER_NAME/DRIVER_NAME keys are set
264
703
            pData->cPrinterName[std::size(pData->cPrinterName) - 1] = 0;
265
703
            rJobData.SetPrinterName( OStringToOUString(pData->cPrinterName, aStreamEncoding) );
266
703
            pData->cDriverName[std::size(pData->cDriverName) - 1] = 0;
267
703
            rJobData.SetDriver( OStringToOUString(pData->cDriverName, aStreamEncoding) );
268
269
            // Are these our new JobSetup files?
270
703
            if ( nSystem == JOBSET_FILE364_SYSTEM ||
271
703
                 nSystem == JOBSET_FILE605_SYSTEM )
272
685
            {
273
685
                if (nRead < sizeof(ImplOldJobSetupData) + sizeof(Impl364JobSetupData))
274
0
                {
275
0
                    SAL_WARN("vcl", "Parsing error: " << sizeof(ImplOldJobSetupData) + sizeof(Impl364JobSetupData) <<
276
0
                             " required, but " << nRead << " available");
277
0
                    return rIStream;
278
0
                }
279
280
685
                Impl364JobSetupData* pOldJobData    = reinterpret_cast<Impl364JobSetupData*>(pTempBuf.get() + sizeof( ImplOldJobSetupData ));
281
685
                sal_uInt16 nOldJobDataSize          = SVBT16ToUInt16( pOldJobData->nSize );
282
685
                rJobData.SetSystem( SVBT16ToUInt16( pOldJobData->nSystem ) );
283
685
                const sal_uInt32 nDriverDataLen = SVBT32ToUInt32( pOldJobData->nDriverDataLen );
284
685
                rJobData.SetOrientation( static_cast<Orientation>(SVBT16ToUInt16( pOldJobData->nOrientation )) );
285
685
                rJobData.SetDuplexMode( DuplexMode::Unknown );
286
685
                rJobData.SetPaperBin( SVBT16ToUInt16( pOldJobData->nPaperBin ) );
287
685
                sal_uInt16 nPaperFormat = SVBT16ToUInt16(pOldJobData->nPaperFormat);
288
685
                if (nPaperFormat < NUM_PAPER_ENTRIES)
289
359
                    rJobData.SetPaperFormat(static_cast<Paper>(nPaperFormat));
290
326
                else
291
326
                {
292
326
                    SAL_WARN("vcl", "Parsing error: " << nPaperFormat <<
293
326
                             " paper format, but legal max is " << NUM_PAPER_ENTRIES);
294
326
                }
295
685
                rJobData.SetPaperWidth( static_cast<tools::Long>(SVBT32ToUInt32( pOldJobData->nPaperWidth )) );
296
685
                rJobData.SetPaperHeight( static_cast<tools::Long>(SVBT32ToUInt32( pOldJobData->nPaperHeight )) );
297
685
                if ( nDriverDataLen )
298
586
                {
299
586
                    const char* pDriverData = reinterpret_cast<const char*>(pOldJobData) + nOldJobDataSize;
300
586
                    const char* pDriverDataEnd = pDriverData + nDriverDataLen;
301
586
                    if (pDriverDataEnd > pTempBuf.get() + nRead)
302
350
                    {
303
350
                        SAL_WARN("vcl", "corrupted job setup");
304
350
                    }
305
236
                    else
306
236
                    {
307
236
                        auto pNewDriverData = std::make_unique<sal_uInt8[]>( nDriverDataLen );
308
236
                        memcpy( pNewDriverData.get(), pDriverData, nDriverDataLen );
309
236
                        rJobData.SetDriverData( std::move(pNewDriverData), nDriverDataLen );
310
236
                    }
311
586
                }
312
685
                if( nSystem == JOBSET_FILE605_SYSTEM )
313
685
                {
314
685
                    rIStream.Seek( nFirstPos + sizeof( ImplOldJobSetupData ) +
315
685
                        sizeof( Impl364JobSetupData ) + rJobData.GetDriverDataLen() );
316
8.72k
                    while( rIStream.Tell() < nFirstPos + nRead )
317
8.04k
                    {
318
8.04k
                        OUString aKey = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIStream, RTL_TEXTENCODING_UTF8);
319
8.04k
                        OUString aValue = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIStream, RTL_TEXTENCODING_UTF8);
320
8.04k
                        if( aKey == "COMPAT_DUPLEX_MODE" )
321
189
                        {
322
189
                            if( aValue == "DuplexMode::Unknown" )
323
0
                                rJobData.SetDuplexMode( DuplexMode::Unknown );
324
189
                            else if( aValue == "DuplexMode::Off" )
325
0
                                rJobData.SetDuplexMode( DuplexMode::Off );
326
189
                            else if( aValue == "DuplexMode::ShortEdge" )
327
0
                                rJobData.SetDuplexMode( DuplexMode::ShortEdge );
328
189
                            else if( aValue == "DuplexMode::LongEdge" )
329
0
                                rJobData.SetDuplexMode( DuplexMode::LongEdge );
330
189
                        }
331
7.85k
                        else if (aKey == u"PRINTER_NAME")
332
0
                            rJobData.SetPrinterName(aValue);
333
7.85k
                        else if (aKey == u"DRIVER_NAME")
334
0
                            rJobData.SetDriver(aValue);
335
7.85k
                        else
336
7.85k
                            rJobData.SetValueMap(aKey, aValue);
337
8.04k
                    }
338
685
                    SAL_WARN_IF( rIStream.Tell() != nFirstPos+nRead, "vcl", "corrupted job setup" );
339
                    // ensure correct stream position
340
685
                    rIStream.Seek(nFirstPos + nRead);
341
685
                }
342
685
            }
343
703
        }
344
704
    }
345
346
704
    return rIStream;
347
704
}
348
349
SvStream& WriteJobSetup( SvStream& rOStream, const JobSetup& rJobSetup )
350
69
{
351
69
    {
352
69
        sal_uInt16 nLen = 0;
353
69
        if ( rJobSetup.IsDefault() )
354
69
            rOStream.WriteUInt16( nLen );
355
0
        else
356
0
        {
357
0
            const ImplJobSetup& rJobData = rJobSetup.ImplGetConstData();
358
0
            Impl364JobSetupData aOldJobData;
359
0
            sal_uInt16 nOldJobDataSize = sizeof( aOldJobData );
360
0
            ShortToSVBT16( nOldJobDataSize, aOldJobData.nSize );
361
0
            ShortToSVBT16( rJobData.GetSystem(), aOldJobData.nSystem );
362
0
            UInt32ToSVBT32( rJobData.GetDriverDataLen(), aOldJobData.nDriverDataLen );
363
0
            ShortToSVBT16( static_cast<sal_uInt16>(rJobData.GetOrientation()), aOldJobData.nOrientation );
364
0
            ShortToSVBT16( rJobData.GetPaperBin(), aOldJobData.nPaperBin );
365
0
            ShortToSVBT16( static_cast<sal_uInt16>(rJobData.GetPaperFormat()), aOldJobData.nPaperFormat );
366
0
            UInt32ToSVBT32( static_cast<sal_uInt32>(rJobData.GetPaperWidth()), aOldJobData.nPaperWidth );
367
0
            UInt32ToSVBT32( static_cast<sal_uInt32>(rJobData.GetPaperHeight()), aOldJobData.nPaperHeight );
368
369
0
            ImplOldJobSetupData aOldData = {};
370
0
            OString aPrnByteName(OUStringToOString(rJobData.GetPrinterName(), RTL_TEXTENCODING_UTF8));
371
0
            strncpy(aOldData.cPrinterName, aPrnByteName.getStr(), std::size(aOldData.cPrinterName) - 1);
372
0
            OString aDriverByteName(OUStringToOString(rJobData.GetDriver(), RTL_TEXTENCODING_UTF8));
373
0
            strncpy(aOldData.cDriverName, aDriverByteName.getStr(), std::size(aOldData.cDriverName) - 1);
374
0
            int nPos = rOStream.Tell();
375
0
            rOStream.WriteUInt16( 0 );
376
0
            rOStream.WriteUInt16( JOBSET_FILE605_SYSTEM );
377
0
            rOStream.WriteBytes( &aOldData, sizeof( aOldData ) );
378
0
            rOStream.WriteBytes( &aOldJobData, nOldJobDataSize );
379
0
            rOStream.WriteBytes( rJobData.GetDriverData(), rJobData.GetDriverDataLen() );
380
381
0
            const std::unordered_map< OUString, OUString >& rValueMap(
382
0
                rJobData.GetValueMap());
383
384
0
            for (auto const& value : rValueMap)
385
0
            {
386
0
                write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream, value.first, RTL_TEXTENCODING_UTF8);
387
0
                write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream, value.second, RTL_TEXTENCODING_UTF8);
388
0
            }
389
0
            write_uInt16_lenPrefixed_uInt8s_FromOString(rOStream, "COMPAT_DUPLEX_MODE");
390
0
            switch( rJobData.GetDuplexMode() )
391
0
            {
392
0
                case DuplexMode::Unknown:
393
0
                    write_uInt16_lenPrefixed_uInt8s_FromOString(rOStream, "DuplexMode::Unknown");
394
0
                    break;
395
0
                case DuplexMode::Off:
396
0
                    write_uInt16_lenPrefixed_uInt8s_FromOString(rOStream, "DuplexMode::Off");
397
0
                    break;
398
0
                case DuplexMode::ShortEdge:
399
0
                    write_uInt16_lenPrefixed_uInt8s_FromOString(rOStream, "DuplexMode::ShortEdge");
400
0
                    break;
401
0
                case DuplexMode::LongEdge:
402
0
                    write_uInt16_lenPrefixed_uInt8s_FromOString(rOStream, "DuplexMode::LongEdge");
403
0
                    break;
404
0
            }
405
            // write printer, driver name in full, the ones in aOldData may be truncated
406
0
            write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream, u"PRINTER_NAME", RTL_TEXTENCODING_UTF8);
407
0
            write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream, rJobData.GetPrinterName(), RTL_TEXTENCODING_UTF8);
408
0
            write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream, u"DRIVER_NAME", RTL_TEXTENCODING_UTF8);
409
0
            write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream, rJobData.GetDriver(), RTL_TEXTENCODING_UTF8);
410
411
0
            nLen = sal::static_int_cast<sal_uInt16>(rOStream.Tell() - nPos);
412
0
            rOStream.Seek( nPos );
413
0
            rOStream.WriteUInt16( nLen );
414
0
            rOStream.Seek( nPos + nLen );
415
0
        }
416
69
    }
417
418
69
    return rOStream;
419
69
}
420
421
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */