blob: 4a86f29e13c1ee2a2d9f95d0b3d56acce01b11f4 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_framework.hxx"
//_________________________________________________________________________________________________________________
// my own includes
//_________________________________________________________________________________________________________________
#include <services/license.hxx>
#include <threadhelp/resetableguard.hxx>
#include <macros/debug.hxx>
#include <services.h>
// local header for UI implementation
#include "services/licensedlg.hxx"
#include "classes/resource.hrc"
//_________________________________________________________________________________________________________________
// interface includes
//_________________________________________________________________________________________________________________
#include <com/sun/star/frame/XDesktop.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/util/XChangesBatch.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/lang/XComponent.hpp>
//_________________________________________________________________________________________________________________
// includes of other projects
//_________________________________________________________________________________________________________________
#include <rtl/ustrbuf.hxx>
#include <rtl/strbuf.hxx>
#include <rtl/ustring.hxx>
#include <rtl/string.hxx>
#include <unotools/bootstrap.hxx>
#include <osl/file.hxx>
#include <svtools/xtextedt.hxx>
#include <vcl/svapp.hxx>
#include <comphelper/processfactory.hxx>
#include <tools/date.hxx>
#include <tools/time.hxx>
#include <tools/datetime.hxx>
#include <osl/file.hxx>
#include <osl/time.h>
//_________________________________________________________________________________________________________________
// namespace
//_________________________________________________________________________________________________________________
namespace framework{
using namespace utl;
using namespace ::osl ;
using namespace ::cppu ;
using namespace ::com::sun::star::uno ;
using namespace ::com::sun::star::beans ;
using namespace ::com::sun::star::lang ;
using namespace ::com::sun::star::util ;
using namespace ::com::sun::star::frame ;
//_________________________________________________________________________________________________________________
// non exported const
//_________________________________________________________________________________________________________________
// license file name
static const char *szLicensePath = "/share/readme";
#ifdef UNX
static const char *szUNXLicenseName = "/LICENSE";
static const char *szUNXLicenseExt = "";
#elif defined(WNT) || defined(OS2)
static const char *szWNTLicenseName = "/license";
static const char *szWNTLicenseExt = ".txt";
#endif
//_________________________________________________________________________________________________________________
// non exported definitions
//_________________________________________________________________________________________________________________
//_________________________________________________________________________________________________________________
// declarations
//_________________________________________________________________________________________________________________
//*****************************************************************************************************************
// constructor
//*****************************************************************************************************************
License::License( const Reference< XMultiServiceFactory >& xFactory )
// Init baseclasses first
// Attention:
// Don't change order of initialization!
// ThreadHelpBase is a struct with a mutex as member. We can't use a mutex as member, while
// we must garant right initialization and a valid value of this! First initialize
// baseclasses and then members. And we need the mutex for other baseclasses !!!
: ThreadHelpBase ( &Application::GetSolarMutex() )
, OWeakObject ( )
// Init member
, m_xFactory ( xFactory )
, m_bTerminate ( sal_False )
{
}
//*****************************************************************************************************************
// destructor
//*****************************************************************************************************************
License::~License()
{
}
//*****************************************************************************************************************
// XInterface, XTypeProvider, XServiceInfo
//*****************************************************************************************************************
DEFINE_XINTERFACE_4 ( License ,
OWeakObject ,
DIRECT_INTERFACE(XTypeProvider ),
DIRECT_INTERFACE(XServiceInfo ),
DIRECT_INTERFACE(XJob ),
DIRECT_INTERFACE(XCloseable )
)
DEFINE_XTYPEPROVIDER_4 ( License ,
XTypeProvider ,
XServiceInfo ,
XJob ,
XCloseable
)
DEFINE_XSERVICEINFO_MULTISERVICE ( License,
OWeakObject ,
SERVICENAME_LICENSE ,
IMPLEMENTATIONNAME_LICENSE
)
DEFINE_INIT_SERVICE ( License,
{
}
)
#if 0
IMPL_STATIC_LINK_NOINSTANCE( License, Terminate, void*, EMPTYARG )
{
/*
Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
Reference< XDesktop > xDesktop(xFactory->createInstance(
::rtl::OUString::createFromAscii("com.sun.star.frame.Desktop")), UNO_QUERY);
if (xDesktop.is())
xDesktop->terminate();
*/
/*
_exit(0);
*/
return 0;
}
#endif
static DateTime _oslDateTimeToDateTime(const oslDateTime& aDateTime)
{
return DateTime(
Date(aDateTime.Day, aDateTime.Month, aDateTime.Year),
Time(aDateTime.Hours, aDateTime.Minutes, aDateTime.Seconds));
}
static ::rtl::OUString _makeDateTimeString (const DateTime& aDateTime, sal_Bool bUTC = sal_False)
{
::rtl::OStringBuffer aDateTimeString;
aDateTimeString.append((sal_Int32)aDateTime.GetYear());
aDateTimeString.append("-");
if (aDateTime.GetMonth()<10) aDateTimeString.append("0");
aDateTimeString.append((sal_Int32)aDateTime.GetMonth());
aDateTimeString.append("-");
if (aDateTime.GetDay()<10) aDateTimeString.append("0");
aDateTimeString.append((sal_Int32)aDateTime.GetDay());
aDateTimeString.append("T");
if (aDateTime.GetHour()<10) aDateTimeString.append("0");
aDateTimeString.append((sal_Int32)aDateTime.GetHour());
aDateTimeString.append(":");
if (aDateTime.GetMin()<10) aDateTimeString.append("0");
aDateTimeString.append((sal_Int32)aDateTime.GetMin());
aDateTimeString.append(":");
if (aDateTime.GetSec()<10) aDateTimeString.append("0");
aDateTimeString.append((sal_Int32)aDateTime.GetSec());
if (bUTC) aDateTimeString.append("Z");
return OStringToOUString(aDateTimeString.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US);
}
static sal_Bool _parseDateTime(const ::rtl::OUString& aString, DateTime& aDateTime)
{
// take apart a canonical literal xsd:dateTime string
//CCYY-MM-DDThh:mm:ss(Z)
::rtl::OUString aDateTimeString = aString.trim();
// check length
if (aDateTimeString.getLength() < 19 || aDateTimeString.getLength() > 20)
return sal_False;
sal_Int32 nDateLength = 10;
sal_Int32 nTimeLength = 8;
::rtl::OUString aDateTimeSep = ::rtl::OUString::createFromAscii("T");
::rtl::OUString aDateSep = ::rtl::OUString::createFromAscii("-");
::rtl::OUString aTimeSep = ::rtl::OUString::createFromAscii(":");
::rtl::OUString aUTCString = ::rtl::OUString::createFromAscii("Z");
::rtl::OUString aDateString = aDateTimeString.copy(0, nDateLength);
::rtl::OUString aTimeString = aDateTimeString.copy(nDateLength+1, nTimeLength);
sal_Int32 nIndex = 0;
sal_Int32 nYear = aDateString.getToken(0, '-', nIndex).toInt32();
sal_Int32 nMonth = aDateString.getToken(0, '-', nIndex).toInt32();
sal_Int32 nDay = aDateString.getToken(0, '-', nIndex).toInt32();
nIndex = 0;
sal_Int32 nHour = aTimeString.getToken(0, ':', nIndex).toInt32();
sal_Int32 nMinute = aTimeString.getToken(0, ':', nIndex).toInt32();
sal_Int32 nSecond = aTimeString.getToken(0, ':', nIndex).toInt32();
Date tmpDate((sal_uInt16)nDay, (sal_uInt16)nMonth, (sal_uInt16)nYear);
Time tmpTime(nHour, nMinute, nSecond);
DateTime tmpDateTime(tmpDate, tmpTime);
if (aString.indexOf(aUTCString) < 0)
tmpDateTime.ConvertToUTC();
aDateTime = tmpDateTime;
return sal_True;
}
static ::rtl::OUString _getCurrentDateString()
{
::rtl::OUString aString;
return _makeDateTimeString(DateTime());
}
// execution of license check...
css::uno::Any SAL_CALL License::execute(const css::uno::Sequence< css::beans::NamedValue >& )
throw( css::lang::IllegalArgumentException, css::uno::Exception)
{
// return value
Any aRet; aRet <<= sal_False;
try
{
::rtl::OUString aBaseInstallPath;
Bootstrap::PathStatus aBaseLocateResult =
Bootstrap::locateBaseInstallation(aBaseInstallPath);
if (aBaseLocateResult != Bootstrap::PATH_EXISTS)
{
// base install noit found
// prepare termination
// m_bTerminate = sal_True;
// Application::PostUserEvent( STATIC_LINK( 0, License, Terminate ) );
aRet <<= sal_False;
return aRet;
}
// determine the filename of the license to show
::rtl::OUString aLangString;
::com::sun::star::lang::Locale aLocale;
::rtl::OString aMgrName = ::rtl::OString("fwe");
AllSettings aSettings(Application::GetSettings());
aLocale = aSettings.GetUILocale();
ResMgr* pResMgr = ResMgr::SearchCreateResMgr( aMgrName.getStr(), aLocale);
aLangString = aLocale.Language;
if ( aLocale.Country.getLength() != 0 )
{
aLangString += ::rtl::OUString::createFromAscii("-");
aLangString += aLocale.Country;
if ( aLocale.Variant.getLength() != 0 )
{
aLangString += ::rtl::OUString::createFromAscii("-");
aLangString += aLocale.Variant;
}
}
#if defined(WNT) || defined(OS2)
::rtl::OUString aLicensePath =
aBaseInstallPath + ::rtl::OUString::createFromAscii(szLicensePath)
+ ::rtl::OUString::createFromAscii(szWNTLicenseName)
+ ::rtl::OUString::createFromAscii("_")
+ aLangString
+ ::rtl::OUString::createFromAscii(szWNTLicenseExt);
#else
::rtl::OUString aLicensePath =
aBaseInstallPath + ::rtl::OUString::createFromAscii(szLicensePath)
+ ::rtl::OUString::createFromAscii(szUNXLicenseName)
+ ::rtl::OUString::createFromAscii("_")
+ aLangString
+ ::rtl::OUString::createFromAscii(szUNXLicenseExt);
#endif
// check if we need to show the license at all
// open org.openoffice.Setup/Office/ooLicenseAcceptDate
::rtl::OUString sConfigSrvc = SERVICENAME_CFGPROVIDER;
::rtl::OUString sAccessSrvc = ::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");
::rtl::OUString sReadSrvc = SERVICENAME_CFGREADACCESS;
// get configuration provider
Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >(
m_xFactory->createInstance(sConfigSrvc), UNO_QUERY_THROW);
Sequence< Any > theArgs(1);
NamedValue v;
v.Name = ::rtl::OUString::createFromAscii("NodePath");
v.Value <<= ::rtl::OUString::createFromAscii("org.openoffice.Setup/Office");
theArgs[0] <<= v;
Reference< XPropertySet > pset = Reference< XPropertySet >(
theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW);
// if we find a date there, compare it to baseinstall license date
::rtl::OUString aAcceptDate;
if (pset->getPropertyValue(::rtl::OUString::createFromAscii("ooLicenseAcceptDate")) >>= aAcceptDate)
{
// get LicenseFileDate from base install
::rtl::OUString aLicenseURL = aLicensePath;
/*
if (FileBase::getFileURLFromSystemPath(aLicensePath, aLicenseURL) != FileBase::E_None)
return makeAny(sal_False);
*/
DirectoryItem aDirItem;
if (DirectoryItem::get(aLicenseURL, aDirItem) != FileBase::E_None)
return makeAny(sal_False);
FileStatus aStatus(FileStatusMask_All);
if (aDirItem.getFileStatus(aStatus) != FileBase::E_None)
return makeAny(sal_False);
TimeValue aTimeVal = aStatus.getModifyTime();
oslDateTime aDateTimeVal;
if (!osl_getDateTimeFromTimeValue(&aTimeVal, &aDateTimeVal))
return makeAny(sal_False);
// compare dates
DateTime aLicenseDateTime = _oslDateTimeToDateTime(aDateTimeVal);
DateTime aAcceptDateTime;
if (!_parseDateTime(aAcceptDate, aAcceptDateTime))
return makeAny(sal_False);
if ( aAcceptDateTime > aLicenseDateTime )
return makeAny(sal_True);
}
// prepare to show
// display license dialog
LicenseDialog* pDialog = new LicenseDialog(aLicensePath, pResMgr);
sal_Bool bAgreed = (pDialog->Execute() == 1);
delete pDialog;
if (bAgreed) {
// write org.openoffice.Setup/ooLicenseAcceptDate
aAcceptDate = _getCurrentDateString();
pset->setPropertyValue(::rtl::OUString::createFromAscii("ooLicenseAcceptDate"), makeAny(aAcceptDate));
Reference< XChangesBatch >(pset, UNO_QUERY_THROW)->commitChanges();
// enable quickstarter
sal_Bool bQuickstart( sal_True );
sal_Bool bAutostart( sal_True );
Sequence< Any > aSeq( 2 );
aSeq[0] <<= bQuickstart;
aSeq[1] <<= bAutostart;
Reference < XInitialization > xQuickstart( ::comphelper::getProcessServiceFactory()->createInstance(
::rtl::OUString::createFromAscii( "com.sun.star.office.Quickstart" )),UNO_QUERY );
if ( xQuickstart.is() )
xQuickstart->initialize( aSeq );
aRet <<= sal_True;
}
else
{
// license was not accepted
// prepare termination
// m_bTerminate = sal_True;
// Application::PostUserEvent( STATIC_LINK( 0, License, Terminate ) );
aRet <<= sal_False;
}
}
catch (RuntimeException&)
{
// license could not be verified
aRet <<= sal_False;
}
return aRet;
}
void SAL_CALL License::close(sal_Bool /*bDeliverOwnership*/) throw (css::util::CloseVetoException)
{
if (!m_bTerminate)
throw CloseVetoException();
}
void SAL_CALL License::addCloseListener(const css::uno::Reference< css::util::XCloseListener >&)
throw (css::uno::RuntimeException)
{
}
void SAL_CALL License::removeCloseListener(const css::uno::Reference< css::util::XCloseListener >&)
throw (css::uno::RuntimeException)
{
}
//************************************************************************
// License Dialog
//************************************************************************
LicenseDialog::LicenseDialog(const ::rtl::OUString & aLicensePath, ResMgr *pResMgr) :
ModalDialog(NULL, ResId(DLG_LICENSE, *pResMgr)),
aLicenseML(this, ResId(ML_LICENSE, *pResMgr)),
aInfo1FT(this, ResId(FT_INFO1, *pResMgr)),
aInfo2FT(this, ResId(FT_INFO2, *pResMgr)),
aInfo3FT(this, ResId(FT_INFO3, *pResMgr)),
aInfo2_1FT(this, ResId(FT_INFO2_1, *pResMgr)),
aInfo3_1FT(this, ResId(FT_INFO3_1, *pResMgr)),
aFixedLine(this, ResId(FL_DIVIDE, *pResMgr)),
aPBPageDown(this, ResId(PB_PAGEDOWN, *pResMgr)),
aPBDecline( this, ResId(PB_DECLINE, *pResMgr) ),
aPBAccept( this, ResId(PB_ACCEPT, *pResMgr) ),
aArrow(this, ResId(IMG_ARROW, *pResMgr)),
aStrAccept( ResId(LICENSE_ACCEPT, *pResMgr) ),
aStrNotAccept( ResId(LICENSE_NOTACCEPT, *pResMgr) ),
bEndReached(sal_False)
{
FreeResource();
aLicenseML.SetEndReachedHdl( LINK(this, LicenseDialog, EndReachedHdl) );
aLicenseML.SetScrolledHdl( LINK(this, LicenseDialog, ScrolledHdl) );
aPBPageDown.SetClickHdl( LINK(this, LicenseDialog, PageDownHdl) );
aPBDecline.SetClickHdl( LINK(this, LicenseDialog, DeclineBtnHdl) );
aPBAccept.SetClickHdl( LINK(this, LicenseDialog, AcceptBtnHdl) );
// We want a automatic repeating page down button
WinBits aStyle = aPBPageDown.GetStyle();
aStyle |= WB_REPEAT;
aPBPageDown.SetStyle( aStyle );
String aText = aInfo2FT.GetText();
aText.SearchAndReplaceAll( UniString::CreateFromAscii("%PAGEDOWN"), aPBPageDown.GetText() );
aInfo2FT.SetText( aText );
aPBDecline.SetText( aStrNotAccept );
aPBAccept.SetText( aStrAccept );
aPBAccept.Disable();
// load license text
File aLicenseFile(aLicensePath);
if ( aLicenseFile.open(OpenFlag_Read) == FileBase::E_None)
{
DirectoryItem d;
DirectoryItem::get(aLicensePath, d);
FileStatus fs(FileStatusMask_FileSize);
d.getFileStatus(fs);
sal_uInt64 nBytesRead = 0;
sal_uInt64 nPosition = 0;
sal_uInt32 nBytes = (sal_uInt32)fs.getFileSize();
sal_Char *pBuffer = new sal_Char[nBytes];
// FileBase RC r = FileBase::E_None;
while (aLicenseFile.read(pBuffer+nPosition, nBytes-nPosition, nBytesRead) == FileBase::E_None
&& nPosition + nBytesRead < nBytes)
{
nPosition += nBytesRead;
}
::rtl::OUString aLicenseString(pBuffer, nBytes, RTL_TEXTENCODING_UTF8,
OSTRING_TO_OUSTRING_CVTFLAGS | RTL_TEXTTOUNICODE_FLAGS_GLOBAL_SIGNATURE);
delete[] pBuffer;
aLicenseML.SetText(aLicenseString);
}
}
LicenseDialog::~LicenseDialog()
{
}
IMPL_LINK( LicenseDialog, PageDownHdl, PushButton *, EMPTYARG )
{
aLicenseML.ScrollDown( SCROLL_PAGEDOWN );
return 0;
}
IMPL_LINK( LicenseDialog, EndReachedHdl, LicenseView *, EMPTYARG )
{
bEndReached = sal_True;
EnableControls();
return 0;
}
IMPL_LINK( LicenseDialog, ScrolledHdl, LicenseView *, EMPTYARG )
{
EnableControls();
return 0;
}
IMPL_LINK( LicenseDialog, DeclineBtnHdl, PushButton *, EMPTYARG )
{
EndDialog(0);
return 0;
}
IMPL_LINK( LicenseDialog, AcceptBtnHdl, PushButton *, EMPTYARG )
{
EndDialog(1);
return 0;
}
void LicenseDialog::EnableControls()
{
if( !bEndReached &&
( aLicenseML.IsEndReached() || !aLicenseML.GetText().Len() ) )
bEndReached = sal_True;
if ( bEndReached )
{
Point aPos( aInfo1FT.GetPosPixel().X(),
aInfo3_1FT.GetPosPixel().Y() );
aArrow.SetPosPixel( aPos );
aPBAccept.Enable();
}
else
{
Point aPos( aInfo1FT.GetPosPixel().X(),
aInfo2_1FT.GetPosPixel().Y() );
aArrow.SetPosPixel( aPos );
aPBAccept.Disable();
}
if ( aLicenseML.IsEndReached() )
aPBPageDown.Disable();
else
aPBPageDown.Enable();
}
LicenseView::LicenseView( Window* pParent, const ResId& rResId )
: MultiLineEdit( pParent, rResId )
{
SetLeftMargin( 5 );
mbEndReached = IsEndReached();
StartListening( *GetTextEngine() );
}
LicenseView::~LicenseView()
{
maEndReachedHdl = Link();
maScrolledHdl = Link();
EndListeningAll();
}
void LicenseView::ScrollDown( ScrollType eScroll )
{
ScrollBar* pScroll = GetVScrollBar();
if ( pScroll )
pScroll->DoScrollAction( eScroll );
}
sal_Bool LicenseView::IsEndReached() const
{
sal_Bool bEndReached;
ExtTextView* pView = GetTextView();
ExtTextEngine* pEdit = GetTextEngine();
sal_uLong nHeight = pEdit->GetTextHeight();
Size aOutSize = pView->GetWindow()->GetOutputSizePixel();
Point aBottom( 0, aOutSize.Height() );
if ( (sal_uLong) pView->GetDocPos( aBottom ).Y() >= nHeight - 1 )
bEndReached = sal_True;
else
bEndReached = sal_False;
return bEndReached;
}
void LicenseView::Notify( SfxBroadcaster&, const SfxHint& rHint )
{
if ( rHint.IsA( TYPE(TextHint) ) )
{
sal_Bool bLastVal = EndReached();
sal_uLong nId = ((const TextHint&)rHint).GetId();
if ( nId == TEXT_HINT_PARAINSERTED )
{
if ( bLastVal )
mbEndReached = IsEndReached();
}
else if ( nId == TEXT_HINT_VIEWSCROLLED )
{
if ( ! mbEndReached )
mbEndReached = IsEndReached();
maScrolledHdl.Call( this );
}
if ( EndReached() && !bLastVal )
{
maEndReachedHdl.Call( this );
}
}
}
} // namespace framework