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, WizardResId(DLG_FIRSTSTART_WIZARD),
120         WZB_NEXT|WZB_PREVIOUS|WZB_FINISH|WZB_CANCEL|WZB_HELP)
121     ,m_bOverride(sal_False)
122     ,m_aDefaultPath(0)
123 	,m_aMigrationPath(0)
124     ,m_bDone(sal_False)
125 	,m_bLicenseNeedsAcceptance( bLicenseNeedsAcceptance )
126     ,m_bLicenseWasAccepted(sal_False)
127     ,m_bAutomaticUpdChk(sal_True)
128     ,m_aThrobber(this, WizardResId(CTRL_THROBBER))
129     ,m_aLicensePath( rLicensePath )
130 {
131     FreeResource();
132     // ---
133 //	enableState(STATE_USER, sal_False);
134 //  enableState(STATE_REGISTRATION, sal_False);
135 
136     Size aTPSize(TP_WIDTH, TP_HEIGHT);
137     SetPageSizePixel(LogicToPixel(aTPSize, MAP_APPFONT));
138 
139     //set help id
140     m_pPrevPage->SetHelpId(HID_FIRSTSTART_PREV);
141     m_pNextPage->SetHelpId(HID_FIRSTSTART_NEXT);
142     m_pCancel->SetHelpId(HID_FIRSTSTART_CANCEL);
143     m_pFinish->SetHelpId(HID_FIRSTSTART_FINISH);
144     // m_pHelp->SetUniqueId(UID_FIRSTSTART_HELP);
145     m_pHelp->Hide();
146     m_pHelp->Disable();
147 
148     // save button lables
149     m_sNext = m_pNextPage->GetText();
150     m_sCancel = m_pCancel->GetText();
151 
152     // save cancel click handler
153     m_lnkCancel = m_pCancel->GetClickHdl();
154 
155     m_aDefaultPath = defineWizardPagesDependingFromContext();
156 	activatePath(m_aDefaultPath, sal_True);
157 
158     ActivatePage();
159 
160     // set text of finish putton:
161     m_pFinish->SetText(String(WizardResId(STR_FINISH)));
162     // disable "finish button"
163     enableButtons(WZB_FINISH, sal_False);
164     defaultButton(WZB_NEXT);
165 }
166 
167 void FirstStartWizard::DisableButtonsWhileMigration()
168 {
169     enableButtons(0xff, sal_False);
170 }
171 
172 ::svt::RoadmapWizardTypes::PathId FirstStartWizard::defineWizardPagesDependingFromContext()
173 {
174 	::svt::RoadmapWizardTypes::PathId aDefaultPath = 0;
175 
176     sal_Bool bPage_Welcome      = sal_True;
177     sal_Bool bPage_Migration    = sal_True;
178     sal_Bool bPage_User         = sal_True;
179     sal_Bool bPage_UpdateCheck  = sal_True;
180 
181     bPage_Migration   = Migration::checkMigration();
182     bPage_UpdateCheck = showOnlineUpdatePage();
183 
184     WizardPath aPath;
185     if (bPage_Welcome)
186         aPath.push_back(STATE_WELCOME);
187     if (bPage_Migration)
188         aPath.push_back(STATE_MIGRATION);
189     if (bPage_User)
190         aPath.push_back(STATE_USER);
191     if (bPage_UpdateCheck)
192         aPath.push_back(STATE_UPDATE_CHECK);
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     if (bPage_User)
204         enableState(STATE_USER, bAllowDirectLink);
205     if (bPage_UpdateCheck)
206         enableState(STATE_UPDATE_CHECK, bAllowDirectLink);
207     if (bPage_Migration)
208         enableState(STATE_MIGRATION, bAllowDirectLink);
209 
210 	return aDefaultPath;
211 }
212 
213 // catch F1 and disable help
214 long FirstStartWizard::PreNotify( NotifyEvent& rNEvt )
215 {
216     if( rNEvt.GetType() == EVENT_KEYINPUT )
217     {
218         const KeyCode& rKey = rNEvt.GetKeyEvent()->GetKeyCode();
219         if( rKey.GetCode() == KEY_F1 && ! rKey.GetModifier() )
220             return sal_True;
221     }
222     return RoadmapWizard::PreNotify(rNEvt);
223 }
224 
225 
226 void FirstStartWizard::enterState(WizardState _nState)
227 {
228     RoadmapWizard::enterState(_nState);
229     // default state
230     // all on
231     enableButtons(0xff, sal_True);
232     // finish off
233     enableButtons(WZB_FINISH, sal_False);
234     // default text
235     m_pCancel->SetText(m_sCancel);
236     m_pCancel->SetClickHdl(m_lnkCancel);
237     m_pNextPage->SetText(m_sNext);
238 
239     // default
240     defaultButton(WZB_NEXT);
241 
242     // specialized state
243     switch (_nState)
244     {
245     case STATE_WELCOME:
246         enableButtons(WZB_PREVIOUS, sal_False);
247         break;
248     case STATE_LICENSE:
249         m_pCancel->SetText(String(WizardResId(STR_LICENSE_DECLINE)));
250         m_pNextPage->SetText(String(WizardResId(STR_LICENSE_ACCEPT)));
251         enableButtons(WZB_NEXT, sal_False);
252         // attach warning dialog to cancel/decline button
253         m_pCancel->SetClickHdl( LINK(this, FirstStartWizard, DeclineHdl) );
254         break;
255     case STATE_REGISTRATION:
256         enableButtons(WZB_NEXT, sal_False);
257         enableButtons(WZB_FINISH, sal_True);
258         defaultButton(WZB_FINISH);
259         break;
260     }
261 
262     // focus
263 
264 }
265 
266 IMPL_LINK( FirstStartWizard, DeclineHdl, PushButton *, EMPTYARG )
267 {
268     QueryBox aBox(this, WizardResId(QB_ASK_DECLINE));
269     sal_Int32 ret = aBox.Execute();
270     if ( ret == BUTTON_OK || ret == BUTTON_YES)
271     {
272         Close();
273         return sal_False;
274     }
275     else
276         return sal_True;
277 }
278 
279 
280 TabPage* FirstStartWizard::createPage(WizardState _nState)
281 {
282     TabPage *pTabPage = 0;
283     switch (_nState)
284     {
285     case STATE_WELCOME:
286         pTabPage = new WelcomePage(this, WizardResId(TP_WELCOME), m_bLicenseNeedsAcceptance);
287         break;
288     case STATE_MIGRATION:
289         pTabPage = new MigrationPage(this, WizardResId(TP_MIGRATION), m_aThrobber);
290         break;
291     case STATE_USER:
292         pTabPage = new UserPage(this, WizardResId(TP_USER));
293         break;
294     case STATE_UPDATE_CHECK:
295         pTabPage = new UpdateCheckPage(this, WizardResId(TP_UPDATE_CHECK));
296         break;
297     }
298     pTabPage->Show();
299 
300     return pTabPage;
301 }
302 
303 String FirstStartWizard::getStateDisplayName( WizardState _nState ) const
304 {
305     String sName;
306     switch(_nState)
307     {
308     case STATE_WELCOME:
309         sName = String(WizardResId(STR_STATE_WELCOME));
310         break;
311     case STATE_MIGRATION:
312         sName = String(WizardResId(STR_STATE_MIGRATION));
313         break;
314     case STATE_USER:
315         sName = String(WizardResId(STR_STATE_USER));
316         break;
317     case STATE_UPDATE_CHECK:
318         sName = String(WizardResId(STR_STATE_UPDATE_CHECK));
319         break;
320     }
321     return sName;
322 }
323 
324 sal_Bool FirstStartWizard::prepareLeaveCurrentState( CommitPageReason _eReason )
325 {
326     // the license acceptance is handled here, because it needs to change the state
327     // of the roadmap wizard which the page implementation does not know.
328     if (
329 		(_eReason              == eTravelForward) &&
330 		(getCurrentState()     == STATE_LICENSE ) &&
331 		(m_bLicenseWasAccepted == sal_False     )
332 	   )
333     {
334 		if (Migration::checkMigration())
335             enableState(FirstStartWizard::STATE_MIGRATION, sal_True);
336         if ( showOnlineUpdatePage() )
337             enableState(FirstStartWizard::STATE_UPDATE_CHECK, sal_True);
338 		enableState(FirstStartWizard::STATE_USER, sal_True);
339         enableState(FirstStartWizard::STATE_REGISTRATION, sal_True);
340 
341         storeAcceptDate();
342         m_bLicenseWasAccepted = sal_True;
343     }
344 
345     return svt::RoadmapWizard::prepareLeaveCurrentState(_eReason);
346 }
347 
348 sal_Bool FirstStartWizard::leaveState(WizardState)
349 {
350     if (( getCurrentState() == STATE_MIGRATION ) && m_bLicenseWasAccepted )
351     {
352         // Store accept date and patch level now as it has been
353         // overwritten by the migration process!
354         storeAcceptDate();
355         setPatchLevel();
356     }
357 
358     return sal_True;
359 }
360 
361 sal_Bool FirstStartWizard::onFinish()
362 {
363     return svt::RoadmapWizard::onFinish();
364 }
365 
366 short FirstStartWizard::Execute()
367 {
368     return svt::RoadmapWizard::Execute();
369 }
370 
371 static OUString _makeDateTimeString (const DateTime& aDateTime, sal_Bool bUTC = sal_False)
372 {
373     OStringBuffer aDateTimeString;
374     aDateTimeString.append((sal_Int32)aDateTime.GetYear());
375     aDateTimeString.append("-");
376     if (aDateTime.GetMonth()<10) aDateTimeString.append("0");
377     aDateTimeString.append((sal_Int32)aDateTime.GetMonth());
378     aDateTimeString.append("-");
379     if (aDateTime.GetDay()<10) aDateTimeString.append("0");
380     aDateTimeString.append((sal_Int32)aDateTime.GetDay());
381     aDateTimeString.append("T");
382     if (aDateTime.GetHour()<10) aDateTimeString.append("0");
383     aDateTimeString.append((sal_Int32)aDateTime.GetHour());
384     aDateTimeString.append(":");
385     if (aDateTime.GetMin()<10) aDateTimeString.append("0");
386     aDateTimeString.append((sal_Int32)aDateTime.GetMin());
387     aDateTimeString.append(":");
388     if (aDateTime.GetSec()<10) aDateTimeString.append("0");
389     aDateTimeString.append((sal_Int32)aDateTime.GetSec());
390     if (bUTC) aDateTimeString.append("Z");
391 
392     return OStringToOUString(aDateTimeString.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US);
393 }
394 
395 static OUString _getCurrentDateString()
396 {
397     OUString aString;
398     return _makeDateTimeString(DateTime());
399 }
400 
401 
402 static const OUString sConfigSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) );
403 static const OUString sAccessSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) );
404 static const OUString sReadSrvc  ( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationAccess" ) );
405 
406 void FirstStartWizard::storeAcceptDate()
407 {
408 
409     try {
410         Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
411         // get configuration provider
412         Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >(
413         xFactory->createInstance(sConfigSrvc), UNO_QUERY_THROW);
414         Sequence< Any > theArgs(1);
415         NamedValue v(OUString::createFromAscii("NodePath"),
416             makeAny(OUString::createFromAscii("org.openoffice.Setup/Office")));
417         theArgs[0] <<= v;
418         Reference< XPropertySet > pset = Reference< XPropertySet >(
419             theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW);
420         Any result = pset->getPropertyValue(OUString::createFromAscii("LicenseAcceptDate"));
421 
422         OUString aAcceptDate = _getCurrentDateString();
423         pset->setPropertyValue(OUString::createFromAscii("LicenseAcceptDate"), makeAny(aAcceptDate));
424         Reference< XChangesBatch >(pset, UNO_QUERY_THROW)->commitChanges();
425 
426 		// since the license is accepted the local user registry can be cleaned if required
427 		cleanOldOfficeRegKeys();
428     } catch (const Exception&)
429     {
430     }
431 
432 }
433 
434 void FirstStartWizard::setPatchLevel()
435 {
436     try {
437         Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
438         // get configuration provider
439         Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >(
440         xFactory->createInstance(sConfigSrvc), UNO_QUERY_THROW);
441         Sequence< Any > theArgs(1);
442         NamedValue v(OUString::createFromAscii("NodePath"),
443             makeAny(OUString::createFromAscii("org.openoffice.Office.Common/Help/Registration")));
444         theArgs[0] <<= v;
445         Reference< XPropertySet > pset = Reference< XPropertySet >(
446             theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW);
447         Any result = pset->getPropertyValue(OUString::createFromAscii("ReminderDate"));
448 
449         OUString aPatchLevel( RTL_CONSTASCII_USTRINGPARAM( "Patch" ));
450         aPatchLevel += OUString::valueOf( getBuildId(), 10 );
451         pset->setPropertyValue(OUString::createFromAscii("ReminderDate"), makeAny(aPatchLevel));
452         Reference< XChangesBatch >(pset, UNO_QUERY_THROW)->commitChanges();
453     } catch (const Exception&)
454     {
455     }
456 }
457 
458 #ifdef WNT
459 typedef int ( __stdcall * CleanCurUserRegProc ) ( wchar_t* );
460 #endif
461 
462 void FirstStartWizard::cleanOldOfficeRegKeys()
463 {
464 #ifdef WNT
465 	// after the wizard is completed clean OOo1.1.x entries in the current user registry if required
466 	// issue i47658
467 
468     OUString aBaseLocationPath;
469     OUString aSharedLocationPath;
470 	OUString aInstallMode;
471 
472 	::utl::Bootstrap::PathStatus aBaseLocateResult =
473         ::utl::Bootstrap::locateBaseInstallation( aBaseLocationPath );
474     ::utl::Bootstrap::PathStatus aSharedLocateResult =
475         ::utl::Bootstrap::locateSharedData( aSharedLocationPath );
476     aInstallMode = ::utl::Bootstrap::getAllUsersValue( ::rtl::OUString() );
477 
478 	// TODO: replace the checking for install mode
479     if ( aBaseLocateResult == ::utl::Bootstrap::PATH_EXISTS && aSharedLocateResult == ::utl::Bootstrap::PATH_EXISTS
480 	  && aInstallMode.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "1" ) ) ) )
481     {
482 		::rtl::OUString aDeregCompletePath =
483 					aBaseLocationPath + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/program/regcleanold.dll" ) );
484 		::rtl::OUString aExecCompletePath =
485 					aSharedLocationPath + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/regdeinstall/userdeinst.exe" ) );
486 
487 		osl::Module aCleanModule( aDeregCompletePath );
488 		CleanCurUserRegProc pNativeProc = ( CleanCurUserRegProc )(
489 					aCleanModule.getFunctionSymbol(
490 						::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CleanCurUserOldSystemRegistry" ) ) ) );
491 
492 		if( pNativeProc!=NULL )
493 		{
494 			::rtl::OUString aExecCompleteSysPath;
495 			if ( osl::File::getSystemPathFromFileURL( aExecCompletePath, aExecCompleteSysPath ) == FileBase::E_None
496 			  && aExecCompleteSysPath.getLength() )
497 			{
498 				( *pNativeProc )( (wchar_t*)( aExecCompleteSysPath.getStr() ) );
499 			}
500 		}
501 	}
502 #endif
503 }
504 
505 sal_Bool FirstStartWizard::showOnlineUpdatePage()
506 {
507     try {
508         Reference < XNameReplace > xUpdateAccess;
509         Reference < XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
510 
511         xUpdateAccess = Reference < XNameReplace >(
512             xFactory->createInstance( UNISTRING( "com.sun.star.setup.UpdateCheckConfig" ) ), UNO_QUERY_THROW );
513 
514         if ( xUpdateAccess.is() )
515         {
516             sal_Bool bAutoUpdChk = sal_False;
517             Any result = xUpdateAccess->getByName( UNISTRING( "AutoCheckEnabled" ) );
518             result >>= bAutoUpdChk;
519             if ( bAutoUpdChk == sal_False )
520                 return sal_True;
521             else
522                 return sal_False;
523         }
524     } catch (const Exception&)
525     {
526     }
527     return sal_False;
528 }
529 
530 }
531