1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
28 #define JOBSET_FILE364_SYSTEM (sal_uInt16(0xFFFF))
29 #define JOBSET_FILE605_SYSTEM (sal_uInt16(0xFFFE))
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
38 char cPrinterName
[64];
44 struct Impl364JobSetupData
48 SVBT32 nDriverDataLen
;
58 ImplJobSetup::ImplJobSetup()
61 meOrientation
= Orientation::Portrait
;
62 meDuplexMode
= DuplexMode::Unknown
;
64 mePaperFormat
= PAPER_USER
;
68 mbPapersizeFromSetup
= false;
69 meSetupMode
= PrinterSetupMode::DocumentGlobal
;
72 ImplJobSetup::ImplJobSetup( const ImplJobSetup
& rJobSetup
) :
73 mnSystem( rJobSetup
.GetSystem() ),
74 maPrinterName( rJobSetup
.GetPrinterName() ),
75 maDriver( rJobSetup
.GetDriver() ),
76 meOrientation( rJobSetup
.GetOrientation() ),
77 meDuplexMode( rJobSetup
.GetDuplexMode() ),
78 mnPaperBin( rJobSetup
.GetPaperBin() ),
79 mePaperFormat( rJobSetup
.GetPaperFormat() ),
80 mnPaperWidth( rJobSetup
.GetPaperWidth() ),
81 mnPaperHeight( rJobSetup
.GetPaperHeight() ),
82 mnDriverDataLen( rJobSetup
.GetDriverDataLen() ),
84 mbPapersizeFromSetup( rJobSetup
.GetPapersizeFromSetup() ),
85 meSetupMode( rJobSetup
.GetPrinterSetupMode() ),
86 maValueMap( rJobSetup
.GetValueMap() )
88 if ( rJobSetup
.GetDriverData() )
90 mpDriverData
.reset( new sal_uInt8
[mnDriverDataLen
] );
91 memcpy( mpDriverData
.get(), rJobSetup
.GetDriverData(), mnDriverDataLen
);
94 mpDriverData
= nullptr;
97 ImplJobSetup::~ImplJobSetup()
101 void ImplJobSetup::SetSystem(sal_uInt16 nSystem
)
106 void ImplJobSetup::SetPrinterName(const OUString
& rPrinterName
)
108 maPrinterName
= rPrinterName
;
111 void ImplJobSetup::SetDriver(const OUString
& rDriver
)
116 void ImplJobSetup::SetOrientation(Orientation eOrientation
)
118 meOrientation
= eOrientation
;
121 void ImplJobSetup::SetDuplexMode(DuplexMode eDuplexMode
)
123 meDuplexMode
= eDuplexMode
;
126 void ImplJobSetup::SetPaperBin(sal_uInt16 nPaperBin
)
128 mnPaperBin
= nPaperBin
;
131 void ImplJobSetup::SetPaperFormat(Paper ePaperFormat
)
133 mePaperFormat
= ePaperFormat
;
136 void ImplJobSetup::SetPaperWidth(tools::Long nPaperWidth
)
138 mnPaperWidth
= nPaperWidth
;
141 void ImplJobSetup::SetPaperHeight(tools::Long nPaperHeight
)
143 mnPaperHeight
= nPaperHeight
;
146 void ImplJobSetup::SetDriverData(std::unique_ptr
<sal_uInt8
[]> pDriverData
, sal_uInt32 nDriverDataLen
)
148 mpDriverData
= std::move(pDriverData
);
149 mnDriverDataLen
= nDriverDataLen
;
152 void ImplJobSetup::SetPapersizeFromSetup(bool bPapersizeFromSetup
)
154 mbPapersizeFromSetup
= bPapersizeFromSetup
;
157 void ImplJobSetup::SetPrinterSetupMode(PrinterSetupMode eMode
)
162 void ImplJobSetup::SetValueMap( const OUString
& rKey
, const OUString
& rValue
)
164 maValueMap
[ rKey
] = rValue
;
167 JobSetup
& JobSetup::operator=( const JobSetup
& ) = default;
169 JobSetup
& JobSetup::operator=( JobSetup
&& ) = default;
171 bool ImplJobSetup::operator==( const ImplJobSetup
& rImplJobSetup
) const
173 return mnSystem
== rImplJobSetup
.mnSystem
&&
174 maPrinterName
== rImplJobSetup
.maPrinterName
&&
175 maDriver
== rImplJobSetup
.maDriver
&&
176 meOrientation
== rImplJobSetup
.meOrientation
&&
177 meDuplexMode
== rImplJobSetup
.meDuplexMode
&&
178 mnPaperBin
== rImplJobSetup
.mnPaperBin
&&
179 mePaperFormat
== rImplJobSetup
.mePaperFormat
&&
180 mnPaperWidth
== rImplJobSetup
.mnPaperWidth
&&
181 mnPaperHeight
== rImplJobSetup
.mnPaperHeight
&&
182 mbPapersizeFromSetup
== rImplJobSetup
.mbPapersizeFromSetup
&&
183 mnDriverDataLen
== rImplJobSetup
.mnDriverDataLen
&&
184 maValueMap
== rImplJobSetup
.maValueMap
&&
185 memcmp( mpDriverData
.get(),
186 rImplJobSetup
.mpDriverData
.get(),
187 std::min(mnDriverDataLen
, rImplJobSetup
.mnDriverDataLen
)) == 0;
192 JobSetup::ImplType
& GetGlobalDefault()
194 static JobSetup::ImplType gDefault
;
199 JobSetup::JobSetup() : mpData(GetGlobalDefault())
203 JobSetup::JobSetup( const JobSetup
& ) = default;
205 JobSetup::~JobSetup() = default;
207 bool JobSetup::operator==( const JobSetup
& rJobSetup
) const
209 return mpData
== rJobSetup
.mpData
;
212 const ImplJobSetup
& JobSetup::ImplGetConstData() const
217 ImplJobSetup
& JobSetup::ImplGetData()
222 OUString
const & JobSetup::GetPrinterName() const
224 return mpData
->GetPrinterName();
227 bool JobSetup::IsDefault() const
229 return mpData
.same_object(GetGlobalDefault());
232 SvStream
& ReadJobSetup( SvStream
& rIStream
, JobSetup
& rJobSetup
)
236 rIStream
.ReadUInt16( nLen
);
240 sal_uInt16 nSystem
= 0;
241 rIStream
.ReadUInt16( nSystem
);
242 size_t nRead
= nLen
- sizeof(nLen
) - sizeof(nSystem
);
243 if (nRead
> rIStream
.remainingSize())
245 SAL_WARN("vcl", "Parsing error: " << rIStream
.remainingSize() <<
246 " max possible entries, but " << nRead
<< " claimed, truncating");
249 sal_uInt64
const nFirstPos
= rIStream
.Tell();
250 std::unique_ptr
<char[]> pTempBuf(new char[nRead
]);
251 nRead
= rIStream
.ReadBytes(pTempBuf
.get(), nRead
);
252 if (nRead
>= sizeof(ImplOldJobSetupData
))
254 ImplOldJobSetupData
* pData
= reinterpret_cast<ImplOldJobSetupData
*>(pTempBuf
.get());
256 rtl_TextEncoding aStreamEncoding
= RTL_TEXTENCODING_UTF8
;
257 if( nSystem
== JOBSET_FILE364_SYSTEM
)
258 aStreamEncoding
= rIStream
.GetStreamCharSet();
260 ImplJobSetup
& rJobData
= rJobSetup
.ImplGetData();
262 // use (potentially truncated) printer/driver name from ImplOldJobSetupData as fallback,
263 // gets overwritten below if PRINTER_NAME/DRIVER_NAME keys are set
264 pData
->cPrinterName
[std::size(pData
->cPrinterName
) - 1] = 0;
265 rJobData
.SetPrinterName( OStringToOUString(pData
->cPrinterName
, aStreamEncoding
) );
266 pData
->cDriverName
[std::size(pData
->cDriverName
) - 1] = 0;
267 rJobData
.SetDriver( OStringToOUString(pData
->cDriverName
, aStreamEncoding
) );
269 // Are these our new JobSetup files?
270 if ( nSystem
== JOBSET_FILE364_SYSTEM
||
271 nSystem
== JOBSET_FILE605_SYSTEM
)
273 if (nRead
< sizeof(ImplOldJobSetupData
) + sizeof(Impl364JobSetupData
))
275 SAL_WARN("vcl", "Parsing error: " << sizeof(ImplOldJobSetupData
) + sizeof(Impl364JobSetupData
) <<
276 " required, but " << nRead
<< " available");
280 Impl364JobSetupData
* pOldJobData
= reinterpret_cast<Impl364JobSetupData
*>(pTempBuf
.get() + sizeof( ImplOldJobSetupData
));
281 sal_uInt16 nOldJobDataSize
= SVBT16ToUInt16( pOldJobData
->nSize
);
282 rJobData
.SetSystem( SVBT16ToUInt16( pOldJobData
->nSystem
) );
283 const sal_uInt32 nDriverDataLen
= SVBT32ToUInt32( pOldJobData
->nDriverDataLen
);
284 rJobData
.SetOrientation( static_cast<Orientation
>(SVBT16ToUInt16( pOldJobData
->nOrientation
)) );
285 rJobData
.SetDuplexMode( DuplexMode::Unknown
);
286 rJobData
.SetPaperBin( SVBT16ToUInt16( pOldJobData
->nPaperBin
) );
287 sal_uInt16 nPaperFormat
= SVBT16ToUInt16(pOldJobData
->nPaperFormat
);
288 if (nPaperFormat
< NUM_PAPER_ENTRIES
)
289 rJobData
.SetPaperFormat(static_cast<Paper
>(nPaperFormat
));
292 SAL_WARN("vcl", "Parsing error: " << nPaperFormat
<<
293 " paper format, but legal max is " << NUM_PAPER_ENTRIES
);
295 rJobData
.SetPaperWidth( static_cast<tools::Long
>(SVBT32ToUInt32( pOldJobData
->nPaperWidth
)) );
296 rJobData
.SetPaperHeight( static_cast<tools::Long
>(SVBT32ToUInt32( pOldJobData
->nPaperHeight
)) );
297 if ( nDriverDataLen
)
299 const char* pDriverData
= reinterpret_cast<const char*>(pOldJobData
) + nOldJobDataSize
;
300 const char* pDriverDataEnd
= pDriverData
+ nDriverDataLen
;
301 if (pDriverDataEnd
> pTempBuf
.get() + nRead
)
303 SAL_WARN("vcl", "corrupted job setup");
307 auto pNewDriverData
= std::make_unique
<sal_uInt8
[]>( nDriverDataLen
);
308 memcpy( pNewDriverData
.get(), pDriverData
, nDriverDataLen
);
309 rJobData
.SetDriverData( std::move(pNewDriverData
), nDriverDataLen
);
312 if( nSystem
== JOBSET_FILE605_SYSTEM
)
314 rIStream
.Seek( nFirstPos
+ sizeof( ImplOldJobSetupData
) +
315 sizeof( Impl364JobSetupData
) + rJobData
.GetDriverDataLen() );
316 while( rIStream
.Tell() < nFirstPos
+ nRead
)
318 OUString aKey
= read_uInt16_lenPrefixed_uInt8s_ToOUString(rIStream
, RTL_TEXTENCODING_UTF8
);
319 OUString aValue
= read_uInt16_lenPrefixed_uInt8s_ToOUString(rIStream
, RTL_TEXTENCODING_UTF8
);
320 if( aKey
== "COMPAT_DUPLEX_MODE" )
322 if( aValue
== "DuplexMode::Unknown" )
323 rJobData
.SetDuplexMode( DuplexMode::Unknown
);
324 else if( aValue
== "DuplexMode::Off" )
325 rJobData
.SetDuplexMode( DuplexMode::Off
);
326 else if( aValue
== "DuplexMode::ShortEdge" )
327 rJobData
.SetDuplexMode( DuplexMode::ShortEdge
);
328 else if( aValue
== "DuplexMode::LongEdge" )
329 rJobData
.SetDuplexMode( DuplexMode::LongEdge
);
331 else if (aKey
== u
"PRINTER_NAME")
332 rJobData
.SetPrinterName(aValue
);
333 else if (aKey
== u
"DRIVER_NAME")
334 rJobData
.SetDriver(aValue
);
336 rJobData
.SetValueMap(aKey
, aValue
);
338 SAL_WARN_IF( rIStream
.Tell() != nFirstPos
+nRead
, "vcl", "corrupted job setup" );
339 // ensure correct stream position
340 rIStream
.Seek(nFirstPos
+ nRead
);
349 SvStream
& WriteJobSetup( SvStream
& rOStream
, const JobSetup
& rJobSetup
)
353 if ( rJobSetup
.IsDefault() )
354 rOStream
.WriteUInt16( nLen
);
357 const ImplJobSetup
& rJobData
= rJobSetup
.ImplGetConstData();
358 Impl364JobSetupData aOldJobData
;
359 sal_uInt16 nOldJobDataSize
= sizeof( aOldJobData
);
360 ShortToSVBT16( nOldJobDataSize
, aOldJobData
.nSize
);
361 ShortToSVBT16( rJobData
.GetSystem(), aOldJobData
.nSystem
);
362 UInt32ToSVBT32( rJobData
.GetDriverDataLen(), aOldJobData
.nDriverDataLen
);
363 ShortToSVBT16( static_cast<sal_uInt16
>(rJobData
.GetOrientation()), aOldJobData
.nOrientation
);
364 ShortToSVBT16( rJobData
.GetPaperBin(), aOldJobData
.nPaperBin
);
365 ShortToSVBT16( static_cast<sal_uInt16
>(rJobData
.GetPaperFormat()), aOldJobData
.nPaperFormat
);
366 UInt32ToSVBT32( static_cast<sal_uInt32
>(rJobData
.GetPaperWidth()), aOldJobData
.nPaperWidth
);
367 UInt32ToSVBT32( static_cast<sal_uInt32
>(rJobData
.GetPaperHeight()), aOldJobData
.nPaperHeight
);
369 ImplOldJobSetupData aOldData
= {};
370 OString
aPrnByteName(OUStringToOString(rJobData
.GetPrinterName(), RTL_TEXTENCODING_UTF8
));
371 strncpy(aOldData
.cPrinterName
, aPrnByteName
.getStr(), std::size(aOldData
.cPrinterName
) - 1);
372 OString
aDriverByteName(OUStringToOString(rJobData
.GetDriver(), RTL_TEXTENCODING_UTF8
));
373 strncpy(aOldData
.cDriverName
, aDriverByteName
.getStr(), std::size(aOldData
.cDriverName
) - 1);
374 int nPos
= rOStream
.Tell();
375 rOStream
.WriteUInt16( 0 );
376 rOStream
.WriteUInt16( JOBSET_FILE605_SYSTEM
);
377 rOStream
.WriteBytes( &aOldData
, sizeof( aOldData
) );
378 rOStream
.WriteBytes( &aOldJobData
, nOldJobDataSize
);
379 rOStream
.WriteBytes( rJobData
.GetDriverData(), rJobData
.GetDriverDataLen() );
381 const std::unordered_map
< OUString
, OUString
>& rValueMap(
382 rJobData
.GetValueMap());
384 for (auto const& value
: rValueMap
)
386 write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream
, value
.first
, RTL_TEXTENCODING_UTF8
);
387 write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream
, value
.second
, RTL_TEXTENCODING_UTF8
);
389 write_uInt16_lenPrefixed_uInt8s_FromOString(rOStream
, "COMPAT_DUPLEX_MODE");
390 switch( rJobData
.GetDuplexMode() )
392 case DuplexMode::Unknown
:
393 write_uInt16_lenPrefixed_uInt8s_FromOString(rOStream
, "DuplexMode::Unknown");
395 case DuplexMode::Off
:
396 write_uInt16_lenPrefixed_uInt8s_FromOString(rOStream
, "DuplexMode::Off");
398 case DuplexMode::ShortEdge
:
399 write_uInt16_lenPrefixed_uInt8s_FromOString(rOStream
, "DuplexMode::ShortEdge");
401 case DuplexMode::LongEdge
:
402 write_uInt16_lenPrefixed_uInt8s_FromOString(rOStream
, "DuplexMode::LongEdge");
405 // write printer, driver name in full, the ones in aOldData may be truncated
406 write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream
, u
"PRINTER_NAME", RTL_TEXTENCODING_UTF8
);
407 write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream
, rJobData
.GetPrinterName(), RTL_TEXTENCODING_UTF8
);
408 write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream
, u
"DRIVER_NAME", RTL_TEXTENCODING_UTF8
);
409 write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream
, rJobData
.GetDriver(), RTL_TEXTENCODING_UTF8
);
411 nLen
= sal::static_int_cast
<sal_uInt16
>(rOStream
.Tell() - nPos
);
412 rOStream
.Seek( nPos
);
413 rOStream
.WriteUInt16( nLen
);
414 rOStream
.Seek( nPos
+ nLen
);
421 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */