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("$OOO_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.getStr(), 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 // permissive licences like ALv2 don't need end user license approval 110 return sal_False; 111 } 112 113 /* Local function - get access to the configuration */ 114 static Reference< XPropertySet > impl_getConfigurationAccess( const OUString& rPath ) 115 { 116 Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); 117 118 // get configuration provider 119 Reference< XMultiServiceFactory > xConfigProvider = Reference< XMultiServiceFactory >( 120 xFactory->createInstance( sConfigSrvc ), UNO_QUERY_THROW ); 121 122 Sequence< Any > aArgs( 1 ); 123 NamedValue aValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "NodePath" ) ), makeAny( rPath ) ); 124 aArgs[0] <<= aValue; 125 return Reference< XPropertySet >( 126 xConfigProvider->createInstanceWithArguments( sAccessSrvc, aArgs ), UNO_QUERY_THROW ); 127 } 128 129 /* Local function - was the wizard completed already? */ 130 static sal_Bool impl_isFirstStart() 131 { 132 try { 133 Reference< XPropertySet > xPSet = impl_getConfigurationAccess( OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Setup/Office" ) ) ); 134 135 Any result = xPSet->getPropertyValue(OUString::createFromAscii("FirstStartWizardCompleted")); 136 sal_Bool bCompleted = sal_False; 137 if ((result >>= bCompleted) && bCompleted) 138 return sal_False; // wizard was already completed 139 else 140 return sal_True; 141 } catch (const Exception&) 142 { 143 return sal_True; 144 } 145 } 146 147 /* Local function - convert oslDateTime to tools DateTime */ 148 static DateTime impl_oslDateTimeToDateTime(const oslDateTime& aDateTime) 149 { 150 return DateTime( 151 Date(aDateTime.Day, aDateTime.Month, aDateTime.Year), 152 Time(aDateTime.Hours, aDateTime.Minutes, aDateTime.Seconds)); 153 } 154 155 /* Local function - get DateTime from a string */ 156 static sal_Bool impl_parseDateTime(const OUString& aString, DateTime& aDateTime) 157 { 158 // take apart a canonical literal xsd:dateTime string 159 //CCYY-MM-DDThh:mm:ss(Z) 160 161 OUString aDateTimeString = aString.trim(); 162 163 // check length 164 if (aDateTimeString.getLength() < 19 || aDateTimeString.getLength() > 20) 165 return sal_False; 166 167 sal_Int32 nDateLength = 10; 168 sal_Int32 nTimeLength = 8; 169 170 OUString aDateTimeSep = OUString::createFromAscii("T"); 171 OUString aDateSep = OUString::createFromAscii("-"); 172 OUString aTimeSep = OUString::createFromAscii(":"); 173 OUString aUTCString = OUString::createFromAscii("Z"); 174 175 OUString aDateString = aDateTimeString.copy(0, nDateLength); 176 OUString aTimeString = aDateTimeString.copy(nDateLength+1, nTimeLength); 177 178 sal_Int32 nIndex = 0; 179 sal_Int32 nYear = aDateString.getToken(0, '-', nIndex).toInt32(); 180 sal_Int32 nMonth = aDateString.getToken(0, '-', nIndex).toInt32(); 181 sal_Int32 nDay = aDateString.getToken(0, '-', nIndex).toInt32(); 182 nIndex = 0; 183 sal_Int32 nHour = aTimeString.getToken(0, ':', nIndex).toInt32(); 184 sal_Int32 nMinute = aTimeString.getToken(0, ':', nIndex).toInt32(); 185 sal_Int32 nSecond = aTimeString.getToken(0, ':', nIndex).toInt32(); 186 187 Date tmpDate((sal_uInt16)nDay, (sal_uInt16)nMonth, (sal_uInt16)nYear); 188 Time tmpTime(nHour, nMinute, nSecond); 189 DateTime tmpDateTime(tmpDate, tmpTime); 190 if (aString.indexOf(aUTCString) < 0) 191 tmpDateTime.ConvertToUTC(); 192 193 aDateTime = tmpDateTime; 194 return sal_True; 195 } 196 197 /* Local function - was the license accepted already? */ 198 static sal_Bool impl_isLicenseAccepted() 199 { 200 // If no license will be shown ... it must not be accepted. 201 // So it was accepted "hardly" by the outside installer. 202 // But if the configuration entry "HideEula" will be removed afterwards .. 203 // we have to show the licese page again and user has to accept it here .-) 204 if ( ! Desktop::LicenseNeedsAcceptance() ) 205 return sal_True; 206 207 try 208 { 209 Reference< XPropertySet > xPSet = impl_getConfigurationAccess( OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Setup/Office" ) ) ); 210 211 Any result = xPSet->getPropertyValue(OUString::createFromAscii("LicenseAcceptDate")); 212 213 OUString aAcceptDate; 214 if (result >>= aAcceptDate) 215 { 216 // compare to date of license file 217 OUString aLicenseURL = Desktop::GetLicensePath(); 218 osl::DirectoryItem aDirItem; 219 if (osl::DirectoryItem::get(aLicenseURL, aDirItem) != osl::FileBase::E_None) 220 return sal_False; 221 osl::FileStatus aStatus(FileStatusMask_All); 222 if (aDirItem.getFileStatus(aStatus) != osl::FileBase::E_None) 223 return sal_False; 224 TimeValue aTimeVal = aStatus.getModifyTime(); 225 oslDateTime aDateTimeVal; 226 if (!osl_getDateTimeFromTimeValue(&aTimeVal, &aDateTimeVal)) 227 return sal_False; 228 229 // compare dates 230 DateTime aLicenseDateTime = impl_oslDateTimeToDateTime(aDateTimeVal); 231 DateTime aAcceptDateTime; 232 if (!impl_parseDateTime(aAcceptDate, aAcceptDateTime)) 233 return sal_False; 234 235 if ( aAcceptDateTime > aLicenseDateTime ) 236 return sal_True; 237 } 238 return sal_False; 239 } catch (const Exception&) 240 { 241 return sal_False; 242 } 243 } 244 245 /* Check if we need the first start wizard. */ 246 sal_Bool Desktop::IsFirstStartWizardNeeded() 247 { 248 return impl_isFirstStart() || !impl_isLicenseAccepted(); 249 } 250 251 void Desktop::FinishFirstStart() 252 { 253 #if 0 // most platforms no longer benefit from the quickstarter, TODO: are the other benefits worth it? 254 #ifndef OS2 // cannot enable quickstart on first startup, see shutdownicon.cxx comments. 255 EnableQuickstart(); 256 #endif 257 #endif 258 259 try { 260 Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); 261 // get configuration provider 262 Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >( 263 xFactory->createInstance(sConfigSrvc), UNO_QUERY_THROW); 264 Sequence< Any > theArgs(1); 265 NamedValue v(OUString::createFromAscii("NodePath"), 266 makeAny(OUString::createFromAscii("org.openoffice.Setup/Office"))); 267 theArgs[0] <<= v; 268 Reference< XPropertySet > pset = Reference< XPropertySet >( 269 theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW); 270 pset->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("FirstStartWizardCompleted")), makeAny(sal_True)); 271 Reference< util::XChangesBatch >(pset, UNO_QUERY_THROW)->commitChanges(); 272 } catch (const uno::Exception&) { 273 // ignore the exception as it is not critical enough to prevent office from starting 274 } 275 } 276 277 void Desktop::EnableQuickstart() 278 { 279 sal_Bool bQuickstart( sal_True ); 280 sal_Bool bAutostart( sal_True ); 281 Sequence< Any > aSeq( 2 ); 282 aSeq[0] <<= bQuickstart; 283 aSeq[1] <<= bAutostart; 284 285 Reference < XInitialization > xQuickstart( ::comphelper::getProcessServiceFactory()->createInstance( 286 OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.office.Quickstart"))), UNO_QUERY ); 287 if ( xQuickstart.is() ) 288 xQuickstart->initialize( aSeq ); 289 } 290 291 void Desktop::DoRestartActionsIfNecessary( sal_Bool bQuickStart ) 292 { 293 if ( bQuickStart ) 294 { 295 try 296 { 297 Reference< XPropertySet > xPSet = impl_getConfigurationAccess( OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Setup/Office" ) ) ); 298 299 OUString sPropName( RTL_CONSTASCII_USTRINGPARAM( "OfficeRestartInProgress" ) ); 300 Any aRestart = xPSet->getPropertyValue( sPropName ); 301 sal_Bool bRestart = sal_False; 302 if ( ( aRestart >>= bRestart ) && bRestart ) 303 { 304 xPSet->setPropertyValue( sPropName, makeAny( sal_False ) ); 305 Reference< util::XChangesBatch >( xPSet, UNO_QUERY_THROW )->commitChanges(); 306 307 Sequence< Any > aSeq( 2 ); 308 aSeq[0] <<= sal_True; 309 aSeq[1] <<= sal_True; 310 311 Reference < XInitialization > xQuickstart( ::comphelper::getProcessServiceFactory()->createInstance( 312 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.office.Quickstart" ) ) ),UNO_QUERY_THROW ); 313 xQuickstart->initialize( aSeq ); 314 } 315 } 316 catch( uno::Exception& ) 317 { 318 // this is no critical operation so it should not prevent office from starting 319 } 320 } 321 } 322 323 void Desktop::SetRestartState() 324 { 325 try 326 { 327 Reference< XPropertySet > xPSet = impl_getConfigurationAccess( OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Setup/Office" ) ) ); 328 OUString sPropName( RTL_CONSTASCII_USTRINGPARAM( "OfficeRestartInProgress" ) ); 329 xPSet->setPropertyValue( sPropName, makeAny( sal_True ) ); 330 Reference< util::XChangesBatch >( xPSet, UNO_QUERY_THROW )->commitChanges(); 331 } 332 catch( uno::Exception& ) 333 { 334 // this is no critical operation, ignore the exception 335 } 336 337 } 338