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_desktop.hxx"
30 #include "wordbookmigration.hxx"
31 #include <tools/urlobj.hxx>
32 #include <unotools/bootstrap.hxx>
33 #include <unotools/ucbstreamhelper.hxx>
34 
35 using namespace ::com::sun::star;
36 using namespace ::com::sun::star::uno;
37 
38 
39 //.........................................................................
40 namespace migration
41 {
42 //.........................................................................
43 
44 
45     static ::rtl::OUString sSourceSubDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/wordbook" ) );
46     static ::rtl::OUString sTargetSubDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/wordbook" ) );
47     static ::rtl::OUString sBaseName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/wordbook" ) );
48     static ::rtl::OUString sSuffix = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".dic" ) );
49 
50 
51     // =============================================================================
52     // component operations
53     // =============================================================================
54 
55     ::rtl::OUString WordbookMigration_getImplementationName()
56     {
57         static ::rtl::OUString* pImplName = 0;
58 	    if ( !pImplName )
59 	    {
60             ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
61             if ( !pImplName )
62 		    {
63                 static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.desktop.migration.Wordbooks" ) );
64 			    pImplName = &aImplName;
65 		    }
66 	    }
67 	    return *pImplName;
68     }
69 
70     // -----------------------------------------------------------------------------
71 
72     Sequence< ::rtl::OUString > WordbookMigration_getSupportedServiceNames()
73     {
74         static Sequence< ::rtl::OUString >* pNames = 0;
75 	    if ( !pNames )
76 	    {
77             ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
78 		    if ( !pNames )
79 		    {
80                 static Sequence< ::rtl::OUString > aNames(1);
81                 aNames.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.migration.Wordbooks" ) );
82                 pNames = &aNames;
83 		    }
84 	    }
85 	    return *pNames;
86     }
87 
88     // =============================================================================
89     // WordbookMigration
90     // =============================================================================
91 
92     WordbookMigration::WordbookMigration()
93     {
94     }
95 
96     // -----------------------------------------------------------------------------
97 
98     WordbookMigration::~WordbookMigration()
99     {
100     }
101 
102     // -----------------------------------------------------------------------------
103 
104     TStringVectorPtr WordbookMigration::getFiles( const ::rtl::OUString& rBaseURL ) const
105     {
106         TStringVectorPtr aResult( new TStringVector );
107         ::osl::Directory aDir( rBaseURL);
108 
109         if ( aDir.open() == ::osl::FileBase::E_None )
110         {
111             // iterate over directory content
112             TStringVector aSubDirs;
113             ::osl::DirectoryItem aItem;
114             while ( aDir.getNextItem( aItem ) == ::osl::FileBase::E_None )
115             {
116                 ::osl::FileStatus aFileStatus( FileStatusMask_Type | FileStatusMask_FileURL );
117                 if ( aItem.getFileStatus( aFileStatus ) == ::osl::FileBase::E_None )
118                 {
119                     if ( aFileStatus.getFileType() == ::osl::FileStatus::Directory )
120                         aSubDirs.push_back( aFileStatus.getFileURL() );
121                     else
122                         aResult->push_back( aFileStatus.getFileURL() );
123                 }
124             }
125 
126             // iterate recursive over subfolders
127             TStringVector::const_iterator aI = aSubDirs.begin();
128             while ( aI != aSubDirs.end() )
129             {
130                 TStringVectorPtr aSubResult = getFiles( *aI );
131                 aResult->insert( aResult->end(), aSubResult->begin(), aSubResult->end() );
132                 ++aI;
133             }
134         }
135 
136         return aResult;
137     }
138 
139     // -----------------------------------------------------------------------------
140 
141     ::osl::FileBase::RC WordbookMigration::checkAndCreateDirectory( INetURLObject& rDirURL )
142     {
143         ::osl::FileBase::RC aResult = ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) );
144         if ( aResult == ::osl::FileBase::E_NOENT )
145         {
146             INetURLObject aBaseURL( rDirURL );
147             aBaseURL.removeSegment();
148             checkAndCreateDirectory( aBaseURL );
149             return ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) );
150         }
151         else
152         {
153             return aResult;
154         }
155     }
156 
157 #define MAX_HEADER_LENGTH 16
158 bool IsUserWordbook( const ::rtl::OUString& rFile )
159 {
160 	static const sal_Char*		pVerStr2	= "WBSWG2";
161 	static const sal_Char*		pVerStr5	= "WBSWG5";
162 	static const sal_Char*		pVerStr6	= "WBSWG6";
163 	static const sal_Char*      pVerOOo7    = "OOoUserDict1";
164 
165     bool bRet = false;
166 	SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( String(rFile), STREAM_STD_READ );
167 	if ( pStream && !pStream->GetError() )
168 	{
169 	    sal_Size nSniffPos = pStream->Tell();
170 		static sal_Size nVerOOo7Len = sal::static_int_cast< sal_Size >(strlen( pVerOOo7 ));
171 		sal_Char pMagicHeader[MAX_HEADER_LENGTH];
172 		pMagicHeader[ nVerOOo7Len ] = '\0';
173 		if ((pStream->Read((void *) pMagicHeader, nVerOOo7Len) == nVerOOo7Len))
174 		{
175 			if ( !strcmp(pMagicHeader, pVerOOo7) )
176 				bRet = true;
177 			else
178 			{
179 		        sal_uInt16 nLen;
180 		        pStream->Seek (nSniffPos);
181 		        *pStream >> nLen;
182 				if ( nLen < MAX_HEADER_LENGTH )
183 				{
184 			       pStream->Read(pMagicHeader, nLen);
185 			       pMagicHeader[nLen] = '\0';
186 					if ( !strcmp(pMagicHeader, pVerStr2)
187 					 ||  !strcmp(pMagicHeader, pVerStr5)
188 			         ||  !strcmp(pMagicHeader, pVerStr6) )
189 					bRet = true;
190 				}
191 			}
192 		}
193 	}
194 
195 	delete pStream;
196 	return bRet;
197 }
198 
199 
200     // -----------------------------------------------------------------------------
201 
202     void WordbookMigration::copyFiles()
203     {
204         ::rtl::OUString sTargetDir;
205         ::utl::Bootstrap::PathStatus aStatus = ::utl::Bootstrap::locateUserInstallation( sTargetDir );
206         if ( aStatus == ::utl::Bootstrap::PATH_EXISTS )
207         {
208             sTargetDir += sTargetSubDir;
209             TStringVectorPtr aFileList = getFiles( m_sSourceDir );
210             TStringVector::const_iterator aI = aFileList->begin();
211             while ( aI != aFileList->end() )
212             {
213 				if (IsUserWordbook(*aI) )
214 				{
215 					::rtl::OUString sSourceLocalName = aI->copy( m_sSourceDir.getLength() );
216 					::rtl::OUString sTargetName = sTargetDir + sSourceLocalName;
217 					INetURLObject aURL( sTargetName );
218 					aURL.removeSegment();
219 					checkAndCreateDirectory( aURL );
220 					::osl::FileBase::RC aResult = ::osl::File::copy( *aI, sTargetName );
221 					if ( aResult != ::osl::FileBase::E_None )
222 					{
223 						::rtl::OString aMsg( "WordbookMigration::copyFiles: cannot copy " );
224 						aMsg += ::rtl::OUStringToOString( *aI, RTL_TEXTENCODING_UTF8 ) + " to "
225 							 +  ::rtl::OUStringToOString( sTargetName, RTL_TEXTENCODING_UTF8 );
226 						OSL_ENSURE( sal_False, aMsg.getStr() );
227 					}
228 				}
229 				++aI;
230             }
231         }
232         else
233         {
234             OSL_ENSURE( sal_False, "WordbookMigration::copyFiles: no user installation!" );
235         }
236     }
237 
238     // -----------------------------------------------------------------------------
239     // XServiceInfo
240     // -----------------------------------------------------------------------------
241 
242     ::rtl::OUString WordbookMigration::getImplementationName() throw (RuntimeException)
243     {
244         return WordbookMigration_getImplementationName();
245     }
246 
247     // -----------------------------------------------------------------------------
248 
249     sal_Bool WordbookMigration::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException)
250     {
251 	    Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() );
252 	    const ::rtl::OUString* pNames = aNames.getConstArray();
253 	    const ::rtl::OUString* pEnd = pNames + aNames.getLength();
254 	    for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames )
255 		    ;
256 
257 	    return pNames != pEnd;
258     }
259 
260     // -----------------------------------------------------------------------------
261 
262     Sequence< ::rtl::OUString > WordbookMigration::getSupportedServiceNames() throw (RuntimeException)
263     {
264         return WordbookMigration_getSupportedServiceNames();
265     }
266 
267     // -----------------------------------------------------------------------------
268     // XInitialization
269     // -----------------------------------------------------------------------------
270 
271     void WordbookMigration::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException)
272     {
273         ::osl::MutexGuard aGuard( m_aMutex );
274 
275         const Any* pIter = aArguments.getConstArray();
276         const Any* pEnd = pIter + aArguments.getLength();
277         for ( ; pIter != pEnd ; ++pIter )
278         {
279             beans::NamedValue aValue;
280             *pIter >>= aValue;
281             if ( aValue.Name.equalsAscii( "UserData" ) )
282             {
283                 if ( !(aValue.Value >>= m_sSourceDir) )
284                 {
285                     OSL_ENSURE( false, "WordbookMigration::initialize: argument UserData has wrong type!" );
286                 }
287                 m_sSourceDir += sSourceSubDir;
288                 break;
289             }
290         }
291     }
292 
293     // -----------------------------------------------------------------------------
294     // XJob
295     // -----------------------------------------------------------------------------
296 
297     Any WordbookMigration::execute( const Sequence< beans::NamedValue >& )
298         throw (lang::IllegalArgumentException, Exception, RuntimeException)
299     {
300         ::osl::MutexGuard aGuard( m_aMutex );
301 
302         copyFiles();
303 
304         return Any();
305     }
306 
307     // =============================================================================
308     // component operations
309     // =============================================================================
310 
311     Reference< XInterface > SAL_CALL WordbookMigration_create(
312         Reference< XComponentContext > const & )
313         SAL_THROW( () )
314     {
315         return static_cast< lang::XTypeProvider * >( new WordbookMigration() );
316     }
317 
318     // -----------------------------------------------------------------------------
319 
320 //.........................................................................
321 }	// namespace migration
322 //.........................................................................
323