tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / svl / source / misc / sharecontrolfile.cxx
blob92b8d04445dd0d468e5cc4ffeb8460b554e083e2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
22 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
23 #include <com/sun/star/ucb/XContent.hpp>
24 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
25 #include <com/sun/star/ucb/InteractiveIOException.hpp>
26 #include <com/sun/star/io/NotConnectedException.hpp>
28 #include <o3tl/enumrange.hxx>
30 #include <rtl/string.hxx>
31 #include <rtl/ustring.hxx>
32 #include <rtl/ustrbuf.hxx>
34 #include <comphelper/processfactory.hxx>
35 #include <ucbhelper/content.hxx>
37 #include <tools/stream.hxx>
38 #include <unotools/streamwrap.hxx>
40 #include <svl/sharecontrolfile.hxx>
42 using namespace ::com::sun::star;
44 namespace svt {
47 ShareControlFile::ShareControlFile( std::u16string_view aOrigURL )
48 : LockFileCommon(GenerateOwnLockFileURL(aOrigURL, u".~sharing."))
50 if ( !m_xStream.is() && !GetURL().isEmpty() )
52 uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
53 ::ucbhelper::Content aContent( GetURL(), xDummyEnv, comphelper::getProcessComponentContext() );
55 uno::Reference< ucb::XContentIdentifier > xContId( aContent.get().is() ? aContent.get()->getIdentifier() : nullptr );
56 if ( !xContId.is() || xContId->getContentProviderScheme() != "file" )
57 throw io::IOException(); // the implementation supports only local files for now
59 uno::Reference< io::XStream > xStream;
61 // Currently the locking of the original document is intended to be used.
62 // That means that the shared file should be accessed only when the original document is locked and only by user who has locked the document.
63 // TODO/LATER: should the own file locking be used?
65 try
67 xStream = aContent.openWriteableStreamNoLock();
69 catch ( ucb::InteractiveIOException const & e )
71 if ( e.Code == ucb::IOErrorCode_NOT_EXISTING )
73 // Create file...
74 ucb::InsertCommandArgument aInsertArg;
75 SvMemoryStream aStream(0,0);
76 aInsertArg.Data.set(new ::utl::OInputStreamWrapper(aStream));
77 aInsertArg.ReplaceExisting = false;
78 aContent.executeCommand( u"insert"_ustr, uno::Any( aInsertArg ) );
80 // try to let the file be hidden if possible
81 try {
82 aContent.setPropertyValue(u"IsHidden"_ustr, uno::Any( true ) );
83 } catch( uno::Exception& ) {}
85 // Try to open one more time
86 xStream = aContent.openWriteableStreamNoLock();
88 else
89 throw;
92 m_xSeekable.set( xStream, uno::UNO_QUERY_THROW );
93 m_xInputStream.set( xStream->getInputStream(), uno::UNO_SET_THROW );
94 m_xOutputStream.set( xStream->getOutputStream(), uno::UNO_SET_THROW );
95 m_xTruncate.set( m_xOutputStream, uno::UNO_QUERY_THROW );
96 m_xStream = std::move(xStream);
99 if ( !IsValid() )
100 throw io::NotConnectedException();
103 ShareControlFile::~ShareControlFile()
107 Close();
109 catch( uno::Exception& )
113 void ShareControlFile::Close()
115 // if it is called outside of destructor the mutex must be locked
117 if ( !m_xStream.is() )
118 return;
122 if ( m_xInputStream.is() )
123 m_xInputStream->closeInput();
124 if ( m_xOutputStream.is() )
125 m_xOutputStream->closeOutput();
127 catch( uno::Exception& )
130 m_xStream.clear();
131 m_xInputStream.clear();
132 m_xOutputStream.clear();
133 m_xSeekable.clear();
134 m_xTruncate.clear();
135 m_aUsersData.clear();
139 std::vector< o3tl::enumarray< LockFileComponent, OUString > > ShareControlFile::GetUsersData()
141 std::unique_lock aGuard(m_aMutex);
142 return GetUsersDataImpl(aGuard);
145 const std::vector< o3tl::enumarray< LockFileComponent, OUString > > & ShareControlFile::GetUsersDataImpl(std::unique_lock<std::mutex>& /*rGuard*/)
147 if ( !IsValid() )
148 throw io::NotConnectedException();
150 if ( m_aUsersData.empty() )
152 sal_Int64 nLength = m_xSeekable->getLength();
153 if (nLength > SAL_MAX_INT32 || nLength < 0)
154 throw uno::RuntimeException();
156 uno::Sequence< sal_Int8 > aBuffer( static_cast<sal_Int32>(nLength) );
157 m_xSeekable->seek( 0 );
159 sal_Int32 nRead = m_xInputStream->readBytes( aBuffer, static_cast<sal_Int32>(nLength) );
160 auto aBufferRange = asNonConstRange(aBuffer);
161 nLength -= nRead;
162 while ( nLength > 0 )
164 uno::Sequence< sal_Int8 > aTmpBuf( static_cast<sal_Int32>(nLength) );
165 nRead = m_xInputStream->readBytes( aTmpBuf, static_cast<sal_Int32>(nLength) );
166 if ( nRead > nLength )
167 throw uno::RuntimeException();
169 for ( sal_Int32 nInd = 0; nInd < nRead; nInd++ )
170 aBufferRange[aBuffer.getLength() - static_cast<sal_Int32>(nLength) + nInd] = aTmpBuf[nInd];
171 nLength -= nRead;
174 ParseList( aBuffer, m_aUsersData );
177 return m_aUsersData;
180 void ShareControlFile::SetUsersDataAndStore( std::unique_lock<std::mutex>& /*rGuard*/, std::vector< LockFileEntry >&& aUsersData )
182 if ( !IsValid() )
183 throw io::NotConnectedException();
185 if ( !m_xTruncate.is() || !m_xOutputStream.is() || !m_xSeekable.is() )
186 throw uno::RuntimeException();
188 m_xTruncate->truncate();
189 m_xSeekable->seek( 0 );
191 OUStringBuffer aBuffer;
192 for (const auto & rData : aUsersData)
194 for ( LockFileComponent nEntryInd : o3tl::enumrange<LockFileComponent>() )
196 aBuffer.append( EscapeCharacters( rData[nEntryInd] ) );
197 if ( nEntryInd < LockFileComponent::LAST )
198 aBuffer.append( ',' );
199 else
200 aBuffer.append( ';' );
204 OString aStringData( OUStringToOString( aBuffer, RTL_TEXTENCODING_UTF8 ) );
205 uno::Sequence< sal_Int8 > aData( reinterpret_cast<sal_Int8 const *>(aStringData.getStr()), aStringData.getLength() );
206 m_xOutputStream->writeBytes( aData );
207 m_aUsersData = std::move(aUsersData);
210 LockFileEntry ShareControlFile::InsertOwnEntry()
212 std::unique_lock aGuard( m_aMutex );
214 if ( !IsValid() )
215 throw io::NotConnectedException();
217 GetUsersDataImpl(aGuard);
218 std::vector< LockFileEntry > aNewData( m_aUsersData );
219 LockFileEntry aNewEntry = GenerateOwnEntry();
221 bool bExists = false;
222 sal_Int32 nNewInd = 0;
223 for (LockFileEntry & rEntry : m_aUsersData)
225 if ( rEntry[LockFileComponent::LOCALHOST] == aNewEntry[LockFileComponent::LOCALHOST]
226 && rEntry[LockFileComponent::SYSUSERNAME] == aNewEntry[LockFileComponent::SYSUSERNAME]
227 && rEntry[LockFileComponent::USERURL] == aNewEntry[LockFileComponent::USERURL] )
229 if ( !bExists )
231 aNewData[nNewInd] = aNewEntry;
232 bExists = true;
235 else
237 aNewData[nNewInd] = rEntry;
240 nNewInd++;
243 if ( !bExists )
244 aNewData.push_back( aNewEntry );
246 SetUsersDataAndStore( aGuard, std::move(aNewData) );
248 return aNewEntry;
252 bool ShareControlFile::HasOwnEntry()
254 std::unique_lock aGuard( m_aMutex );
256 if ( !IsValid() )
258 throw io::NotConnectedException();
261 GetUsersDataImpl(aGuard);
262 LockFileEntry aEntry = GenerateOwnEntry();
264 for (LockFileEntry & rEntry : m_aUsersData)
266 if ( rEntry[LockFileComponent::LOCALHOST] == aEntry[LockFileComponent::LOCALHOST] &&
267 rEntry[LockFileComponent::SYSUSERNAME] == aEntry[LockFileComponent::SYSUSERNAME] &&
268 rEntry[LockFileComponent::USERURL] == aEntry[LockFileComponent::USERURL] )
270 return true;
274 return false;
278 void ShareControlFile::RemoveEntry()
280 RemoveEntry(GenerateOwnEntry());
283 void ShareControlFile::RemoveEntry( const LockFileEntry& aEntry )
285 std::unique_lock aGuard( m_aMutex );
287 if ( !IsValid() )
288 throw io::NotConnectedException();
290 GetUsersDataImpl(aGuard);
292 std::vector< LockFileEntry > aNewData;
294 for (LockFileEntry & rEntry : m_aUsersData)
296 if ( rEntry[LockFileComponent::LOCALHOST] != aEntry[LockFileComponent::LOCALHOST]
297 || rEntry[LockFileComponent::SYSUSERNAME] != aEntry[LockFileComponent::SYSUSERNAME]
298 || rEntry[LockFileComponent::USERURL] != aEntry[LockFileComponent::USERURL] )
300 aNewData.push_back( rEntry );
304 const bool bNewDataEmpty = aNewData.empty();
305 SetUsersDataAndStore( aGuard, std::move(aNewData) );
307 if ( bNewDataEmpty )
309 // try to remove the file if it is empty
310 RemoveFileImpl(aGuard);
315 void ShareControlFile::RemoveFile()
317 std::unique_lock aGuard(m_aMutex);
318 return RemoveFileImpl(aGuard);
321 void ShareControlFile::RemoveFileImpl(std::unique_lock<std::mutex>& /*rGuard*/)
323 if ( !IsValid() )
324 throw io::NotConnectedException();
326 Close();
328 uno::Reference<ucb::XSimpleFileAccess3> xSimpleFileAccess(ucb::SimpleFileAccess::create(comphelper::getProcessComponentContext()));
329 xSimpleFileAccess->kill( GetURL() );
332 } // namespace svt
334 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */