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