1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_svl.hxx" 30 31 #include <stdio.h> 32 33 #include <com/sun/star/ucb/XSimpleFileAccess.hpp> 34 #include <com/sun/star/ucb/XCommandEnvironment.hpp> 35 #include <com/sun/star/ucb/InsertCommandArgument.hpp> 36 #include <com/sun/star/ucb/NameClashException.hpp> 37 #include <com/sun/star/io/WrongFormatException.hpp> 38 39 #include <osl/time.h> 40 #include <osl/security.hxx> 41 #include <osl/socket.hxx> 42 43 #include <rtl/string.hxx> 44 #include <rtl/ustring.hxx> 45 #include <rtl/strbuf.hxx> 46 #include <rtl/ustrbuf.hxx> 47 48 #include <comphelper/processfactory.hxx> 49 50 #include <tools/urlobj.hxx> 51 #include <unotools/bootstrap.hxx> 52 53 #include <ucbhelper/content.hxx> 54 55 #include <unotools/useroptions.hxx> 56 57 #include <svl/documentlockfile.hxx> 58 59 using namespace ::com::sun::star; 60 61 namespace svt { 62 63 sal_Bool DocumentLockFile::m_bAllowInteraction = sal_True; 64 65 // ---------------------------------------------------------------------- 66 DocumentLockFile::DocumentLockFile( const ::rtl::OUString& aOrigURL, const uno::Reference< lang::XMultiServiceFactory >& xFactory ) 67 : LockFileCommon( aOrigURL, xFactory, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".~lock." ) ) ) 68 { 69 } 70 71 // ---------------------------------------------------------------------- 72 DocumentLockFile::~DocumentLockFile() 73 { 74 } 75 76 // ---------------------------------------------------------------------- 77 void DocumentLockFile::WriteEntryToStream( uno::Sequence< ::rtl::OUString > aEntry, uno::Reference< io::XOutputStream > xOutput ) 78 { 79 ::osl::MutexGuard aGuard( m_aMutex ); 80 81 ::rtl::OUStringBuffer aBuffer; 82 83 for ( sal_Int32 nEntryInd = 0; nEntryInd < aEntry.getLength(); nEntryInd++ ) 84 { 85 aBuffer.append( EscapeCharacters( aEntry[nEntryInd] ) ); 86 if ( nEntryInd < aEntry.getLength() - 1 ) 87 aBuffer.append( (sal_Unicode)',' ); 88 else 89 aBuffer.append( (sal_Unicode)';' ); 90 } 91 92 ::rtl::OString aStringData( ::rtl::OUStringToOString( aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ) ); 93 uno::Sequence< sal_Int8 > aData( (sal_Int8*)aStringData.getStr(), aStringData.getLength() ); 94 xOutput->writeBytes( aData ); 95 } 96 97 // ---------------------------------------------------------------------- 98 sal_Bool DocumentLockFile::CreateOwnLockFile() 99 { 100 ::osl::MutexGuard aGuard( m_aMutex ); 101 102 try 103 { 104 uno::Reference< io::XStream > xTempFile( 105 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.io.TempFile" ) ), 106 uno::UNO_QUERY_THROW ); 107 uno::Reference< io::XSeekable > xSeekable( xTempFile, uno::UNO_QUERY_THROW ); 108 109 uno::Reference< io::XInputStream > xInput = xTempFile->getInputStream(); 110 uno::Reference< io::XOutputStream > xOutput = xTempFile->getOutputStream(); 111 112 if ( !xInput.is() || !xOutput.is() ) 113 throw uno::RuntimeException(); 114 115 uno::Sequence< ::rtl::OUString > aNewEntry = GenerateOwnEntry(); 116 WriteEntryToStream( aNewEntry, xOutput ); 117 xOutput->closeOutput(); 118 119 xSeekable->seek( 0 ); 120 121 uno::Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv; 122 ::ucbhelper::Content aTargetContent( m_aURL, xEnv ); 123 124 ucb::InsertCommandArgument aInsertArg; 125 aInsertArg.Data = xInput; 126 aInsertArg.ReplaceExisting = sal_False; 127 uno::Any aCmdArg; 128 aCmdArg <<= aInsertArg; 129 aTargetContent.executeCommand( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), aCmdArg ); 130 131 // try to let the file be hidden if possible 132 try { 133 aTargetContent.setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsHidden" ) ), uno::makeAny( sal_True ) ); 134 } catch( uno::Exception& ) {} 135 } 136 catch( ucb::NameClashException& ) 137 { 138 return sal_False; 139 } 140 141 return sal_True; 142 } 143 144 // ---------------------------------------------------------------------- 145 uno::Sequence< ::rtl::OUString > DocumentLockFile::GetLockData() 146 { 147 ::osl::MutexGuard aGuard( m_aMutex ); 148 149 uno::Reference< io::XInputStream > xInput = OpenStream(); 150 if ( !xInput.is() ) 151 throw uno::RuntimeException(); 152 153 const sal_Int32 nBufLen = 32000; 154 uno::Sequence< sal_Int8 > aBuffer( nBufLen ); 155 156 sal_Int32 nRead = 0; 157 158 nRead = xInput->readBytes( aBuffer, nBufLen ); 159 xInput->closeInput(); 160 161 if ( nRead == nBufLen ) 162 throw io::WrongFormatException(); 163 164 sal_Int32 nCurPos = 0; 165 return ParseEntry( aBuffer, nCurPos ); 166 } 167 168 // ---------------------------------------------------------------------- 169 uno::Reference< io::XInputStream > DocumentLockFile::OpenStream() 170 { 171 ::osl::MutexGuard aGuard( m_aMutex ); 172 173 uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); 174 uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess > xSimpleFileAccess( 175 xFactory->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.ucb.SimpleFileAccess") ), 176 uno::UNO_QUERY_THROW ); 177 178 // the file can be opened readonly, no locking will be done 179 return xSimpleFileAccess->openFileRead( m_aURL ); 180 } 181 182 // ---------------------------------------------------------------------- 183 sal_Bool DocumentLockFile::OverwriteOwnLockFile() 184 { 185 // allows to overwrite the lock file with the current data 186 try 187 { 188 uno::Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv; 189 ::ucbhelper::Content aTargetContent( m_aURL, xEnv ); 190 191 uno::Sequence< ::rtl::OUString > aNewEntry = GenerateOwnEntry(); 192 193 uno::Reference< io::XStream > xStream = aTargetContent.openWriteableStreamNoLock(); 194 uno::Reference< io::XOutputStream > xOutput = xStream->getOutputStream(); 195 uno::Reference< io::XTruncate > xTruncate( xOutput, uno::UNO_QUERY_THROW ); 196 197 xTruncate->truncate(); 198 WriteEntryToStream( aNewEntry, xOutput ); 199 xOutput->closeOutput(); 200 } 201 catch( uno::Exception& ) 202 { 203 return sal_False; 204 } 205 206 return sal_True; 207 } 208 209 // ---------------------------------------------------------------------- 210 void DocumentLockFile::RemoveFile() 211 { 212 ::osl::MutexGuard aGuard( m_aMutex ); 213 214 // TODO/LATER: the removing is not atomar, is it possible in general to make it atomar? 215 uno::Sequence< ::rtl::OUString > aNewEntry = GenerateOwnEntry(); 216 uno::Sequence< ::rtl::OUString > aFileData = GetLockData(); 217 218 if ( aFileData.getLength() < LOCKFILE_ENTRYSIZE ) 219 throw io::WrongFormatException(); 220 221 if ( !aFileData[LOCKFILE_SYSUSERNAME_ID].equals( aNewEntry[LOCKFILE_SYSUSERNAME_ID] ) 222 || !aFileData[LOCKFILE_LOCALHOST_ID].equals( aNewEntry[LOCKFILE_LOCALHOST_ID] ) 223 || !aFileData[LOCKFILE_USERURL_ID].equals( aNewEntry[LOCKFILE_USERURL_ID] ) ) 224 throw io::IOException(); // not the owner, access denied 225 226 uno::Reference< lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); 227 uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess > xSimpleFileAccess( 228 xFactory->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.ucb.SimpleFileAccess") ), 229 uno::UNO_QUERY_THROW ); 230 xSimpleFileAccess->kill( m_aURL ); 231 } 232 233 } // namespace svt 234 235