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 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_desktop.hxx"
26 
27 #include <migration.hxx>
28 #include "wizard.hxx"
29 #include "wizard.hrc"
30 #include "pages.hxx"
31 #include "app.hxx"
32 
33 #include <rtl/ustring.hxx>
34 #include <rtl/ustrbuf.hxx>
35 #include <rtl/string.hxx>
36 #include <rtl/strbuf.hxx>
37 #include <rtl/bootstrap.hxx>
38 
39 #include <comphelper/processfactory.hxx>
40 #include <tools/date.hxx>
41 #include <tools/time.hxx>
42 #include <tools/datetime.hxx>
43 #include <osl/file.hxx>
44 #include <osl/time.h>
45 #include <osl/module.hxx>
46 #include <unotools/bootstrap.hxx>
47 #include <vcl/msgbox.hxx>
48 
49 #include <com/sun/star/uno/Any.hxx>
50 #include <com/sun/star/uno/Sequence.hxx>
51 #include <com/sun/star/beans/NamedValue.hpp>
52 #include <com/sun/star/beans/XPropertySet.hpp>
53 #include <com/sun/star/beans/XPropertyState.hpp>
54 #include <com/sun/star/frame/XDesktop.hpp>
55 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
56 #include <com/sun/star/lang/XInitialization.hpp>
57 #include <com/sun/star/lang/XComponent.hpp>
58 #include <com/sun/star/util/XChangesBatch.hpp>
59 #include <com/sun/star/container/XNameReplace.hpp>
60 #include <com/sun/star/awt/WindowDescriptor.hpp>
61 #include <com/sun/star/awt/WindowAttribute.hpp>
62 
63 using namespace svt;
64 using namespace rtl;
65 using namespace osl;
66 using namespace utl;
67 using namespace com::sun::star;
68 using namespace com::sun::star::uno;
69 using namespace com::sun::star::lang;
70 using namespace com::sun::star::beans;
71 using namespace com::sun::star::util;
72 using namespace com::sun::star::container;
73 
74 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
75 
76 namespace desktop
77 {
78 
79 const FirstStartWizard::WizardState FirstStartWizard::STATE_WELCOME      = 0;
80 const FirstStartWizard::WizardState FirstStartWizard::STATE_LICENSE      = 1;
81 const FirstStartWizard::WizardState FirstStartWizard::STATE_MIGRATION    = 2;
82 const FirstStartWizard::WizardState FirstStartWizard::STATE_USER         = 3;
83 const FirstStartWizard::WizardState FirstStartWizard::STATE_UPDATE_CHECK = 4;
84 const FirstStartWizard::WizardState FirstStartWizard::STATE_REGISTRATION = 5;
85 
86 static sal_Int32 getBuildId()
87 {
88     ::rtl::OUString aDefault;
89     ::rtl::OUString aBuildIdData = utl::Bootstrap::getBuildIdData( aDefault );
90     sal_Int32 nBuildId( 0 );
91     sal_Int32 nIndex1 = aBuildIdData.indexOf(':');
92     sal_Int32 nIndex2 = aBuildIdData.indexOf(')');
93     if (( nIndex1 > 0 ) && ( nIndex2 > 0 ) && ( nIndex2-1 > nIndex1+1 ))
94     {
95         ::rtl::OUString aBuildId = aBuildIdData.copy( nIndex1+1, nIndex2-nIndex1-1 );
96         nBuildId = aBuildId.toInt32();
97     }
98     return nBuildId;
99 }
100 
101 WizardResId::WizardResId( sal_uInt16 nId ) :
102 	ResId( nId, *FirstStartWizard::GetResManager() )
103 {
104 }
105 
106 ResMgr *FirstStartWizard::pResMgr = 0;
107 
108 ResMgr *FirstStartWizard::GetResManager()
109 {
110     if ( !FirstStartWizard::pResMgr )
111     {
112         String aMgrName = String::CreateFromAscii( "dkt" );
113         FirstStartWizard::pResMgr = ResMgr::CreateResMgr( OUStringToOString( aMgrName, RTL_TEXTENCODING_UTF8 ));
114     }
115     return FirstStartWizard::pResMgr;
116 }
117 
118 FirstStartWizard::FirstStartWizard( Window* pParent, sal_Bool bLicenseNeedsAcceptance, const rtl::OUString &rLicensePath )
119     :RoadmapWizard( pParent,
120                     WizardResId(DLG_FIRSTSTART_WIZARD),
121                     WZB_NEXT|WZB_PREVIOUS|WZB_FINISH|WZB_CANCEL|WZB_HELP)
122     ,m_bOverride(sal_False)
123     , m_lastState( STATE_WELCOME )
124     ,m_aDefaultPath(0)
125 	,m_aMigrationPath(0)
126     ,m_bDone(sal_False)
127 	,m_bLicenseNeedsAcceptance( bLicenseNeedsAcceptance )
128     ,m_bLicenseWasAccepted(sal_False)
129     ,m_bAutomaticUpdChk(sal_True)
130     ,m_aThrobber(this, WizardResId(CTRL_THROBBER))
131     ,m_aLicensePath( rLicensePath )
132 {
133     FreeResource();
134 
135     Size aTPSize(TP_WIDTH, TP_HEIGHT);
136     SetPageSizePixel(LogicToPixel(aTPSize, MAP_APPFONT));
137 
138     //set help id
139     m_pPrevPage->SetHelpId(HID_FIRSTSTART_PREV);
140     m_pNextPage->SetHelpId(HID_FIRSTSTART_NEXT);
141     m_pCancel->SetHelpId(HID_FIRSTSTART_CANCEL);
142     m_pFinish->SetHelpId(HID_FIRSTSTART_FINISH);
143     m_pHelp->Hide();
144     m_pHelp->Disable();
145 
146     // save button lables
147     m_sNext = m_pNextPage->GetText();
148     m_sCancel = m_pCancel->GetText();
149 
150     // save cancel click handler
151     m_lnkCancel = m_pCancel->GetClickHdl();
152 
153     m_aDefaultPath = defineWizardPagesDependingFromContext();
154 	activatePath(m_aDefaultPath, sal_True);
155 
156     ActivatePage();
157 
158     // set text of finish putton:
159     m_pFinish->SetText(String(WizardResId(STR_FINISH)));
160     // disable "finish button"
161     enableButtons(WZB_FINISH, sal_False);
162     defaultButton(WZB_NEXT);
163 }
164 
165 void FirstStartWizard::DisableButtonsWhileMigration()
166 {
167     enableButtons(0xff, sal_False);
168 }
169 
170 ::svt::RoadmapWizardTypes::PathId FirstStartWizard::defineWizardPagesDependingFromContext()
171 {
172 	::svt::RoadmapWizardTypes::PathId aDefaultPath = 0;
173 
174     sal_Bool bPage_Migration    = sal_True;
175     sal_Bool bPage_UpdateCheck  = sal_True;
176 
177     bPage_Migration   = Migration::checkMigration();
178     bPage_UpdateCheck = showOnlineUpdatePage();
179 
180     WizardPath aPath;
181     aPath.push_back(STATE_WELCOME);
182     if (bPage_Migration)
183     {
184         aPath.push_back(STATE_MIGRATION);
185     }
186     aPath.push_back(STATE_USER);
187     m_lastState = STATE_USER;
188     if (bPage_UpdateCheck)
189     {
190         aPath.push_back(STATE_UPDATE_CHECK);
191         m_lastState = STATE_UPDATE_CHECK;
192     }
193 
194     declarePath(aDefaultPath, aPath);
195 
196 	// a) If license must be accepted by the user, all direct links
197 	//    to wizard tab pages must be disabled. Because such pages
198 	//	  should be accessible only in case license was accepted !
199 	// b) But if no license should be shown at all ...
200 	//    such direct links can be enabled by default.
201 	sal_Bool bAllowDirectLink = true;
202 
203     enableState(STATE_USER, bAllowDirectLink);
204     if (bPage_Migration)
205         enableState(STATE_MIGRATION, bAllowDirectLink);
206     if (bPage_UpdateCheck)
207         enableState(STATE_UPDATE_CHECK, bAllowDirectLink);
208 
209 	return aDefaultPath;
210 }
211 
212 // catch F1 and disable help
213 long FirstStartWizard::PreNotify( NotifyEvent& rNEvt )
214 {
215     if( rNEvt.GetType() == EVENT_KEYINPUT )
216     {
217         const KeyCode& rKey = rNEvt.GetKeyEvent()->GetKeyCode();
218         if( rKey.GetCode() == KEY_F1 && ! rKey.GetModifier() )
219             return sal_True;
220     }
221     return RoadmapWizard::PreNotify(rNEvt);
222 }
223 
224 
225 void FirstStartWizard::enterState(WizardState _nState)
226 {
227     RoadmapWizard::enterState(_nState);
228     // default state
229     // all on
230     enableButtons(0xff, sal_True);
231     // finish off
232     enableButtons(WZB_FINISH, sal_False);
233     // default text
234     m_pCancel->SetText(m_sCancel);
235     m_pCancel->SetClickHdl(m_lnkCancel);
236     m_pNextPage->SetText(m_sNext);
237 
238     // default
239     defaultButton(WZB_NEXT);
240 
241     // specialized state
242     switch (_nState)
243     {
244     case STATE_WELCOME:
245         enableButtons(WZB_PREVIOUS, sal_False);
246         break;
247     case STATE_LICENSE:
248         m_pCancel->SetText(String(WizardResId(STR_LICENSE_DECLINE)));
249         m_pNextPage->SetText(String(WizardResId(STR_LICENSE_ACCEPT)));
250         enableButtons(WZB_NEXT, sal_False);
251         // attach warning dialog to cancel/decline button
252         m_pCancel->SetClickHdl( LINK(this, FirstStartWizard, DeclineHdl) );
253         break;
254     }
255     if ( _nState == m_lastState )
256     {
257         enableButtons(WZB_NEXT, sal_False);
258         enableButtons(WZB_FINISH, sal_True);
259         defaultButton(WZB_FINISH);
260     }
261 }
262 
263 IMPL_LINK( FirstStartWizard, DeclineHdl, PushButton *, EMPTYARG )
264 {
265     QueryBox aBox(this, WizardResId(QB_ASK_DECLINE));
266     sal_Int32 ret = aBox.Execute();
267     if ( ret == BUTTON_OK || ret == BUTTON_YES)
268     {
269         Close();
270         return sal_False;
271     }
272     else
273         return sal_True;
274 }
275 
276 
277 TabPage* FirstStartWizard::createPage(WizardState _nState)
278 {
279     TabPage *pTabPage = 0;
280     switch (_nState)
281     {
282     case STATE_WELCOME:
283         pTabPage = new WelcomePage(this, WizardResId(TP_WELCOME), m_bLicenseNeedsAcceptance);
284         break;
285     case STATE_MIGRATION:
286         pTabPage = new MigrationPage(this, WizardResId(TP_MIGRATION), m_aThrobber);
287         break;
288     case STATE_USER:
289         pTabPage = new UserPage(this, WizardResId(TP_USER));
290         break;
291     case STATE_UPDATE_CHECK:
292         pTabPage = new UpdateCheckPage(this, WizardResId(TP_UPDATE_CHECK));
293         break;
294     }
295     pTabPage->Show();
296 
297     return pTabPage;
298 }
299 
300 String FirstStartWizard::getStateDisplayName( WizardState _nState ) const
301 {
302     String sName;
303     switch(_nState)
304     {
305     case STATE_WELCOME:
306         sName = String(WizardResId(STR_STATE_WELCOME));
307         break;
308     case STATE_MIGRATION:
309         sName = String(WizardResId(STR_STATE_MIGRATION));
310         break;
311     case STATE_USER:
312         sName = String(WizardResId(STR_STATE_USER));
313         break;
314     case STATE_UPDATE_CHECK:
315         sName = String(WizardResId(STR_STATE_UPDATE_CHECK));
316         break;
317     }
318     return sName;
319 }
320 
321 sal_Bool FirstStartWizard::prepareLeaveCurrentState( CommitPageReason _eReason )
322 {
323     // the license acceptance is handled here, because it needs to change the state
324     // of the roadmap wizard which the page implementation does not know.
325     if (
326 		(_eReason              == eTravelForward) &&
327 		(getCurrentState()     == STATE_LICENSE ) &&
328 		(m_bLicenseWasAccepted == sal_False     )
329 	   )
330     {
331 		if (Migration::checkMigration())
332             enableState(FirstStartWizard::STATE_MIGRATION, sal_True);
333         if ( showOnlineUpdatePage() )
334             enableState(FirstStartWizard::STATE_UPDATE_CHECK, sal_True);
335 		enableState(FirstStartWizard::STATE_USER, sal_True);
336         enableState(FirstStartWizard::STATE_REGISTRATION, sal_True);
337 
338         storeAcceptDate();
339         m_bLicenseWasAccepted = sal_True;
340     }
341 
342     return svt::RoadmapWizard::prepareLeaveCurrentState(_eReason);
343 }
344 
345 sal_Bool FirstStartWizard::leaveState(WizardState)
346 {
347     if (( getCurrentState() == STATE_MIGRATION ) && m_bLicenseWasAccepted )
348     {
349         // Store accept date and patch level now as it has been
350         // overwritten by the migration process!
351         storeAcceptDate();
352         setPatchLevel();
353     }
354 
355     return sal_True;
356 }
357 
358 sal_Bool FirstStartWizard::onFinish()
359 {
360     return svt::RoadmapWizard::onFinish();
361 }
362 
363 short FirstStartWizard::Execute()
364 {
365     return svt::RoadmapWizard::Execute();
366 }
367 
368 static OUString _makeDateTimeString (const DateTime& aDateTime, sal_Bool bUTC = sal_False)
369 {
370     OStringBuffer aDateTimeString;
371     aDateTimeString.append((sal_Int32)aDateTime.GetYear());
372     aDateTimeString.append("-");
373     if (aDateTime.GetMonth()<10) aDateTimeString.append("0");
374     aDateTimeString.append((sal_Int32)aDateTime.GetMonth());
375     aDateTimeString.append("-");
376     if (aDateTime.GetDay()<10) aDateTimeString.append("0");
377     aDateTimeString.append((sal_Int32)aDateTime.GetDay());
378     aDateTimeString.append("T");
379     if (aDateTime.GetHour()<10) aDateTimeString.append("0");
380     aDateTimeString.append((sal_Int32)aDateTime.GetHour());
381     aDateTimeString.append(":");
382     if (aDateTime.GetMin()<10) aDateTimeString.append("0");
383     aDateTimeString.append((sal_Int32)aDateTime.GetMin());
384     aDateTimeString.append(":");
385     if (aDateTime.GetSec()<10) aDateTimeString.append("0");
386     aDateTimeString.append((sal_Int32)aDateTime.GetSec());
387     if (bUTC) aDateTimeString.append("Z");
388 
389     return OStringToOUString(aDateTimeString.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US);
390 }
391 
392 static OUString _getCurrentDateString()
393 {
394     OUString aString;
395     return _makeDateTimeString(DateTime());
396 }
397 
398 
399 static const OUString sConfigSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) );
400 static const OUString sAccessSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) );
401 static const OUString sReadSrvc  ( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationAccess" ) );
402 
403 void FirstStartWizard::storeAcceptDate()
404 {
405 
406     try {
407         Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
408         // get configuration provider
409         Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >(
410         xFactory->createInstance(sConfigSrvc), UNO_QUERY_THROW);
411         Sequence< Any > theArgs(1);
412         NamedValue v(OUString::createFromAscii("NodePath"),
413             makeAny(OUString::createFromAscii("org.openoffice.Setup/Office")));
414         theArgs[0] <<= v;
415         Reference< XPropertySet > pset = Reference< XPropertySet >(
416             theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW);
417         Any result = pset->getPropertyValue(OUString::createFromAscii("LicenseAcceptDate"));
418 
419         OUString aAcceptDate = _getCurrentDateString();
420         pset->setPropertyValue(OUString::createFromAscii("LicenseAcceptDate"), makeAny(aAcceptDate));
421         Reference< XChangesBatch >(pset, UNO_QUERY_THROW)->commitChanges();
422 
423 		// since the license is accepted the local user registry can be cleaned if required
424 		cleanOldOfficeRegKeys();
425     } catch (const Exception&)
426     {
427     }
428 
429 }
430 
431 void FirstStartWizard::setPatchLevel()
432 {
433     try {
434         Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
435         // get configuration provider
436         Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >(
437         xFactory->createInstance(sConfigSrvc), UNO_QUERY_THROW);
438         Sequence< Any > theArgs(1);
439         NamedValue v(OUString::createFromAscii("NodePath"),
440             makeAny(OUString::createFromAscii("org.openoffice.Office.Common/Help/Registration")));
441         theArgs[0] <<= v;
442         Reference< XPropertySet > pset = Reference< XPropertySet >(
443             theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW);
444         Any result = pset->getPropertyValue(OUString::createFromAscii("ReminderDate"));
445 
446         OUString aPatchLevel( RTL_CONSTASCII_USTRINGPARAM( "Patch" ));
447         aPatchLevel += OUString::valueOf( getBuildId(), 10 );
448         pset->setPropertyValue(OUString::createFromAscii("ReminderDate"), makeAny(aPatchLevel));
449         Reference< XChangesBatch >(pset, UNO_QUERY_THROW)->commitChanges();
450     } catch (const Exception&)
451     {
452     }
453 }
454 
455 #ifdef WNT
456 typedef int ( __stdcall * CleanCurUserRegProc ) ( wchar_t* );
457 #endif
458 
459 void FirstStartWizard::cleanOldOfficeRegKeys()
460 {
461 #ifdef WNT
462 	// after the wizard is completed clean OOo1.1.x entries in the current user registry if required
463 	// issue i47658
464 
465     OUString aBaseLocationPath;
466     OUString aSharedLocationPath;
467 	OUString aInstallMode;
468 
469 	::utl::Bootstrap::PathStatus aBaseLocateResult =
470         ::utl::Bootstrap::locateBaseInstallation( aBaseLocationPath );
471     ::utl::Bootstrap::PathStatus aSharedLocateResult =
472         ::utl::Bootstrap::locateSharedData( aSharedLocationPath );
473     aInstallMode = ::utl::Bootstrap::getAllUsersValue( ::rtl::OUString() );
474 
475 	// TODO: replace the checking for install mode
476     if ( aBaseLocateResult == ::utl::Bootstrap::PATH_EXISTS && aSharedLocateResult == ::utl::Bootstrap::PATH_EXISTS
477 	  && aInstallMode.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "1" ) ) ) )
478     {
479 		::rtl::OUString aDeregCompletePath =
480 					aBaseLocationPath + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/program/regcleanold.dll" ) );
481 		::rtl::OUString aExecCompletePath =
482 					aSharedLocationPath + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/regdeinstall/userdeinst.exe" ) );
483 
484 		osl::Module aCleanModule( aDeregCompletePath );
485 		CleanCurUserRegProc pNativeProc = ( CleanCurUserRegProc )(
486 					aCleanModule.getFunctionSymbol(
487 						::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CleanCurUserOldSystemRegistry" ) ) ) );
488 
489 		if( pNativeProc!=NULL )
490 		{
491 			::rtl::OUString aExecCompleteSysPath;
492 			if ( osl::File::getSystemPathFromFileURL( aExecCompletePath, aExecCompleteSysPath ) == FileBase::E_None
493 			  && aExecCompleteSysPath.getLength() )
494 			{
495 				( *pNativeProc )( (wchar_t*)( aExecCompleteSysPath.getStr() ) );
496 			}
497 		}
498 	}
499 #endif
500 }
501 
502 sal_Bool FirstStartWizard::showOnlineUpdatePage()
503 {
504     try {
505         Reference < XNameReplace > xUpdateAccess;
506         Reference < XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
507 
508         xUpdateAccess = Reference < XNameReplace >(
509             xFactory->createInstance( UNISTRING( "com.sun.star.setup.UpdateCheckConfig" ) ), UNO_QUERY_THROW );
510 
511         if ( xUpdateAccess.is() )
512         {
513             sal_Bool bAutoUpdChk = sal_False;
514             Any result = xUpdateAccess->getByName( UNISTRING( "AutoCheckEnabled" ) );
515             result >>= bAutoUpdChk;
516             if ( bAutoUpdChk == sal_False )
517                 return sal_True;
518             else
519                 return sal_False;
520         }
521     } catch (const Exception&)
522     {
523     }
524     return sal_False;
525 }
526 
527 }
528