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 // MARKER(update_precomp.py): autogen include statement, do not remove
28 #include "precompiled_desktop.hxx"
29 
30 #include <osl/file.hxx>
31 #include <rtl/bootstrap.hxx>
32 #include <rtl/ustring.hxx>
33 #include <tools/datetime.hxx>
34 #include <unotools/configmgr.hxx>
35 
36 #include <comphelper/processfactory.hxx>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/beans/NamedValue.hpp>
39 #include <com/sun/star/util/XChangesBatch.hpp>
40 
41 #include "app.hxx"
42 
43 using ::rtl::OUString;
44 using namespace ::desktop;
45 using namespace ::com::sun::star;
46 using namespace ::com::sun::star::beans;
47 
48 static const OUString sConfigSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) );
49 static const OUString sAccessSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) );
50 
51 /* Path of the license. */
52 OUString Desktop::GetLicensePath()
53 {
54     // license file name
55     static const char *szLicensePath = "/share/readme";
56 #if defined(WNT) || defined(OS2)
57     static const char *szWNTLicenseName = "/license";
58     static const char *szWNTLicenseExt = ".txt";
59 #else
60     static const char *szUNXLicenseName = "/LICENSE";
61     static const char *szUNXLicenseExt = "";
62 #endif
63     static OUString aLicensePath;
64 
65     if (aLicensePath.getLength() > 0)
66         return aLicensePath;
67 
68     OUString aBaseInstallPath(RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR"));
69     rtl::Bootstrap::expandMacros(aBaseInstallPath);
70 
71     // determine the filename of the license to show
72     OUString  aLangString;
73     ::com::sun::star::lang::Locale aLocale;
74     OString aMgrName = OString("dkt");
75 
76     AllSettings aSettings(Application::GetSettings());
77     aLocale = aSettings.GetUILocale();
78     ResMgr* pLocalResMgr = ResMgr::SearchCreateResMgr(aMgrName, aLocale);
79 
80     aLangString = aLocale.Language;
81     if ( aLocale.Country.getLength() != 0 )
82     {
83         aLangString += OUString::createFromAscii("-");
84         aLangString += aLocale.Country;
85         if ( aLocale.Variant.getLength() != 0 )
86         {
87             aLangString += OUString::createFromAscii("-");
88             aLangString += aLocale.Variant;
89         }
90     }
91 #if defined(WNT) || defined(OS2)
92     aLicensePath =
93         aBaseInstallPath + OUString::createFromAscii(szLicensePath)
94         + OUString::createFromAscii(szWNTLicenseName)
95         + OUString::createFromAscii("_")
96         + aLangString
97         + OUString::createFromAscii(szWNTLicenseExt);
98 #else
99     aLicensePath =
100         aBaseInstallPath + OUString::createFromAscii(szLicensePath)
101         + OUString::createFromAscii(szUNXLicenseName)
102         + OUString::createFromAscii("_")
103         + aLangString
104         + OUString::createFromAscii(szUNXLicenseExt);
105 #endif
106     delete pLocalResMgr;
107     return aLicensePath;
108 }
109 
110 /* Check if we need to accept license. */
111 sal_Bool Desktop::LicenseNeedsAcceptance()
112 {
113     // Don't show a license
114     return sal_False;
115 /*
116     sal_Bool bShowLicense = sal_True;
117     sal_Int32 nOpenSourceContext = 0;
118     try
119     {
120         ::utl::ConfigManager::GetDirectConfigProperty(
121             ::utl::ConfigManager::OPENSOURCECONTEXT ) >>= nOpenSourceContext;
122     }
123     catch( const ::com::sun::star::uno::Exception& ) {}
124 
125     // open source needs no license
126     if ( nOpenSourceContext > 0 )
127         bShowLicense = sal_False;
128 
129     return bShowLicense;
130 */
131 }
132 
133 /* Local function - get access to the configuration */
134 static Reference< XPropertySet > impl_getConfigurationAccess( const OUString& rPath )
135 {
136     Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
137 
138     // get configuration provider
139     Reference< XMultiServiceFactory > xConfigProvider = Reference< XMultiServiceFactory >(
140             xFactory->createInstance( sConfigSrvc ), UNO_QUERY_THROW );
141 
142     Sequence< Any > aArgs( 1 );
143     NamedValue aValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "NodePath" ) ), makeAny( rPath ) );
144     aArgs[0] <<= aValue;
145     return Reference< XPropertySet >(
146             xConfigProvider->createInstanceWithArguments( sAccessSrvc, aArgs ), UNO_QUERY_THROW );
147 }
148 
149 /* Local function - was the wizard completed already? */
150 static sal_Bool impl_isFirstStart()
151 {
152     try {
153         Reference< XPropertySet > xPSet = impl_getConfigurationAccess( OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Setup/Office" ) ) );
154 
155         Any result = xPSet->getPropertyValue(OUString::createFromAscii("FirstStartWizardCompleted"));
156         sal_Bool bCompleted = sal_False;
157         if ((result >>= bCompleted) && bCompleted)
158             return sal_False;  // wizard was already completed
159         else
160             return sal_True;
161     } catch (const Exception&)
162     {
163         return sal_True;
164     }
165 }
166 
167 /* Local function - convert oslDateTime to tools DateTime */
168 static DateTime impl_oslDateTimeToDateTime(const oslDateTime& aDateTime)
169 {
170     return DateTime(
171         Date(aDateTime.Day, aDateTime.Month, aDateTime.Year),
172         Time(aDateTime.Hours, aDateTime.Minutes, aDateTime.Seconds));
173 }
174 
175 /* Local function - get DateTime from a string */
176 static sal_Bool impl_parseDateTime(const OUString& aString, DateTime& aDateTime)
177 {
178     // take apart a canonical literal xsd:dateTime string
179     //CCYY-MM-DDThh:mm:ss(Z)
180 
181     OUString aDateTimeString = aString.trim();
182 
183     // check length
184     if (aDateTimeString.getLength() < 19 || aDateTimeString.getLength() > 20)
185         return sal_False;
186 
187     sal_Int32 nDateLength = 10;
188     sal_Int32 nTimeLength = 8;
189 
190     OUString aDateTimeSep = OUString::createFromAscii("T");
191     OUString aDateSep = OUString::createFromAscii("-");
192     OUString aTimeSep = OUString::createFromAscii(":");
193     OUString aUTCString = OUString::createFromAscii("Z");
194 
195     OUString aDateString = aDateTimeString.copy(0, nDateLength);
196     OUString aTimeString = aDateTimeString.copy(nDateLength+1, nTimeLength);
197 
198     sal_Int32 nIndex = 0;
199     sal_Int32 nYear = aDateString.getToken(0, '-', nIndex).toInt32();
200     sal_Int32 nMonth = aDateString.getToken(0, '-', nIndex).toInt32();
201     sal_Int32 nDay = aDateString.getToken(0, '-', nIndex).toInt32();
202     nIndex = 0;
203     sal_Int32 nHour = aTimeString.getToken(0, ':', nIndex).toInt32();
204     sal_Int32 nMinute = aTimeString.getToken(0, ':', nIndex).toInt32();
205     sal_Int32 nSecond = aTimeString.getToken(0, ':', nIndex).toInt32();
206 
207     Date tmpDate((sal_uInt16)nDay, (sal_uInt16)nMonth, (sal_uInt16)nYear);
208     Time tmpTime(nHour, nMinute, nSecond);
209     DateTime tmpDateTime(tmpDate, tmpTime);
210     if (aString.indexOf(aUTCString) < 0)
211         tmpDateTime.ConvertToUTC();
212 
213     aDateTime = tmpDateTime;
214     return sal_True;
215 }
216 
217 /* Local function - was the license accepted already? */
218 static sal_Bool impl_isLicenseAccepted()
219 {
220     // If no license will be shown ... it must not be accepted.
221     // So it was accepted "hardly" by the outside installer.
222     // But if the configuration entry "HideEula" will be removed afterwards ..
223     // we have to show the licese page again and user has to accept it here .-)
224     if ( ! Desktop::LicenseNeedsAcceptance() )
225         return sal_True;
226 
227     try
228     {
229         Reference< XPropertySet > xPSet = impl_getConfigurationAccess( OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Setup/Office" ) ) );
230 
231         Any result = xPSet->getPropertyValue(OUString::createFromAscii("LicenseAcceptDate"));
232 
233         OUString aAcceptDate;
234         if (result >>= aAcceptDate)
235         {
236             // compare to date of license file
237             OUString aLicenseURL = Desktop::GetLicensePath();
238             osl::DirectoryItem aDirItem;
239             if (osl::DirectoryItem::get(aLicenseURL, aDirItem) != osl::FileBase::E_None)
240                 return sal_False;
241             osl::FileStatus aStatus(FileStatusMask_All);
242             if (aDirItem.getFileStatus(aStatus) != osl::FileBase::E_None)
243                 return sal_False;
244             TimeValue aTimeVal = aStatus.getModifyTime();
245             oslDateTime aDateTimeVal;
246             if (!osl_getDateTimeFromTimeValue(&aTimeVal, &aDateTimeVal))
247                 return sal_False;
248 
249             // compare dates
250             DateTime aLicenseDateTime = impl_oslDateTimeToDateTime(aDateTimeVal);
251             DateTime aAcceptDateTime;
252             if (!impl_parseDateTime(aAcceptDate, aAcceptDateTime))
253                 return sal_False;
254 
255             if ( aAcceptDateTime > aLicenseDateTime )
256                 return sal_True;
257         }
258         return sal_False;
259     } catch (const Exception&)
260     {
261         return sal_False;
262     }
263 }
264 
265 /* Check if we need the first start wizard. */
266 sal_Bool Desktop::IsFirstStartWizardNeeded()
267 {
268     return impl_isFirstStart() || !impl_isLicenseAccepted();
269 }
270 
271 void Desktop::DoRestartActionsIfNecessary( sal_Bool bQuickStart )
272 {
273     if ( bQuickStart )
274     {
275         try
276         {
277             Reference< XPropertySet > xPSet = impl_getConfigurationAccess( OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Setup/Office" ) ) );
278 
279             OUString sPropName( RTL_CONSTASCII_USTRINGPARAM( "OfficeRestartInProgress" ) );
280             Any aRestart = xPSet->getPropertyValue( sPropName );
281             sal_Bool bRestart = sal_False;
282             if ( ( aRestart >>= bRestart ) && bRestart )
283             {
284                 xPSet->setPropertyValue( sPropName, makeAny( sal_False ) );
285                 Reference< util::XChangesBatch >( xPSet, UNO_QUERY_THROW )->commitChanges();
286 
287                 Sequence< Any > aSeq( 2 );
288                 aSeq[0] <<= sal_True;
289                 aSeq[1] <<= sal_True;
290 
291                 Reference < XInitialization > xQuickstart( ::comphelper::getProcessServiceFactory()->createInstance(
292                     OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.office.Quickstart" ) ) ),UNO_QUERY_THROW );
293                 xQuickstart->initialize( aSeq );
294             }
295         }
296         catch( uno::Exception& )
297         {
298             // this is no critical operation so it should not prevent office from starting
299         }
300     }
301 }
302 
303 void Desktop::SetRestartState()
304 {
305     try
306     {
307         Reference< XPropertySet > xPSet = impl_getConfigurationAccess( OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Setup/Office" ) ) );
308         OUString sPropName( RTL_CONSTASCII_USTRINGPARAM( "OfficeRestartInProgress" ) );
309         xPSet->setPropertyValue( sPropName, makeAny( sal_True ) );
310         Reference< util::XChangesBatch >( xPSet, UNO_QUERY_THROW )->commitChanges();
311     }
312     catch( uno::Exception& )
313     {
314         // this is no critical operation, ignore the exception
315     }
316 
317 }
318 
319