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