Line data Source code
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 <algorithm>
21 :
22 : #include "rtl/string.h"
23 : #include "stgole.hxx"
24 : #include "sot/storinfo.hxx"
25 : #include <boost/scoped_array.hpp>
26 : #include <sot/exchange.hxx>
27 :
28 : #ifdef _MSC_VER
29 : #pragma warning(disable: 4342)
30 : #endif
31 : ///////////////////////// class StgInternalStream
32 :
33 130 : StgInternalStream::StgInternalStream( BaseStorage& rStg, const OUString& rName, bool bWr )
34 : {
35 130 : bIsWritable = true;
36 : StreamMode nMode = bWr
37 : ? StreamMode::WRITE | StreamMode::SHARE_DENYALL
38 130 : : StreamMode::READ | StreamMode::SHARE_DENYWRITE | StreamMode::NOCREATE;
39 130 : pStrm = rStg.OpenStream( rName, nMode );
40 :
41 : // set the error code right here in the stream
42 130 : SetError( rStg.GetError() );
43 130 : SetBufferSize( 1024 );
44 130 : }
45 :
46 260 : StgInternalStream::~StgInternalStream()
47 : {
48 130 : delete pStrm;
49 130 : }
50 :
51 0 : sal_uLong StgInternalStream::GetData( void* pData, sal_uLong nSize )
52 : {
53 0 : if( pStrm )
54 : {
55 0 : nSize = pStrm->Read( pData, nSize );
56 0 : SetError( pStrm->GetError() );
57 0 : return nSize;
58 : }
59 : else
60 0 : return 0;
61 : }
62 :
63 106 : sal_uLong StgInternalStream::PutData( const void* pData, sal_uLong nSize )
64 : {
65 106 : if( pStrm )
66 : {
67 106 : nSize = pStrm->Write( pData, nSize );
68 106 : SetError( pStrm->GetError() );
69 106 : return nSize;
70 : }
71 : else
72 0 : return 0;
73 : }
74 :
75 106 : sal_uInt64 StgInternalStream::SeekPos(sal_uInt64 const nPos)
76 : {
77 106 : return pStrm ? pStrm->Seek( nPos ) : 0;
78 : }
79 :
80 106 : void StgInternalStream::FlushData()
81 : {
82 106 : if( pStrm )
83 : {
84 106 : pStrm->Flush();
85 106 : SetError( pStrm->GetError() );
86 : }
87 106 : }
88 :
89 106 : void StgInternalStream::Commit()
90 : {
91 106 : Flush();
92 106 : pStrm->Commit();
93 106 : }
94 :
95 : ///////////////////////// class StgCompObjStream
96 :
97 77 : StgCompObjStream::StgCompObjStream( BaseStorage& rStg, bool bWr )
98 77 : : StgInternalStream( rStg, OUString("\1CompObj"), bWr )
99 : {
100 77 : memset( &aClsId, 0, sizeof( ClsId ) );
101 77 : nCbFormat = SotClipboardFormatId::NONE;
102 77 : }
103 :
104 24 : bool StgCompObjStream::Load()
105 : {
106 24 : memset( &aClsId, 0, sizeof( ClsId ) );
107 24 : nCbFormat = SotClipboardFormatId::NONE;
108 24 : aUserName.clear();
109 24 : if( GetError() != SVSTREAM_OK )
110 24 : return false;
111 0 : Seek( 8L ); // skip the first part
112 0 : sal_Int32 nMarker = 0;
113 0 : ReadInt32( nMarker );
114 0 : if( nMarker == -1L )
115 : {
116 0 : ReadClsId( *this, aClsId );
117 0 : sal_Int32 nLen1 = 0;
118 0 : ReadInt32( nLen1 );
119 0 : if ( nLen1 > 0 )
120 : {
121 : // higher bits are ignored
122 0 : sal_uLong nStrLen = ::std::min( nLen1, (sal_Int32)0xFFFE );
123 :
124 0 : boost::scoped_array<sal_Char> p(new sal_Char[ nStrLen+1 ]);
125 0 : p[nStrLen] = 0;
126 0 : if( Read( p.get(), nStrLen ) == nStrLen )
127 : {
128 : //The encoding here is "ANSI", which is pretty useless seeing as
129 : //the actual codepage used doesn't seem to be specified/stored
130 : //anywhere :-(. Might as well pick 1252 and be consistent on
131 : //all platforms and envs
132 : //https://bz.apache.org/ooo/attachment.cgi?id=68668
133 : //for a good edge-case example
134 0 : aUserName = nStrLen ? OUString( p.get(), nStrLen, RTL_TEXTENCODING_MS_1252 ) : OUString();
135 0 : nCbFormat = ReadClipboardFormat( *this );
136 : }
137 : else
138 0 : SetError( SVSTREAM_GENERALERROR );
139 : }
140 : }
141 0 : return GetError() == SVSTREAM_OK;
142 : }
143 :
144 53 : bool StgCompObjStream::Store()
145 : {
146 53 : if( GetError() != SVSTREAM_OK )
147 0 : return false;
148 53 : Seek( 0L );
149 53 : OString aAsciiUserName(OUStringToOString(aUserName, RTL_TEXTENCODING_MS_1252));
150 53 : WriteInt16( 1 ); // Version?
151 53 : WriteInt16( -2 ); // 0xFFFE = Byte Order Indicator
152 53 : WriteInt32( 0x0A03 ); // Windows 3.10
153 53 : WriteInt32( -1L );
154 53 : WriteClsId( *this, aClsId ); // Class ID
155 53 : WriteInt32( aAsciiUserName.getLength() + 1 );
156 53 : WriteCharPtr( aAsciiUserName.getStr() );
157 53 : WriteUChar( 0 ); // string terminator
158 53 : WriteClipboardFormat( *this, nCbFormat );
159 53 : WriteInt32( 0 ); // terminator
160 53 : Commit();
161 53 : return GetError() == SVSTREAM_OK;
162 : }
163 :
164 : /////////////////////////// class StgOleStream
165 :
166 53 : StgOleStream::StgOleStream( BaseStorage& rStg, bool bWr )
167 53 : : StgInternalStream( rStg, OUString("\1Ole"), bWr )
168 : {
169 53 : nFlags = 0;
170 53 : }
171 :
172 0 : bool StgOleStream::Load()
173 : {
174 0 : nFlags = 0;
175 0 : if( GetError() != SVSTREAM_OK )
176 0 : return false;
177 :
178 0 : sal_Int32 version = 0;
179 0 : Seek( 0L );
180 0 : ReadInt32( version ).ReadUInt32( nFlags );
181 0 : return GetError() == SVSTREAM_OK;
182 : }
183 :
184 53 : bool StgOleStream::Store()
185 : {
186 53 : if( GetError() != SVSTREAM_OK )
187 0 : return false;
188 :
189 53 : Seek( 0L );
190 53 : WriteInt32( 0x02000001 ); // OLE version, format
191 53 : WriteInt32( nFlags ); // Object flags
192 53 : WriteInt32( 0 ); // Update Options
193 53 : WriteInt32( 0 ); // reserved
194 53 : WriteInt32( 0 ); // Moniker 1
195 53 : Commit();
196 53 : return GetError() == SVSTREAM_OK;
197 : }
198 :
199 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|