Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <services/license.hxx>
21 : #include <threadhelp/resetableguard.hxx>
22 : #include <macros/debug.hxx>
23 : #include <services.h>
24 :
25 : // local header for UI implementation
26 : #include "services/licensedlg.hxx"
27 : #include "classes/resource.hrc"
28 :
29 : #include <com/sun/star/frame/XDesktop.hpp>
30 : #include <com/sun/star/lang/XInitialization.hpp>
31 : #include <com/sun/star/beans/XPropertySet.hpp>
32 : #include <com/sun/star/configuration/theDefaultProvider.hpp>
33 : #include <com/sun/star/uno/Any.hxx>
34 : #include <com/sun/star/util/XChangesBatch.hpp>
35 : #include <com/sun/star/office/Quickstart.hpp>
36 : #include <com/sun/star/beans/NamedValue.hpp>
37 : #include <com/sun/star/lang/XComponent.hpp>
38 :
39 : #include <rtl/ustrbuf.hxx>
40 : #include <rtl/strbuf.hxx>
41 : #include <rtl/ustring.hxx>
42 : #include <rtl/string.hxx>
43 : #include <unotools/bootstrap.hxx>
44 : #include <osl/file.hxx>
45 : #include <vcl/xtextedt.hxx>
46 : #include <vcl/svapp.hxx>
47 : #include <comphelper/processfactory.hxx>
48 : #include <tools/date.hxx>
49 : #include <tools/time.hxx>
50 : #include <tools/datetime.hxx>
51 : #include <osl/time.h>
52 :
53 : #include <boost/scoped_ptr.hpp>
54 :
55 : namespace framework{
56 : using namespace utl;
57 : using namespace ::osl ;
58 : using namespace ::cppu ;
59 : using namespace ::com::sun::star::uno ;
60 : using namespace ::com::sun::star::beans ;
61 : using namespace ::com::sun::star::configuration ;
62 : using namespace ::com::sun::star::lang ;
63 : using namespace ::com::sun::star::util ;
64 : using namespace ::com::sun::star::frame ;
65 :
66 : // license file name
67 : static const char *szLicensePath = "/share/readme";
68 : #ifdef UNX
69 : static const char *szUNXLicenseName = "/LICENSE";
70 : static const char *szUNXLicenseExt = "";
71 : #elif defined(WNT)
72 : static const char *szWNTLicenseName = "/license";
73 : static const char *szWNTLicenseExt = ".txt";
74 : #endif
75 :
76 : //*****************************************************************************************************************
77 : // constructor
78 : //*****************************************************************************************************************
79 0 : License::License( const Reference< XComponentContext >& rxContext )
80 : // Init baseclasses first
81 : // Attention:
82 : // Don't change order of initialization!
83 : // ThreadHelpBase is a struct with a mutex as member. We can't use a mutex as member, while
84 : // we must garant right initialization and a valid value of this! First initialize
85 : // baseclasses and then members. And we need the mutex for other baseclasses !!!
86 0 : : ThreadHelpBase ( &Application::GetSolarMutex() )
87 : , OWeakObject ( )
88 : // Init member
89 : , m_xContext ( rxContext )
90 0 : , m_bTerminate ( sal_False )
91 : {
92 0 : }
93 :
94 : //*****************************************************************************************************************
95 : // destructor
96 : //*****************************************************************************************************************
97 0 : License::~License()
98 : {
99 0 : }
100 :
101 : //*****************************************************************************************************************
102 : // XInterface, XTypeProvider, XServiceInfo
103 : //*****************************************************************************************************************
104 :
105 0 : DEFINE_XINTERFACE_4 ( License ,
106 : OWeakObject ,
107 : DIRECT_INTERFACE(XTypeProvider ),
108 : DIRECT_INTERFACE(XServiceInfo ),
109 : DIRECT_INTERFACE(XJob ),
110 : DIRECT_INTERFACE(XCloseable )
111 : )
112 :
113 0 : DEFINE_XTYPEPROVIDER_4 ( License ,
114 : XTypeProvider ,
115 : XServiceInfo ,
116 : XJob ,
117 : XCloseable
118 : )
119 :
120 42 : DEFINE_XSERVICEINFO_MULTISERVICE_2 ( License,
121 : OWeakObject ,
122 : SERVICENAME_LICENSE ,
123 : IMPLEMENTATIONNAME_LICENSE
124 : )
125 :
126 0 : DEFINE_INIT_SERVICE ( License,
127 : {
128 : }
129 : )
130 :
131 :
132 :
133 0 : static DateTime _oslDateTimeToDateTime(const oslDateTime& aDateTime)
134 : {
135 : return DateTime(
136 : Date(aDateTime.Day, aDateTime.Month, aDateTime.Year),
137 0 : Time(aDateTime.Hours, aDateTime.Minutes, aDateTime.Seconds));
138 : }
139 :
140 0 : static OUString _makeDateTimeString (const DateTime& aDateTime, sal_Bool bUTC = sal_False)
141 : {
142 0 : OStringBuffer aDateTimeString;
143 0 : aDateTimeString.append((sal_Int32)aDateTime.GetYear());
144 0 : aDateTimeString.append("-");
145 0 : if (aDateTime.GetMonth()<10) aDateTimeString.append("0");
146 0 : aDateTimeString.append((sal_Int32)aDateTime.GetMonth());
147 0 : aDateTimeString.append("-");
148 0 : if (aDateTime.GetDay()<10) aDateTimeString.append("0");
149 0 : aDateTimeString.append((sal_Int32)aDateTime.GetDay());
150 0 : aDateTimeString.append("T");
151 0 : if (aDateTime.GetHour()<10) aDateTimeString.append("0");
152 0 : aDateTimeString.append((sal_Int32)aDateTime.GetHour());
153 0 : aDateTimeString.append(":");
154 0 : if (aDateTime.GetMin()<10) aDateTimeString.append("0");
155 0 : aDateTimeString.append((sal_Int32)aDateTime.GetMin());
156 0 : aDateTimeString.append(":");
157 0 : if (aDateTime.GetSec()<10) aDateTimeString.append("0");
158 0 : aDateTimeString.append((sal_Int32)aDateTime.GetSec());
159 0 : if (bUTC) aDateTimeString.append("Z");
160 :
161 0 : return OStringToOUString(aDateTimeString.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US);
162 : }
163 :
164 0 : static sal_Bool _parseDateTime(const OUString& aString, DateTime& aDateTime)
165 : {
166 : // take apart a canonical literal xsd:dateTime string
167 : //CCYY-MM-DDThh:mm:ss(Z)
168 :
169 0 : OUString aDateTimeString = aString.trim();
170 :
171 : // check length
172 0 : if (aDateTimeString.getLength() < 19 || aDateTimeString.getLength() > 20)
173 0 : return sal_False;
174 :
175 0 : sal_Int32 nDateLength = 10;
176 0 : sal_Int32 nTimeLength = 8;
177 :
178 0 : OUString aUTCString("Z");
179 :
180 0 : OUString aDateString = aDateTimeString.copy(0, nDateLength);
181 0 : OUString aTimeString = aDateTimeString.copy(nDateLength+1, nTimeLength);
182 :
183 0 : sal_Int32 nIndex = 0;
184 0 : sal_Int32 nYear = aDateString.getToken(0, '-', nIndex).toInt32();
185 0 : sal_Int32 nMonth = aDateString.getToken(0, '-', nIndex).toInt32();
186 0 : sal_Int32 nDay = aDateString.getToken(0, '-', nIndex).toInt32();
187 0 : nIndex = 0;
188 0 : sal_Int32 nHour = aTimeString.getToken(0, ':', nIndex).toInt32();
189 0 : sal_Int32 nMinute = aTimeString.getToken(0, ':', nIndex).toInt32();
190 0 : sal_Int32 nSecond = aTimeString.getToken(0, ':', nIndex).toInt32();
191 :
192 0 : Date tmpDate((sal_uInt16)nDay, (sal_uInt16)nMonth, (sal_uInt16)nYear);
193 0 : Time tmpTime(nHour, nMinute, nSecond);
194 0 : DateTime tmpDateTime(tmpDate, tmpTime);
195 0 : if (aString.indexOf(aUTCString) < 0)
196 0 : tmpDateTime.ConvertToUTC();
197 :
198 0 : aDateTime = tmpDateTime;
199 0 : return sal_True;
200 : }
201 :
202 0 : static OUString _getCurrentDateString()
203 : {
204 0 : return _makeDateTimeString(DateTime( DateTime::SYSTEM));
205 : }
206 :
207 : // execution of license check...
208 0 : css::uno::Any SAL_CALL License::execute(const css::uno::Sequence< css::beans::NamedValue >& )
209 : throw( css::lang::IllegalArgumentException, css::uno::Exception)
210 : {
211 : // return value
212 0 : Any aRet; aRet <<= sal_False;
213 :
214 : try
215 : {
216 0 : OUString aBaseInstallPath;
217 : Bootstrap::PathStatus aBaseLocateResult =
218 0 : Bootstrap::locateBaseInstallation(aBaseInstallPath);
219 0 : if (aBaseLocateResult != Bootstrap::PATH_EXISTS)
220 : {
221 0 : aRet <<= sal_False;
222 0 : return aRet;
223 : }
224 :
225 : // determine the filename of the license to show
226 0 : OUString aLangString( Application::GetSettings().GetUILanguageTag().getBcp47());
227 : #if defined(WNT)
228 : OUString aLicensePath =
229 : aBaseInstallPath + OUString::createFromAscii(szLicensePath)
230 : + OUString::createFromAscii(szWNTLicenseName)
231 : + OUString("_")
232 : + aLangString
233 : + OUString::createFromAscii(szWNTLicenseExt);
234 : #else
235 : OUString aLicensePath =
236 0 : aBaseInstallPath + OUString::createFromAscii(szLicensePath)
237 0 : + OUString::createFromAscii(szUNXLicenseName)
238 0 : + OUString("_")
239 0 : + aLangString
240 0 : + OUString::createFromAscii(szUNXLicenseExt);
241 : #endif
242 : // check if we need to show the license at all
243 : // open org.openoffice.Setup/Office/ooLicenseAcceptDate
244 0 : OUString sAccessSrvc("com.sun.star.configuration.ConfigurationUpdateAccess");
245 :
246 : // get configuration provider
247 0 : Reference< XMultiServiceFactory > theConfigProvider = theDefaultProvider::get( m_xContext );
248 0 : Sequence< Any > theArgs(1);
249 0 : NamedValue v;
250 0 : v.Name = OUString("NodePath");
251 0 : v.Value <<= OUString("org.openoffice.Setup/Office");
252 0 : theArgs[0] <<= v;
253 : Reference< XPropertySet > pset = Reference< XPropertySet >(
254 0 : theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW);
255 :
256 : // if we find a date there, compare it to baseinstall license date
257 0 : OUString aAcceptDate;
258 0 : if (pset->getPropertyValue("ooLicenseAcceptDate") >>= aAcceptDate)
259 : {
260 : // get LicenseFileDate from base install
261 0 : OUString aLicenseURL = aLicensePath;
262 0 : DirectoryItem aDirItem;
263 0 : if (DirectoryItem::get(aLicenseURL, aDirItem) != FileBase::E_None)
264 0 : return makeAny(sal_False);
265 0 : FileStatus aStatus(osl_FileStatus_Mask_All);
266 0 : if (aDirItem.getFileStatus(aStatus) != FileBase::E_None)
267 0 : return makeAny(sal_False);
268 0 : TimeValue aTimeVal = aStatus.getModifyTime();
269 : oslDateTime aDateTimeVal;
270 0 : if (!osl_getDateTimeFromTimeValue(&aTimeVal, &aDateTimeVal))
271 0 : return makeAny(sal_False);
272 :
273 : // compare dates
274 0 : DateTime aLicenseDateTime = _oslDateTimeToDateTime(aDateTimeVal);
275 0 : DateTime aAcceptDateTime( DateTime::EMPTY);
276 0 : if (!_parseDateTime(aAcceptDate, aAcceptDateTime))
277 0 : return makeAny(sal_False);
278 :
279 0 : if ( aAcceptDateTime > aLicenseDateTime )
280 0 : return makeAny(sal_True);
281 : }
282 : // prepare to show
283 : // display license dialog
284 0 : LanguageTag aLanguageTag( Application::GetSettings().GetUILanguageTag());
285 0 : boost::scoped_ptr<ResMgr> pResMgr( ResMgr::SearchCreateResMgr("fwe", aLanguageTag));
286 0 : boost::scoped_ptr<LicenseDialog> pDialog(new LicenseDialog(aLicensePath, pResMgr.get()));
287 0 : sal_Bool bAgreed = (pDialog->Execute() == 1);
288 :
289 0 : if (bAgreed) {
290 :
291 : // write org.openoffice.Setup/ooLicenseAcceptDate
292 0 : aAcceptDate = _getCurrentDateString();
293 0 : pset->setPropertyValue("ooLicenseAcceptDate", makeAny(aAcceptDate));
294 0 : Reference< XChangesBatch >(pset, UNO_QUERY_THROW)->commitChanges();
295 :
296 : // enable quickstarter
297 :
298 0 : Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
299 0 : css::office::Quickstart::createAutoStart(xContext, true/*Quickstart*/, true/*Autostart*/);
300 :
301 0 : aRet <<= sal_True;
302 : }
303 : else
304 : {
305 0 : aRet <<= sal_False;
306 0 : }
307 : }
308 0 : catch (const RuntimeException&)
309 : {
310 : // license could not be verified
311 0 : aRet <<= sal_False;
312 : }
313 0 : return aRet;
314 : }
315 :
316 0 : void SAL_CALL License::close(sal_Bool /*bDeliverOwnership*/) throw (css::util::CloseVetoException)
317 : {
318 0 : if (!m_bTerminate)
319 0 : throw CloseVetoException();
320 0 : }
321 0 : void SAL_CALL License::addCloseListener(const css::uno::Reference< css::util::XCloseListener >&)
322 : throw (css::uno::RuntimeException)
323 : {
324 0 : }
325 0 : void SAL_CALL License::removeCloseListener(const css::uno::Reference< css::util::XCloseListener >&)
326 : throw (css::uno::RuntimeException)
327 : {
328 0 : }
329 :
330 :
331 : //************************************************************************
332 : // License Dialog
333 : //************************************************************************
334 :
335 0 : LicenseDialog::LicenseDialog(const OUString & aLicensePath, ResMgr *pResMgr) :
336 : ModalDialog(NULL, ResId(DLG_LICENSE, *pResMgr)),
337 : aLicenseML(this, ResId(ML_LICENSE, *pResMgr)),
338 : aInfo1FT(this, ResId(FT_INFO1, *pResMgr)),
339 : aInfo2FT(this, ResId(FT_INFO2, *pResMgr)),
340 : aInfo3FT(this, ResId(FT_INFO3, *pResMgr)),
341 : aInfo2_1FT(this, ResId(FT_INFO2_1, *pResMgr)),
342 : aInfo3_1FT(this, ResId(FT_INFO3_1, *pResMgr)),
343 : aFixedLine(this, ResId(FL_DIVIDE, *pResMgr)),
344 : aPBPageDown(this, ResId(PB_PAGEDOWN, *pResMgr)),
345 : aPBDecline( this, ResId(PB_DECLINE, *pResMgr) ),
346 : aPBAccept( this, ResId(PB_ACCEPT, *pResMgr) ),
347 : aArrow(this, ResId(IMG_ARROW, *pResMgr)),
348 : aStrAccept( ResId(LICENSE_ACCEPT, *pResMgr) ),
349 : aStrNotAccept( ResId(LICENSE_NOTACCEPT, *pResMgr) ),
350 0 : bEndReached(sal_False)
351 : {
352 0 : FreeResource();
353 :
354 0 : aLicenseML.SetEndReachedHdl( LINK(this, LicenseDialog, EndReachedHdl) );
355 0 : aLicenseML.SetScrolledHdl( LINK(this, LicenseDialog, ScrolledHdl) );
356 :
357 0 : aPBPageDown.SetClickHdl( LINK(this, LicenseDialog, PageDownHdl) );
358 0 : aPBDecline.SetClickHdl( LINK(this, LicenseDialog, DeclineBtnHdl) );
359 0 : aPBAccept.SetClickHdl( LINK(this, LicenseDialog, AcceptBtnHdl) );
360 :
361 : // We want a automatic repeating page down button
362 0 : WinBits aStyle = aPBPageDown.GetStyle();
363 0 : aStyle |= WB_REPEAT;
364 0 : aPBPageDown.SetStyle( aStyle );
365 :
366 0 : String aText = aInfo2FT.GetText();
367 0 : aText.SearchAndReplaceAll( OUString("%PAGEDOWN"), aPBPageDown.GetText() );
368 0 : aInfo2FT.SetText( aText );
369 :
370 0 : aPBDecline.SetText( aStrNotAccept );
371 0 : aPBAccept.SetText( aStrAccept );
372 :
373 0 : aPBAccept.Disable();
374 :
375 : // load license text
376 0 : File aLicenseFile(aLicensePath);
377 0 : if ( aLicenseFile.open(osl_File_OpenFlag_Read) == FileBase::E_None)
378 : {
379 0 : DirectoryItem d;
380 0 : DirectoryItem::get(aLicensePath, d);
381 0 : FileStatus fs(osl_FileStatus_Mask_FileSize);
382 0 : d.getFileStatus(fs);
383 0 : sal_uInt64 nBytesRead = 0;
384 0 : sal_uInt64 nPosition = 0;
385 0 : sal_uInt32 nBytes = (sal_uInt32)fs.getFileSize();
386 0 : sal_Char *pBuffer = new sal_Char[nBytes];
387 0 : while (aLicenseFile.read(pBuffer+nPosition, nBytes-nPosition, nBytesRead) == FileBase::E_None
388 0 : && nPosition + nBytesRead < nBytes)
389 : {
390 0 : nPosition += nBytesRead;
391 : }
392 : OUString aLicenseString(pBuffer, nBytes, RTL_TEXTENCODING_UTF8,
393 0 : OSTRING_TO_OUSTRING_CVTFLAGS | RTL_TEXTTOUNICODE_FLAGS_GLOBAL_SIGNATURE);
394 0 : delete[] pBuffer;
395 0 : aLicenseML.SetText(aLicenseString);
396 0 : }
397 :
398 0 : }
399 :
400 0 : LicenseDialog::~LicenseDialog()
401 : {
402 0 : }
403 :
404 0 : IMPL_LINK_NOARG(LicenseDialog, PageDownHdl)
405 : {
406 0 : aLicenseML.ScrollDown( SCROLL_PAGEDOWN );
407 0 : return 0;
408 : }
409 :
410 0 : IMPL_LINK_NOARG(LicenseDialog, EndReachedHdl)
411 : {
412 0 : bEndReached = sal_True;
413 :
414 0 : EnableControls();
415 :
416 0 : return 0;
417 : }
418 :
419 0 : IMPL_LINK_NOARG(LicenseDialog, ScrolledHdl)
420 : {
421 0 : EnableControls();
422 :
423 0 : return 0;
424 : }
425 :
426 0 : IMPL_LINK_NOARG(LicenseDialog, DeclineBtnHdl)
427 : {
428 0 : EndDialog(0);
429 0 : return 0;
430 : }
431 0 : IMPL_LINK_NOARG(LicenseDialog, AcceptBtnHdl)
432 : {
433 0 : EndDialog(1);
434 0 : return 0;
435 : }
436 :
437 :
438 0 : void LicenseDialog::EnableControls()
439 : {
440 0 : if( !bEndReached &&
441 0 : ( aLicenseML.IsEndReached() || aLicenseML.GetText().isEmpty() ) )
442 0 : bEndReached = sal_True;
443 :
444 0 : if ( bEndReached )
445 : {
446 0 : Point aPos( aInfo1FT.GetPosPixel().X(),
447 0 : aInfo3_1FT.GetPosPixel().Y() );
448 0 : aArrow.SetPosPixel( aPos );
449 0 : aPBAccept.Enable();
450 : }
451 : else
452 : {
453 0 : Point aPos( aInfo1FT.GetPosPixel().X(),
454 0 : aInfo2_1FT.GetPosPixel().Y() );
455 0 : aArrow.SetPosPixel( aPos );
456 0 : aPBAccept.Disable();
457 : }
458 :
459 0 : if ( aLicenseML.IsEndReached() )
460 0 : aPBPageDown.Disable();
461 : else
462 0 : aPBPageDown.Enable();
463 :
464 0 : }
465 :
466 :
467 0 : LicenseView::LicenseView( Window* pParent, const ResId& rResId )
468 0 : : MultiLineEdit( pParent, rResId )
469 : {
470 0 : SetLeftMargin( 5 );
471 :
472 0 : mbEndReached = IsEndReached();
473 :
474 0 : StartListening( *GetTextEngine() );
475 0 : }
476 :
477 0 : LicenseView::~LicenseView()
478 : {
479 0 : maEndReachedHdl = Link();
480 0 : maScrolledHdl = Link();
481 :
482 0 : EndListeningAll();
483 0 : }
484 :
485 0 : void LicenseView::ScrollDown( ScrollType eScroll )
486 : {
487 0 : ScrollBar* pScroll = GetVScrollBar();
488 :
489 0 : if ( pScroll )
490 0 : pScroll->DoScrollAction( eScroll );
491 0 : }
492 :
493 0 : sal_Bool LicenseView::IsEndReached() const
494 : {
495 : sal_Bool bEndReached;
496 :
497 0 : ExtTextView* pView = GetTextView();
498 0 : ExtTextEngine* pEdit = GetTextEngine();
499 0 : sal_uLong nHeight = pEdit->GetTextHeight();
500 0 : Size aOutSize = pView->GetWindow()->GetOutputSizePixel();
501 0 : Point aBottom( 0, aOutSize.Height() );
502 :
503 0 : if ( (sal_uLong) pView->GetDocPos( aBottom ).Y() >= nHeight - 1 )
504 0 : bEndReached = sal_True;
505 : else
506 0 : bEndReached = sal_False;
507 :
508 0 : return bEndReached;
509 : }
510 :
511 0 : void LicenseView::Notify( SfxBroadcaster&, const SfxHint& rHint )
512 : {
513 0 : if ( rHint.IsA( TYPE(TextHint) ) )
514 : {
515 0 : sal_Bool bLastVal = EndReached();
516 0 : sal_uLong nId = ((const TextHint&)rHint).GetId();
517 :
518 0 : if ( nId == TEXT_HINT_PARAINSERTED )
519 : {
520 0 : if ( bLastVal )
521 0 : mbEndReached = IsEndReached();
522 : }
523 0 : else if ( nId == TEXT_HINT_VIEWSCROLLED )
524 : {
525 0 : if ( ! mbEndReached )
526 0 : mbEndReached = IsEndReached();
527 0 : maScrolledHdl.Call( this );
528 : }
529 :
530 0 : if ( EndReached() && !bLastVal )
531 : {
532 0 : maEndReachedHdl.Call( this );
533 : }
534 : }
535 0 : }
536 :
537 90 : } // namespace framework
538 :
539 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|