Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/oox/source/ole/axbinarywriter.cxx
Line
Count
Source (jump to first uncovered line)
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
#include <oox/ole/axbinarywriter.hxx>
10
11
namespace oox::ole {
12
13
namespace {
14
15
const sal_uInt32 AX_STRING_COMPRESSED       = 0x80000000;
16
17
} // namespace
18
19
AxAlignedOutputStream::AxAlignedOutputStream( BinaryOutputStream& rOutStrm ) :
20
0
    BinaryStreamBase( false ),
21
0
    mpOutStrm( &rOutStrm ),
22
0
    mnStrmPos( 0 ),
23
0
    mnStrmSize( rOutStrm.getRemaining() ),
24
0
    mnWrappedBeginPos( rOutStrm.tell() )
25
0
{
26
0
    mbEof = mbEof || rOutStrm.isEof();
27
0
}
Unexecuted instantiation: oox::ole::AxAlignedOutputStream::AxAlignedOutputStream(oox::BinaryOutputStream&)
Unexecuted instantiation: oox::ole::AxAlignedOutputStream::AxAlignedOutputStream(oox::BinaryOutputStream&)
28
29
sal_Int64 AxAlignedOutputStream::size() const
30
0
{
31
0
    return mpOutStrm ? mnStrmSize : -1;
32
0
}
33
34
sal_Int64 AxAlignedOutputStream::tell() const
35
0
{
36
0
    return mpOutStrm ? mnStrmPos : -1;
37
0
}
38
39
void AxAlignedOutputStream::seek( sal_Int64 nPos )
40
0
{
41
0
    mbEof = (nPos < 0);
42
0
    if( !mbEof )
43
0
    {
44
0
        mpOutStrm->seek( static_cast< sal_Int32 >( mnWrappedBeginPos + nPos  ) );
45
0
        mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
46
0
    }
47
0
}
48
49
void AxAlignedOutputStream::close()
50
0
{
51
0
    mpOutStrm = nullptr;
52
0
    mbEof = true;
53
0
}
54
55
void AxAlignedOutputStream::writeData( const StreamDataSequence& orData, size_t nAtomSize )
56
0
{
57
0
    mpOutStrm->writeData( orData, nAtomSize );
58
0
    mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
59
0
}
60
61
void AxAlignedOutputStream::writeMemory( const void* opMem, sal_Int32 nBytes, size_t nAtomSize )
62
0
{
63
0
    mpOutStrm->writeMemory( opMem, nBytes, nAtomSize );
64
0
    mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
65
0
}
66
67
void AxAlignedOutputStream::pad( sal_Int32 nBytes )
68
0
{
69
   //PRESUMABLY we need to pad with 0's here as appropriate
70
0
   css::uno::Sequence< sal_Int8 > aData( nBytes );
71
   // ok we could be padding with rubbish here, but really that shouldn't matter
72
   // set to 0(s), easier to not get fooled by 0's when looking at
73
   // binary content...
74
0
   memset( static_cast<void*>( aData.getArray() ), 0, nBytes );
75
0
   mpOutStrm->writeData( aData );
76
0
   mnStrmPos = mpOutStrm->tell() - mnWrappedBeginPos;
77
0
}
78
79
void AxAlignedOutputStream::align( size_t nSize )
80
0
{
81
0
    pad( static_cast< sal_Int32 >( (nSize - (mnStrmPos % nSize)) % nSize ) );
82
0
}
83
84
namespace {
85
86
void lclWriteString( AxAlignedOutputStream& rOutStrm, OUString const & rValue, sal_uInt32 nSize )
87
0
{
88
0
    bool bCompressed = getFlag( nSize, AX_STRING_COMPRESSED );
89
0
    rOutStrm.writeCompressedUnicodeArray( rValue, bCompressed );
90
0
}
91
92
} // namespace
93
94
AxBinaryPropertyWriter::ComplexProperty::~ComplexProperty()
95
0
{
96
0
}
97
98
bool AxBinaryPropertyWriter::PairProperty::writeProperty( AxAlignedOutputStream& rOutStrm )
99
0
{
100
0
    rOutStrm.WriteInt32(mrPairData.first).WriteInt32(mrPairData.second);
101
0
    return true;
102
0
}
103
104
bool AxBinaryPropertyWriter::StringProperty::writeProperty( AxAlignedOutputStream& rOutStrm )
105
0
{
106
0
    lclWriteString( rOutStrm, mrValue, mnSize );
107
0
    return true;
108
0
}
109
110
AxBinaryPropertyWriter::AxBinaryPropertyWriter( BinaryOutputStream& rOutStrm, bool b64BitPropFlags ) :
111
0
    maOutStrm( rOutStrm ),
112
0
    mnPropFlags( 0x0 ),
113
0
    mbValid( true ),
114
0
    mb64BitPropFlags( b64BitPropFlags )
115
0
{
116
0
    sal_uInt16 nId( 0x0200 );
117
0
    maOutStrm.WriteUInt16(nId);
118
0
    mnBlockSize = 0; // will be filled in the finalize method
119
120
0
    maOutStrm.WriteUInt16(nId);
121
0
    mnPropFlagsStart = maOutStrm.tell();
122
123
0
    if( mb64BitPropFlags )
124
0
        maOutStrm.WriteInt64( mnPropFlags );
125
0
    else
126
0
        maOutStrm.WriteUInt32( mnPropFlags );
127
0
    mnNextProp = 1;
128
0
}
129
130
void AxBinaryPropertyWriter::writeBoolProperty( bool orbValue )
131
0
{
132
    // orbValue == bReverse false then we want to set the bit, e.g. don't skip
133
0
    startNextProperty( !orbValue );
134
0
}
135
136
void AxBinaryPropertyWriter::writePairProperty( AxPairData& orPairData )
137
0
{
138
0
    startNextProperty();
139
0
    maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<PairProperty>( orPairData ) ) );
140
0
}
141
142
void AxBinaryPropertyWriter::writeStringProperty( OUString& orValue )
143
0
{
144
0
    sal_uInt32 nSize = orValue.getLength() * 2;
145
0
    setFlag(  nSize, AX_STRING_COMPRESSED, false );
146
0
    maOutStrm.writeAligned< sal_uInt32 >( nSize );
147
0
    maLargeProps.push_back( ComplexPropVector::value_type( std::make_shared<StringProperty>( orValue, nSize ) ) );
148
0
    startNextProperty();
149
0
}
150
151
void AxBinaryPropertyWriter::finalizeExport()
152
0
{
153
    // write large properties
154
0
    maOutStrm.align( 4 );
155
0
    for (auto const& largeProp : maLargeProps)
156
0
    {
157
0
        if (!ensureValid())
158
0
            break;
159
0
        largeProp->writeProperty( maOutStrm );
160
0
        maOutStrm.align( 4 );
161
0
    }
162
163
0
    mnBlockSize = maOutStrm.tell() - mnPropFlagsStart;
164
165
    // write stream properties (no stream alignment between properties!)
166
0
    for (auto const& streamProp : maStreamProps)
167
0
    {
168
0
        if (!ensureValid())
169
0
            break;
170
0
        streamProp->writeProperty( maOutStrm );
171
0
    }
172
173
0
    sal_Int64 nPos = maOutStrm.tell();
174
0
    maOutStrm.seek( mnPropFlagsStart - sizeof( mnBlockSize ) );
175
176
0
    maOutStrm.WriteInt16( mnBlockSize );
177
178
0
    if( mb64BitPropFlags )
179
0
        maOutStrm.WriteInt64( mnPropFlags );
180
0
    else
181
0
        maOutStrm.WriteUInt32( mnPropFlags );
182
183
0
    maOutStrm.seek( nPos );
184
0
}
185
186
bool AxBinaryPropertyWriter::ensureValid()
187
0
{
188
0
    mbValid = mbValid && !maOutStrm.isEof();
189
0
    return mbValid;
190
0
}
191
192
void AxBinaryPropertyWriter::startNextProperty( bool bSkip )
193
0
{
194
    // if we are skipping then we clear the flag
195
0
    setFlag( mnPropFlags, mnNextProp, !bSkip );
196
0
    mnNextProp <<= 1;
197
0
}
198
199
} // namespace oox::ole
200
201
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */