1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: license.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
34 //_________________________________________________________________________________________________________________
36 //_________________________________________________________________________________________________________________
37 #include <services/license.hxx>
38 #include <threadhelp/resetableguard.hxx>
39 #include <macros/debug.hxx>
42 // local header for UI implementation
43 #include "services/licensedlg.hxx"
44 #include "classes/resource.hrc"
46 //_________________________________________________________________________________________________________________
48 //_________________________________________________________________________________________________________________
50 #include <com/sun/star/frame/XDesktop.hpp>
51 #include <com/sun/star/lang/XInitialization.hpp>
52 #include <com/sun/star/beans/XPropertySet.hpp>
53 #include <com/sun/star/uno/Any.hxx>
54 #include <com/sun/star/util/XChangesBatch.hpp>
55 #include <com/sun/star/beans/NamedValue.hpp>
56 #include <com/sun/star/lang/XComponent.hpp>
59 //_________________________________________________________________________________________________________________
60 // includes of other projects
61 //_________________________________________________________________________________________________________________
63 #include <rtl/ustrbuf.hxx>
64 #include <rtl/strbuf.hxx>
65 #include <rtl/ustring.hxx>
66 #include <rtl/string.hxx>
67 #include <unotools/bootstrap.hxx>
68 #include <osl/file.hxx>
69 #include <svtools/xtextedt.hxx>
70 #include <vcl/svapp.hxx>
71 #include <comphelper/processfactory.hxx>
72 #include <tools/date.hxx>
73 #include <tools/time.hxx>
74 #include <tools/datetime.hxx>
75 #include <osl/file.hxx>
78 //_________________________________________________________________________________________________________________
80 //_________________________________________________________________________________________________________________
84 using namespace ::osl
;
85 using namespace ::cppu
;
86 using namespace ::com::sun::star::uno
;
87 using namespace ::com::sun::star::beans
;
88 using namespace ::com::sun::star::lang
;
89 using namespace ::com::sun::star::util
;
90 using namespace ::com::sun::star::frame
;
92 //_________________________________________________________________________________________________________________
94 //_________________________________________________________________________________________________________________
97 static const char *szLicensePath
= "/share/readme";
99 static const char *szUNXLicenseName
= "/LICENSE";
100 static const char *szUNXLicenseExt
= "";
101 #elif defined(WNT) || defined(OS2)
102 static const char *szWNTLicenseName
= "/license";
103 static const char *szWNTLicenseExt
= ".txt";
106 //_________________________________________________________________________________________________________________
107 // non exported definitions
108 //_________________________________________________________________________________________________________________
110 //_________________________________________________________________________________________________________________
112 //_________________________________________________________________________________________________________________
114 //*****************************************************************************************************************
116 //*****************************************************************************************************************
117 License::License( const Reference
< XMultiServiceFactory
>& xFactory
)
118 // Init baseclasses first
120 // Don't change order of initialization!
121 // ThreadHelpBase is a struct with a mutex as member. We can't use a mutex as member, while
122 // we must garant right initialization and a valid value of this! First initialize
123 // baseclasses and then members. And we need the mutex for other baseclasses !!!
124 : ThreadHelpBase ( &Application::GetSolarMutex() )
127 , m_xFactory ( xFactory
)
128 , m_bTerminate ( sal_False
)
132 //*****************************************************************************************************************
134 //*****************************************************************************************************************
139 //*****************************************************************************************************************
140 // XInterface, XTypeProvider, XServiceInfo
141 //*****************************************************************************************************************
143 DEFINE_XINTERFACE_4 ( License
,
145 DIRECT_INTERFACE(XTypeProvider
),
146 DIRECT_INTERFACE(XServiceInfo
),
147 DIRECT_INTERFACE(XJob
),
148 DIRECT_INTERFACE(XCloseable
)
151 DEFINE_XTYPEPROVIDER_4 ( License
,
158 DEFINE_XSERVICEINFO_MULTISERVICE ( License
,
160 SERVICENAME_LICENSE
,
161 IMPLEMENTATIONNAME_LICENSE
164 DEFINE_INIT_SERVICE ( License
,
171 IMPL_STATIC_LINK_NOINSTANCE( License
, Terminate
, void*, EMPTYARG
)
174 Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
175 Reference< XDesktop > xDesktop(xFactory->createInstance(
176 ::rtl::OUString::createFromAscii("com.sun.star.frame.Desktop")), UNO_QUERY);
178 xDesktop->terminate();
187 static DateTime
_oslDateTimeToDateTime(const oslDateTime
& aDateTime
)
190 Date(aDateTime
.Day
, aDateTime
.Month
, aDateTime
.Year
),
191 Time(aDateTime
.Hours
, aDateTime
.Minutes
, aDateTime
.Seconds
));
194 static ::rtl::OUString
_makeDateTimeString (const DateTime
& aDateTime
, sal_Bool bUTC
= sal_False
)
196 ::rtl::OStringBuffer aDateTimeString
;
197 aDateTimeString
.append((sal_Int32
)aDateTime
.GetYear());
198 aDateTimeString
.append("-");
199 if (aDateTime
.GetMonth()<10) aDateTimeString
.append("0");
200 aDateTimeString
.append((sal_Int32
)aDateTime
.GetMonth());
201 aDateTimeString
.append("-");
202 if (aDateTime
.GetDay()<10) aDateTimeString
.append("0");
203 aDateTimeString
.append((sal_Int32
)aDateTime
.GetDay());
204 aDateTimeString
.append("T");
205 if (aDateTime
.GetHour()<10) aDateTimeString
.append("0");
206 aDateTimeString
.append((sal_Int32
)aDateTime
.GetHour());
207 aDateTimeString
.append(":");
208 if (aDateTime
.GetMin()<10) aDateTimeString
.append("0");
209 aDateTimeString
.append((sal_Int32
)aDateTime
.GetMin());
210 aDateTimeString
.append(":");
211 if (aDateTime
.GetSec()<10) aDateTimeString
.append("0");
212 aDateTimeString
.append((sal_Int32
)aDateTime
.GetSec());
213 if (bUTC
) aDateTimeString
.append("Z");
215 return OStringToOUString(aDateTimeString
.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US
);
218 static sal_Bool
_parseDateTime(const ::rtl::OUString
& aString
, DateTime
& aDateTime
)
220 // take apart a canonical literal xsd:dateTime string
221 //CCYY-MM-DDThh:mm:ss(Z)
223 ::rtl::OUString aDateTimeString
= aString
.trim();
226 if (aDateTimeString
.getLength() < 19 || aDateTimeString
.getLength() > 20)
229 sal_Int32 nDateLength
= 10;
230 sal_Int32 nTimeLength
= 8;
232 ::rtl::OUString aDateTimeSep
= ::rtl::OUString::createFromAscii("T");
233 ::rtl::OUString aDateSep
= ::rtl::OUString::createFromAscii("-");
234 ::rtl::OUString aTimeSep
= ::rtl::OUString::createFromAscii(":");
235 ::rtl::OUString aUTCString
= ::rtl::OUString::createFromAscii("Z");
237 ::rtl::OUString aDateString
= aDateTimeString
.copy(0, nDateLength
);
238 ::rtl::OUString aTimeString
= aDateTimeString
.copy(nDateLength
+1, nTimeLength
);
240 sal_Int32 nIndex
= 0;
241 sal_Int32 nYear
= aDateString
.getToken(0, '-', nIndex
).toInt32();
242 sal_Int32 nMonth
= aDateString
.getToken(0, '-', nIndex
).toInt32();
243 sal_Int32 nDay
= aDateString
.getToken(0, '-', nIndex
).toInt32();
245 sal_Int32 nHour
= aTimeString
.getToken(0, ':', nIndex
).toInt32();
246 sal_Int32 nMinute
= aTimeString
.getToken(0, ':', nIndex
).toInt32();
247 sal_Int32 nSecond
= aTimeString
.getToken(0, ':', nIndex
).toInt32();
249 Date
tmpDate((USHORT
)nDay
, (USHORT
)nMonth
, (USHORT
)nYear
);
250 Time
tmpTime(nHour
, nMinute
, nSecond
);
251 DateTime
tmpDateTime(tmpDate
, tmpTime
);
252 if (aString
.indexOf(aUTCString
) < 0)
253 tmpDateTime
.ConvertToUTC();
255 aDateTime
= tmpDateTime
;
259 static ::rtl::OUString
_getCurrentDateString()
261 ::rtl::OUString aString
;
262 return _makeDateTimeString(DateTime());
265 // execution of license check...
266 css::uno::Any SAL_CALL
License::execute(const css::uno::Sequence
< css::beans::NamedValue
>& )
267 throw( css::lang::IllegalArgumentException
, css::uno::Exception
)
270 Any aRet
; aRet
<<= sal_False
;
274 ::rtl::OUString aBaseInstallPath
;
275 Bootstrap::PathStatus aBaseLocateResult
=
276 Bootstrap::locateBaseInstallation(aBaseInstallPath
);
277 if (aBaseLocateResult
!= Bootstrap::PATH_EXISTS
)
279 // base install noit found
280 // prepare termination
281 // m_bTerminate = sal_True;
282 // Application::PostUserEvent( STATIC_LINK( 0, License, Terminate ) );
286 // determine the filename of the license to show
287 ::rtl::OUString aLangString
;
288 ::com::sun::star::lang::Locale aLocale
;
289 ::rtl::OString aMgrName
= ::rtl::OString("fwe");
290 AllSettings
aSettings(Application::GetSettings());
291 aLocale
= aSettings
.GetUILocale();
292 ResMgr
* pResMgr
= ResMgr::SearchCreateResMgr(aMgrName
, aLocale
);
294 aLangString
= aLocale
.Language
;
295 if ( aLocale
.Country
.getLength() != 0 )
297 aLangString
+= ::rtl::OUString::createFromAscii("-");
298 aLangString
+= aLocale
.Country
;
299 if ( aLocale
.Variant
.getLength() != 0 )
301 aLangString
+= ::rtl::OUString::createFromAscii("-");
302 aLangString
+= aLocale
.Variant
;
305 #if defined(WNT) || defined(OS2)
306 ::rtl::OUString aLicensePath
=
307 aBaseInstallPath
+ ::rtl::OUString::createFromAscii(szLicensePath
)
308 + ::rtl::OUString::createFromAscii(szWNTLicenseName
)
309 + ::rtl::OUString::createFromAscii("_")
311 + ::rtl::OUString::createFromAscii(szWNTLicenseExt
);
313 ::rtl::OUString aLicensePath
=
314 aBaseInstallPath
+ ::rtl::OUString::createFromAscii(szLicensePath
)
315 + ::rtl::OUString::createFromAscii(szUNXLicenseName
)
316 + ::rtl::OUString::createFromAscii("_")
318 + ::rtl::OUString::createFromAscii(szUNXLicenseExt
);
320 // check if we need to show the license at all
321 // open org.openoffice.Setup/Office/ooLicenseAcceptDate
322 ::rtl::OUString sConfigSrvc
= SERVICENAME_CFGPROVIDER
;
323 ::rtl::OUString sAccessSrvc
= ::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");
324 ::rtl::OUString sReadSrvc
= SERVICENAME_CFGREADACCESS
;
326 // get configuration provider
327 Reference
< XMultiServiceFactory
> theConfigProvider
= Reference
< XMultiServiceFactory
>(
328 m_xFactory
->createInstance(sConfigSrvc
), UNO_QUERY_THROW
);
329 Sequence
< Any
> theArgs(1);
331 v
.Name
= ::rtl::OUString::createFromAscii("NodePath");
332 v
.Value
<<= ::rtl::OUString::createFromAscii("org.openoffice.Setup/Office");
334 Reference
< XPropertySet
> pset
= Reference
< XPropertySet
>(
335 theConfigProvider
->createInstanceWithArguments(sAccessSrvc
, theArgs
), UNO_QUERY_THROW
);
337 // if we find a date there, compare it to baseinstall license date
338 ::rtl::OUString aAcceptDate
;
339 if (pset
->getPropertyValue(::rtl::OUString::createFromAscii("ooLicenseAcceptDate")) >>= aAcceptDate
)
341 // get LicenseFileDate from base install
342 ::rtl::OUString aLicenseURL
= aLicensePath
;
344 if (FileBase::getFileURLFromSystemPath(aLicensePath, aLicenseURL) != FileBase::E_None)
345 return makeAny(sal_False);
347 DirectoryItem aDirItem
;
348 if (DirectoryItem::get(aLicenseURL
, aDirItem
) != FileBase::E_None
)
349 return makeAny(sal_False
);
350 FileStatus
aStatus(FileStatusMask_All
);
351 if (aDirItem
.getFileStatus(aStatus
) != FileBase::E_None
)
352 return makeAny(sal_False
);
353 TimeValue aTimeVal
= aStatus
.getModifyTime();
354 oslDateTime aDateTimeVal
;
355 if (!osl_getDateTimeFromTimeValue(&aTimeVal
, &aDateTimeVal
))
356 return makeAny(sal_False
);
359 DateTime aLicenseDateTime
= _oslDateTimeToDateTime(aDateTimeVal
);
360 DateTime aAcceptDateTime
;
361 if (!_parseDateTime(aAcceptDate
, aAcceptDateTime
))
362 return makeAny(sal_False
);
364 if ( aAcceptDateTime
> aLicenseDateTime
)
365 return makeAny(sal_True
);
368 // display license dialog
369 LicenseDialog
* pDialog
= new LicenseDialog(aLicensePath
, pResMgr
);
370 sal_Bool bAgreed
= (pDialog
->Execute() == 1);
375 // write org.openoffice.Setup/ooLicenseAcceptDate
376 aAcceptDate
= _getCurrentDateString();
377 pset
->setPropertyValue(::rtl::OUString::createFromAscii("ooLicenseAcceptDate"), makeAny(aAcceptDate
));
378 Reference
< XChangesBatch
>(pset
, UNO_QUERY_THROW
)->commitChanges();
380 // enable quickstarter
381 sal_Bool
bQuickstart( sal_True
);
382 sal_Bool
bAutostart( sal_True
);
383 Sequence
< Any
> aSeq( 2 );
384 aSeq
[0] <<= bQuickstart
;
385 aSeq
[1] <<= bAutostart
;
387 Reference
< XInitialization
> xQuickstart( ::comphelper::getProcessServiceFactory()->createInstance(
388 ::rtl::OUString::createFromAscii( "com.sun.star.office.Quickstart" )),UNO_QUERY
);
389 if ( xQuickstart
.is() )
390 xQuickstart
->initialize( aSeq
);
396 // license was not accepted
397 // prepare termination
398 // m_bTerminate = sal_True;
399 // Application::PostUserEvent( STATIC_LINK( 0, License, Terminate ) );
403 catch (RuntimeException
&)
405 // license could not be verified
411 void SAL_CALL
License::close(sal_Bool
/*bDeliverOwnership*/) throw (css::util::CloseVetoException
)
414 throw CloseVetoException();
416 void SAL_CALL
License::addCloseListener(const css::uno::Reference
< css::util::XCloseListener
>&)
417 throw (css::uno::RuntimeException
)
420 void SAL_CALL
License::removeCloseListener(const css::uno::Reference
< css::util::XCloseListener
>&)
421 throw (css::uno::RuntimeException
)
426 //************************************************************************
428 //************************************************************************
430 LicenseDialog::LicenseDialog(const ::rtl::OUString
& aLicensePath
, ResMgr
*pResMgr
) :
431 ModalDialog(NULL
, ResId(DLG_LICENSE
, *pResMgr
)),
432 aLicenseML(this, ResId(ML_LICENSE
, *pResMgr
)),
433 aInfo1FT(this, ResId(FT_INFO1
, *pResMgr
)),
434 aInfo2FT(this, ResId(FT_INFO2
, *pResMgr
)),
435 aInfo3FT(this, ResId(FT_INFO3
, *pResMgr
)),
436 aInfo2_1FT(this, ResId(FT_INFO2_1
, *pResMgr
)),
437 aInfo3_1FT(this, ResId(FT_INFO3_1
, *pResMgr
)),
438 aFixedLine(this, ResId(FL_DIVIDE
, *pResMgr
)),
439 aPBPageDown(this, ResId(PB_PAGEDOWN
, *pResMgr
)),
440 aPBDecline( this, ResId(PB_DECLINE
, *pResMgr
) ),
441 aPBAccept( this, ResId(PB_ACCEPT
, *pResMgr
) ),
442 aArrow(this, ResId(IMG_ARROW
, *pResMgr
)),
443 aStrAccept( ResId(LICENSE_ACCEPT
, *pResMgr
) ),
444 aStrNotAccept( ResId(LICENSE_NOTACCEPT
, *pResMgr
) ),
449 aLicenseML
.SetEndReachedHdl( LINK(this, LicenseDialog
, EndReachedHdl
) );
450 aLicenseML
.SetScrolledHdl( LINK(this, LicenseDialog
, ScrolledHdl
) );
452 aPBPageDown
.SetClickHdl( LINK(this, LicenseDialog
, PageDownHdl
) );
453 aPBDecline
.SetClickHdl( LINK(this, LicenseDialog
, DeclineBtnHdl
) );
454 aPBAccept
.SetClickHdl( LINK(this, LicenseDialog
, AcceptBtnHdl
) );
456 // We want a automatic repeating page down button
457 WinBits aStyle
= aPBPageDown
.GetStyle();
459 aPBPageDown
.SetStyle( aStyle
);
461 String aText
= aInfo2FT
.GetText();
462 aText
.SearchAndReplaceAll( UniString::CreateFromAscii("%PAGEDOWN"), aPBPageDown
.GetText() );
463 aInfo2FT
.SetText( aText
);
465 aPBDecline
.SetText( aStrNotAccept
);
466 aPBAccept
.SetText( aStrAccept
);
471 File
aLicenseFile(aLicensePath
);
472 if ( aLicenseFile
.open(OpenFlag_Read
) == FileBase::E_None
)
475 DirectoryItem::get(aLicensePath
, d
);
476 FileStatus
fs(FileStatusMask_FileSize
);
478 sal_uInt64 nBytesRead
= 0;
479 sal_uInt64 nPosition
= 0;
480 sal_uInt32 nBytes
= (sal_uInt32
)fs
.getFileSize();
481 sal_Char
*pBuffer
= new sal_Char
[nBytes
];
482 // FileBase RC r = FileBase::E_None;
483 while (aLicenseFile
.read(pBuffer
+nPosition
, nBytes
-nPosition
, nBytesRead
) == FileBase::E_None
484 && nPosition
+ nBytesRead
< nBytes
)
486 nPosition
+= nBytesRead
;
488 ::rtl::OUString
aLicenseString(pBuffer
, nBytes
, RTL_TEXTENCODING_UTF8
,
489 OSTRING_TO_OUSTRING_CVTFLAGS
| RTL_TEXTTOUNICODE_FLAGS_GLOBAL_SIGNATURE
);
491 aLicenseML
.SetText(aLicenseString
);
496 LicenseDialog::~LicenseDialog()
500 IMPL_LINK( LicenseDialog
, PageDownHdl
, PushButton
*, EMPTYARG
)
502 aLicenseML
.ScrollDown( SCROLL_PAGEDOWN
);
506 IMPL_LINK( LicenseDialog
, EndReachedHdl
, LicenseView
*, EMPTYARG
)
515 IMPL_LINK( LicenseDialog
, ScrolledHdl
, LicenseView
*, EMPTYARG
)
522 IMPL_LINK( LicenseDialog
, DeclineBtnHdl
, PushButton
*, EMPTYARG
)
527 IMPL_LINK( LicenseDialog
, AcceptBtnHdl
, PushButton
*, EMPTYARG
)
534 void LicenseDialog::EnableControls()
537 ( aLicenseML
.IsEndReached() || !aLicenseML
.GetText().Len() ) )
542 Point
aPos( aInfo1FT
.GetPosPixel().X(),
543 aInfo3_1FT
.GetPosPixel().Y() );
544 aArrow
.SetPosPixel( aPos
);
549 Point
aPos( aInfo1FT
.GetPosPixel().X(),
550 aInfo2_1FT
.GetPosPixel().Y() );
551 aArrow
.SetPosPixel( aPos
);
555 if ( aLicenseML
.IsEndReached() )
556 aPBPageDown
.Disable();
558 aPBPageDown
.Enable();
563 LicenseView::LicenseView( Window
* pParent
, const ResId
& rResId
)
564 : MultiLineEdit( pParent
, rResId
)
568 mbEndReached
= IsEndReached();
570 StartListening( *GetTextEngine() );
573 LicenseView::~LicenseView()
575 maEndReachedHdl
= Link();
576 maScrolledHdl
= Link();
581 void LicenseView::ScrollDown( ScrollType eScroll
)
583 ScrollBar
* pScroll
= GetVScrollBar();
586 pScroll
->DoScrollAction( eScroll
);
589 BOOL
LicenseView::IsEndReached() const
593 ExtTextView
* pView
= GetTextView();
594 ExtTextEngine
* pEdit
= GetTextEngine();
595 ULONG nHeight
= pEdit
->GetTextHeight();
596 Size aOutSize
= pView
->GetWindow()->GetOutputSizePixel();
597 Point
aBottom( 0, aOutSize
.Height() );
599 if ( (ULONG
) pView
->GetDocPos( aBottom
).Y() >= nHeight
- 1 )
607 void LicenseView::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
609 if ( rHint
.IsA( TYPE(TextHint
) ) )
611 BOOL bLastVal
= EndReached();
612 ULONG nId
= ((const TextHint
&)rHint
).GetId();
614 if ( nId
== TEXT_HINT_PARAINSERTED
)
617 mbEndReached
= IsEndReached();
619 else if ( nId
== TEXT_HINT_VIEWSCROLLED
)
621 if ( ! mbEndReached
)
622 mbEndReached
= IsEndReached();
623 maScrolledHdl
.Call( this );
626 if ( EndReached() && !bLastVal
)
628 maEndReachedHdl
.Call( this );
633 } // namespace framework