/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include "personalization.hxx" #include "personasdochandler.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cuires.hrc" #include #include #include #include "ucbhelper/content.hxx" using namespace com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::ucb; using namespace ::com::sun::star::beans; SelectPersonaDialog::SelectPersonaDialog( vcl::Window *pParent ) : ModalDialog( pParent, "SelectPersonaDialog", "cui/ui/select_persona_dialog.ui" ) { get( m_pSearchButton, "search_personas" ); m_pSearchButton->SetClickHdl( LINK( this, SelectPersonaDialog, SearchPersonas ) ); get( m_vSearchSuggestions[0], "suggestion1" ); m_vSearchSuggestions[0]->SetText( "LibreOffice" ); m_vSearchSuggestions[0]->SetClickHdl( LINK( this, SelectPersonaDialog, SearchPersonas ) ); get( m_vSearchSuggestions[1], "suggestion2" ); m_vSearchSuggestions[1]->SetText( "Abstract" ); m_vSearchSuggestions[1]->SetClickHdl( LINK( this, SelectPersonaDialog, SearchPersonas ) ); get( m_vSearchSuggestions[2], "suggestion3" ); m_vSearchSuggestions[2]->SetText( "Color" ); m_vSearchSuggestions[2]->SetClickHdl( LINK( this, SelectPersonaDialog, SearchPersonas ) ); get( m_vSearchSuggestions[3], "suggestion4" ); m_vSearchSuggestions[3]->SetText( "Music" ); m_vSearchSuggestions[3]->SetClickHdl( LINK( this, SelectPersonaDialog, SearchPersonas ) ); get( m_vSearchSuggestions[4], "suggestion5" ); m_vSearchSuggestions[4]->SetText( "Nature" ); m_vSearchSuggestions[4]->SetClickHdl( LINK( this, SelectPersonaDialog, SearchPersonas ) ); get( m_pEdit, "search_term" ); m_pEdit->SetPlaceholderText( CUI_RES( RID_SVXSTR_SEARCHTERM ) ); get( m_pProgressLabel, "progress_label" ); get( m_pOkButton, "ok" ); m_pOkButton->SetClickHdl( LINK( this, SelectPersonaDialog, ActionOK ) ); get( m_pCancelButton, "cancel" ); m_pCancelButton->SetClickHdl( LINK( this, SelectPersonaDialog, ActionCancel ) ); get( m_vResultList[0], "result1" ); get( m_vResultList[1], "result2" ); get( m_vResultList[2], "result3" ); get( m_vResultList[3], "result4" ); get( m_vResultList[4], "result5" ); get( m_vResultList[5], "result6" ); get( m_vResultList[6], "result7" ); get( m_vResultList[7], "result8" ); get( m_vResultList[8], "result9" ); for (sal_Int32 nIndex = 0; nIndex < 9; ++nIndex) { m_vResultList[nIndex]->SetClickHdl( LINK( this, SelectPersonaDialog, SelectPersona ) ); m_vResultList[nIndex]->Disable(); } } OUString SelectPersonaDialog::GetSelectedPersona() const { if( !m_aSelectedPersona.isEmpty( ) ) return m_aSelectedPersona; return OUString(); } IMPL_LINK( SelectPersonaDialog, SearchPersonas, PushButton*, pButton ) { OUString searchTerm; if( m_rSearchThread.is() ) m_rSearchThread->StopExecution(); if( pButton == m_pSearchButton ) searchTerm = m_pEdit->GetText(); else { for( sal_Int32 nIndex = 0; nIndex < 5; nIndex++ ) { if( pButton == m_vSearchSuggestions[nIndex] ) { searchTerm = m_vSearchSuggestions[nIndex]->GetDisplayText(); break; } } } if( searchTerm.isEmpty( ) ) return 0; // TODO FIXME! // Before the release, the allizom.org url shoud be changed to: // OUString rSearchURL = "https://services.addons.mozilla.org/en-US/firefox/api/1.5/search/" + searchTerm + "/9/9"; // The problem why it cannot be done just now is that the SSL negotiation // with services.addons.mozilla.org fails very early - during an early // propfind, SSL returns X509_V_ERR_CERT_UNTRUSTED to neon, causing the // NE_SSL_UNTRUSTED being set in verify_callback in neon/src/ne_openssl.c // // This is not cleared anywhere during the init, and so later, even though // we have found the certificate, this triggers // NeonSession_CertificationNotify callback, that // causes that NE_SSL_UNTRUSTED is igored in cases when the condition // if ( pSession->isDomainMatch( // GetHostnamePart( xEECert.get()->getSubjectName() ) ) ) // is true; but that is only when getSubjectName() actually returns a // wildcard, or the exact name. // // In the case of services.addons.mozilla.com, the certificate is for // versioncheck.addons.mozilla.com, but it also has // X509v3 Subject Alternative Name: // DNS:services.addons.mozilla.org, DNS:versioncheck-bg.addons.mozilla.org, DNS:pyrepo.addons.mozilla.org, DNS:versioncheck.addons.mozilla.org // So it is all valid; but the early X509_V_ERR_CERT_UNTRUSTED failure // described above just makes this being ignored. // // My suspicion is that this never actually worked, and the // if ( pSession->isDomainMatch( // GetHostnamePart( xEECert.get()->getSubjectName() ) ) ) // works around the root cause that is there for years, and which makes it // work in most cases. I guess that we initialize something wrongly or // too late; but I have already spent few hours debugging, and // give up for the moment - need to return to this at some stage. OUString rSearchURL = "https://addons.allizom.org/en-US/firefox/api/1.5/search/" + searchTerm + "/9/9"; m_rSearchThread = new SearchAndParseThread( this, rSearchURL ); m_rSearchThread->launch(); return 0; } IMPL_LINK( SelectPersonaDialog, ActionOK, PushButton*, /* pButton */ ) { OUString aSelectedPersona = GetSelectedPersona(); if( !aSelectedPersona.isEmpty() ) { m_rSearchThread = new SearchAndParseThread( this, aSelectedPersona ); m_rSearchThread->launch(); } else { if( m_rSearchThread.is() ) m_rSearchThread->StopExecution(); EndDialog( RET_OK ); } return 0; } IMPL_LINK( SelectPersonaDialog, ActionCancel, PushButton*, /* pButton */ ) { if( m_rSearchThread.is() ) m_rSearchThread->StopExecution(); EndDialog( RET_CANCEL ); return 0; } IMPL_LINK( SelectPersonaDialog, SelectPersona, PushButton*, pButton ) { if( m_rSearchThread.is() ) m_rSearchThread->StopExecution(); for( sal_Int32 index = 0; index < 9; index++ ) { if( pButton == m_vResultList[index] ) { if( !m_vPersonaSettings[index].isEmpty() ) { m_aSelectedPersona = m_vPersonaSettings[index]; // get the persona name from the setting variable to show in the progress. sal_Int32 nNameIndex = m_aSelectedPersona.indexOf( ';' ); OUString aName = m_aSelectedPersona.copy( 0, nNameIndex ); OUString aProgress( CUI_RES( RID_SVXSTR_SELECTEDPERSONA ) ); aProgress += aName; SetProgress( aProgress ); } break; } } return 0; } void SelectPersonaDialog::SetAppliedPersonaSetting( OUString& rPersonaSetting ) { m_aAppliedPersona = rPersonaSetting; } OUString SelectPersonaDialog::GetAppliedPersonaSetting() const { return m_aAppliedPersona; } void SelectPersonaDialog::SetProgress( OUString& rProgress ) { if(rProgress.isEmpty()) m_pProgressLabel->Hide(); else { SolarMutexGuard aGuard; m_pProgressLabel->Show(); m_pProgressLabel->SetText( rProgress ); setOptimalLayoutSize(); } } void SelectPersonaDialog::SetImages( Image aImage, sal_Int32 nIndex ) { m_vResultList[nIndex]->Enable(); m_vResultList[nIndex]->SetModeImage( aImage ); } void SelectPersonaDialog::AddPersonaSetting( OUString& rPersonaSetting ) { m_vPersonaSettings.push_back( rPersonaSetting ); } void SelectPersonaDialog::ClearSearchResults() { m_vPersonaSettings.clear(); m_aSelectedPersona = ""; for( sal_Int32 nIndex = 0; nIndex < 9; nIndex++ ) { m_vResultList[nIndex]->Disable(); m_vResultList[nIndex]->SetModeImage(Image()); } } SvxPersonalizationTabPage::SvxPersonalizationTabPage( vcl::Window *pParent, const SfxItemSet &rSet ) : SfxTabPage( pParent, "PersonalizationTabPage", "cui/ui/personalization_tab.ui", &rSet ) { // persona get( m_pNoPersona, "no_persona" ); get( m_pDefaultPersona, "default_persona" ); get( m_pOwnPersona, "own_persona" ); m_pOwnPersona->SetClickHdl( LINK( this, SvxPersonalizationTabPage, ForceSelect ) ); get( m_pSelectPersona, "select_persona" ); m_pSelectPersona->SetClickHdl( LINK( this, SvxPersonalizationTabPage, SelectPersona ) ); get( m_vDefaultPersonaImages[0], "default1" ); m_vDefaultPersonaImages[0]->SetClickHdl( LINK( this, SvxPersonalizationTabPage, DefaultPersona ) ); get( m_vDefaultPersonaImages[1], "default2" ); m_vDefaultPersonaImages[1]->SetClickHdl( LINK( this, SvxPersonalizationTabPage, DefaultPersona ) ); get( m_vDefaultPersonaImages[2], "default3" ); m_vDefaultPersonaImages[2]->SetClickHdl( LINK( this, SvxPersonalizationTabPage, DefaultPersona ) ); get( m_pPersonaList, "installed_personas" ); m_pPersonaList->SetSelectHdl( LINK( this, SvxPersonalizationTabPage, SelectInstalledPersona ) ); get( m_pExtensionPersonaPreview, "persona_preview" ); get ( m_pExtensionLabel, "extensions_label" ); LoadDefaultImages(); LoadExtensionThemes(); } SvxPersonalizationTabPage::~SvxPersonalizationTabPage() { } SfxTabPage* SvxPersonalizationTabPage::Create( vcl::Window *pParent, const SfxItemSet *rSet ) { return new SvxPersonalizationTabPage( pParent, *rSet ); } bool SvxPersonalizationTabPage::FillItemSet( SfxItemSet * ) { // persona OUString aPersona( "default" ); if ( m_pNoPersona->IsChecked() ) aPersona = "no"; else if ( m_pOwnPersona->IsChecked() ) aPersona = "own"; bool bModified = false; uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() ); if ( xContext.is() && ( aPersona != officecfg::Office::Common::Misc::Persona::get( xContext ) || m_aPersonaSettings != officecfg::Office::Common::Misc::PersonaSettings::get( xContext ) ) ) { bModified = true; } // write boost::shared_ptr< comphelper::ConfigurationChanges > batch( comphelper::ConfigurationChanges::create() ); if( aPersona == "no" ) m_aPersonaSettings = ""; officecfg::Office::Common::Misc::Persona::set( aPersona, batch ); officecfg::Office::Common::Misc::PersonaSettings::set( m_aPersonaSettings, batch ); batch->commit(); if ( bModified ) { // broadcast the change DataChangedEvent aDataChanged( DATACHANGED_SETTINGS, NULL, SETTINGS_STYLE ); Application::NotifyAllWindows( aDataChanged ); } return bModified; } void SvxPersonalizationTabPage::Reset( const SfxItemSet * ) { uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() ); // persona OUString aPersona( "default" ); if ( xContext.is() ) { aPersona = officecfg::Office::Common::Misc::Persona::get( xContext ); m_aPersonaSettings = officecfg::Office::Common::Misc::PersonaSettings::get( xContext ); } if ( aPersona == "no" ) m_pNoPersona->Check(); else if ( aPersona == "own" ) m_pOwnPersona->Check(); else m_pDefaultPersona->Check(); } void SvxPersonalizationTabPage::SetPersonaSettings( const OUString& aPersonaSettings ) { m_aPersonaSettings = aPersonaSettings; m_pOwnPersona->Check(); } void SvxPersonalizationTabPage::LoadDefaultImages() { // Load the pre saved personas OUString gallery( "" ); gallery = "$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER; gallery += "/gallery/personas/"; rtl::Bootstrap::expandMacros( gallery ); OUString aPersonasList = gallery + "personas_list.txt"; SvFileStream aStream( aPersonasList, STREAM_READ ); GraphicFilter aFilter; Graphic aGraphic; sal_Int32 nIndex = 0; while( aStream.IsOpen() && !aStream.IsEof() ) { OString aLine; aStream.ReadLine( aLine ); OUString aPersonaSetting( OUString::fromUtf8( aLine ) ); OUString aPreviewFile; sal_Int32 nNewIndex = aPersonaSetting.indexOf( ';', 0 ); if( nNewIndex < 0 ) break; aPreviewFile = aPersonaSetting.copy( 0, nNewIndex ); aPersonaSetting = aPersonaSetting.copy( nNewIndex + 1 ); m_vDefaultPersonaSettings.push_back( aPersonaSetting ); INetURLObject aURLObj( gallery + aPreviewFile ); aFilter.ImportGraphic( aGraphic, aURLObj ); Bitmap aBmp = aGraphic.GetBitmap(); m_vDefaultPersonaImages[nIndex]->Show(); m_vDefaultPersonaImages[nIndex++]->SetModeImage( Image( aBmp ) ); } } void SvxPersonalizationTabPage::LoadExtensionThemes() { // See if any extensions are used to install personas. If yes, load them. css::uno::Sequence installedPersonas( officecfg::Office::Common::Misc::PersonasList::get()->getElementNames() ); sal_Int32 nLength = installedPersonas.getLength(); if( nLength == 0 ) return; m_pPersonaList->Show(); m_pExtensionLabel->Show(); for( sal_Int32 nIndex = 0; nIndex < nLength; nIndex++ ) { Reference< XPropertySet > xPropertySet( officecfg::Office::Common::Misc::PersonasList::get()->getByName( installedPersonas[nIndex] ), UNO_QUERY_THROW ); OUString aPersonaName, aPreviewFile, aHeaderFile, aFooterFile, aTextColor, aAccentColor, aPersonaSettings; Any aValue = xPropertySet->getPropertyValue( "Name" ); aValue >>= aPersonaName; m_pPersonaList->InsertEntry( aPersonaName ); aValue = xPropertySet->getPropertyValue( "Preview" ); aValue >>= aPreviewFile; aValue = xPropertySet->getPropertyValue( "Header" ); aValue >>= aHeaderFile; aValue = xPropertySet->getPropertyValue( "Footer" ); aValue >>= aFooterFile; aValue = xPropertySet->getPropertyValue( "TextColor" ); aValue >>= aTextColor; aValue = xPropertySet->getPropertyValue( "AccentColor" ); aValue >>= aAccentColor; aPersonaSettings = aPreviewFile + ";" + aHeaderFile + ";" + aFooterFile + ";" + aTextColor + ";" + aAccentColor; rtl::Bootstrap::expandMacros( aPersonaSettings ); m_vExtensionPersonaSettings.push_back( aPersonaSettings ); } } IMPL_LINK( SvxPersonalizationTabPage, SelectPersona, PushButton*, /*pButton*/ ) { SelectPersonaDialog aDialog( NULL ); while ( aDialog.Execute() == RET_OK ) { OUString aPersonaSetting( aDialog.GetAppliedPersonaSetting() ); if ( !aPersonaSetting.isEmpty() ) { SetPersonaSettings( aPersonaSetting ); } break; } return 0; } IMPL_LINK( SvxPersonalizationTabPage, ForceSelect, RadioButton*, pButton ) { if ( pButton == m_pOwnPersona && m_aPersonaSettings.isEmpty() ) SelectPersona( m_pSelectPersona ); return 0; } IMPL_LINK( SvxPersonalizationTabPage, DefaultPersona, PushButton*, pButton ) { m_pDefaultPersona->Check(); for( sal_Int32 nIndex = 0; nIndex < 3; nIndex++ ) { if( pButton == m_vDefaultPersonaImages[nIndex] ) m_aPersonaSettings = m_vDefaultPersonaSettings[nIndex]; } return 0; } IMPL_LINK( SvxPersonalizationTabPage, SelectInstalledPersona, ListBox*, ) { m_pOwnPersona->Check(); // Get the details of the selected theme. m_pExtensionPersonaPreview->Show(); sal_Int32 nSelectedPos = m_pPersonaList->GetSelectEntryPos(); OUString aSettings = m_vExtensionPersonaSettings[nSelectedPos]; sal_Int32 nIndex = aSettings.indexOf( ';', 0 ); OUString aPreviewFile = aSettings.copy( 0, nIndex ); m_aPersonaSettings = aSettings.copy( nIndex + 1 ); // Show the preview file in the button. GraphicFilter aFilter; Graphic aGraphic; INetURLObject aURLObj( aPreviewFile ); aFilter.ImportGraphic( aGraphic, aURLObj ); Bitmap aBmp = aGraphic.GetBitmap(); m_pExtensionPersonaPreview->SetModeImage( Image( aBmp ) ); return 0; } /// Find the value on the Persona page, and convert it to a usable form. static OUString searchValue( const OString &rBuffer, sal_Int32 from, const OString &rIdentifier ) { sal_Int32 where = rBuffer.indexOf( rIdentifier, from ); if ( where < 0 ) return OUString(); where += rIdentifier.getLength(); sal_Int32 end = rBuffer.indexOf( """, where ); if ( end < 0 ) return OUString(); OString aOString( rBuffer.copy( where, end - where ) ); OUString aString( aOString.getStr(), aOString.getLength(), RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS ); return aString.replaceAll( "\\/", "/" ); } /// Parse the Persona web page, and find where to get the bitmaps + the color values. static bool parsePersonaInfo( const OString &rBuffer, OUString *pHeaderURL, OUString *pFooterURL, OUString *pTextColor, OUString *pAccentColor, OUString *pPreviewURL, OUString *pName ) { // it is the first attribute that contains "persona=" sal_Int32 persona = rBuffer.indexOf( "data-browsertheme=\"{" ); if ( persona < 0 ) return false; // now search inside *pHeaderURL = searchValue( rBuffer, persona, ""headerURL":"" ); if ( pHeaderURL->isEmpty() ) return false; *pFooterURL = searchValue( rBuffer, persona, ""footerURL":"" ); if ( pFooterURL->isEmpty() ) return false; *pTextColor = searchValue( rBuffer, persona, ""textcolor":"" ); if ( pTextColor->isEmpty() ) return false; *pAccentColor = searchValue( rBuffer, persona, ""accentcolor":"" ); if ( pAccentColor->isEmpty() ) return false; *pPreviewURL = searchValue( rBuffer, persona, ""previewURL":"" ); if ( pPreviewURL->isEmpty() ) return false; *pName = searchValue( rBuffer, persona, ""name":"" ); if ( pName->isEmpty() ) return false; return true; } SearchAndParseThread::SearchAndParseThread( SelectPersonaDialog* pDialog, const OUString& rURL ) : Thread( "cuiPersonasSearchThread" ), m_pPersonaDialog( pDialog ), m_aURL( rURL ), m_bExecute( true ) { } SearchAndParseThread::~SearchAndParseThread() { } void SearchAndParseThread::execute() { if( m_aURL.startsWith( "https://" ) ) { m_pPersonaDialog->ClearSearchResults(); OUString sProgress( CUI_RES( RID_SVXSTR_SEARCHING ) ); m_pPersonaDialog->SetProgress( sProgress ); Reference xContext( ::comphelper::getProcessComponentContext() ); Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(xContext); PersonasDocHandler* pHandler = new PersonasDocHandler(); Reference< xml::sax::XDocumentHandler > xDocHandler = pHandler; uno::Reference< ucb::XSimpleFileAccess3 > xFileAccess( ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() ), uno::UNO_QUERY ); uno::Reference< io::XInputStream > xStream; xParser->setDocumentHandler( xDocHandler ); if ( !xFileAccess.is() ) return; try { xStream = xFileAccess->openFileRead( m_aURL ); } catch (...) { sProgress = CUI_RES(RID_SVXSTR_SEARCHERROR); sProgress = sProgress.replaceAll("%1", m_aURL); m_pPersonaDialog->SetProgress(sProgress); return; } xml::sax::InputSource aParserInput; aParserInput.aInputStream = xStream; xParser->parseStream( aParserInput ); if( !pHandler->hasResults() ) { sProgress = CUI_RES( RID_SVXSTR_NORESULTS ); m_pPersonaDialog->SetProgress( sProgress ); return; } std::vector vLearnmoreURLs = pHandler->getLearnmoreURLs(); std::vector::iterator it; sal_Int32 nIndex = 0; GraphicFilter aFilter; Graphic aGraphic; for( it = vLearnmoreURLs.begin(); it!=vLearnmoreURLs.end(); ++it ) { OUString sPreviewFile, aPersonaSetting; getPreviewFile( *it, &sPreviewFile, &aPersonaSetting ); INetURLObject aURLObj( sPreviewFile ); aFilter.ImportGraphic( aGraphic, aURLObj ); Bitmap aBmp = aGraphic.GetBitmap(); if( !m_bExecute ) return; // for VCL to be able to do visual changes in the thread SolarMutexGuard aGuard; m_pPersonaDialog->SetImages( Image( aBmp ), nIndex++ ); m_pPersonaDialog->setOptimalLayoutSize(); m_pPersonaDialog->AddPersonaSetting( aPersonaSetting ); } if( !m_bExecute ) return; SolarMutexGuard aGuard; sProgress = ""; m_pPersonaDialog->SetProgress( sProgress ); m_pPersonaDialog->setOptimalLayoutSize(); } else { OUString sProgress( CUI_RES( RID_SVXSTR_APPLYPERSONA ) ); m_pPersonaDialog->SetProgress( sProgress ); uno::Reference< ucb::XSimpleFileAccess3 > xFileAccess( ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() ), uno::UNO_QUERY ); if ( !xFileAccess.is() ) return; OUString aName, aHeaderURL, aFooterURL, aTextColor, aAccentColor; OUString aPersonaSetting; // get the required fields from m_aURL sal_Int32 nOldIndex = 0; sal_Int32 nNewIndex = m_aURL.indexOf( ';', nOldIndex ); aName = m_aURL.copy( nOldIndex, ( nNewIndex - nOldIndex ) ); nOldIndex = nNewIndex + 1; nNewIndex = m_aURL.indexOf( ';', nOldIndex ); aHeaderURL = m_aURL.copy(nOldIndex , ( nNewIndex - nOldIndex ) ); nOldIndex = nNewIndex + 1; nNewIndex = m_aURL.indexOf( ';', nOldIndex ); aFooterURL = m_aURL.copy( nOldIndex, ( nNewIndex - nOldIndex ) ); nOldIndex = nNewIndex + 1; nNewIndex = m_aURL.indexOf( ';', nOldIndex ); aTextColor = m_aURL.copy( nOldIndex, ( nNewIndex - nOldIndex ) ); nOldIndex = nNewIndex + 1; nNewIndex = m_aURL.getLength(); aAccentColor = m_aURL.copy( nOldIndex, ( nNewIndex - nOldIndex ) ); // copy the images to the user's gallery OUString gallery = "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE( "bootstrap") "::UserInstallation}"; rtl::Bootstrap::expandMacros( gallery ); gallery += "/user/gallery/personas/"; osl::Directory::createPath( gallery ); OUString aHeaderFile( INetURLObject( aHeaderURL ).getName() ); OUString aFooterFile( INetURLObject( aFooterURL ).getName() ); aHeaderFile = aName + "/" + aHeaderFile; aFooterFile = aName + "/" + aFooterFile; try { xFileAccess->copy( aHeaderURL, gallery + aHeaderFile ); xFileAccess->copy( aFooterURL, gallery + aFooterFile ); } catch ( const uno::Exception & ) { sProgress = CUI_RES( RID_SVXSTR_SEARCHERROR ); sProgress = sProgress.replaceAll("%1", m_aURL); m_pPersonaDialog->SetProgress( sProgress ); return; } if( !m_bExecute ) return; SolarMutexGuard aGuard; aPersonaSetting = aHeaderFile + ";" + aFooterFile + ";" + aTextColor + ";" + aAccentColor; m_pPersonaDialog->SetAppliedPersonaSetting( aPersonaSetting ); m_pPersonaDialog->EndDialog( RET_OK ); } } void SearchAndParseThread::getPreviewFile( const OUString& rURL, OUString *pPreviewFile, OUString *pPersonaSetting ) { uno::Reference< ucb::XSimpleFileAccess3 > xFileAccess( ucb::SimpleFileAccess::create( comphelper::getProcessComponentContext() ), uno::UNO_QUERY ); if ( !xFileAccess.is() ) return; uno::Reference< io::XInputStream > xStream; try { xStream = xFileAccess->openFileRead( rURL ); } catch (...) { OUString sProgress( CUI_RES( RID_SVXSTR_SEARCHERROR ) ); sProgress = sProgress.replaceAll("%1", m_aURL); m_pPersonaDialog->SetProgress( sProgress ); return; } if ( !xStream.is() ) return; // read the persona specification // NOTE: Parsing for real is an overkill here; and worse - I tried, and // the HTML the site provides is not 100% valid ;-) const sal_Int32 BUF_LEN = 8000; uno::Sequence< sal_Int8 > buffer( BUF_LEN ); OStringBuffer aBuffer( 64000 ); sal_Int32 nRead = 0; while ( ( nRead = xStream->readBytes( buffer, BUF_LEN ) ) == BUF_LEN ) aBuffer.append( reinterpret_cast< const char* >( buffer.getConstArray() ), nRead ); if ( nRead > 0 ) aBuffer.append( reinterpret_cast< const char* >( buffer.getConstArray() ), nRead ); xStream->closeInput(); // get the important bits of info OUString aHeaderURL, aFooterURL, aTextColor, aAccentColor, aPreviewURL, aName; if ( !parsePersonaInfo( aBuffer.makeStringAndClear(), &aHeaderURL, &aFooterURL, &aTextColor, &aAccentColor, &aPreviewURL, &aName ) ) return; // copy the images to the user's gallery OUString gallery = "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE( "bootstrap") "::UserInstallation}"; rtl::Bootstrap::expandMacros( gallery ); gallery += "/user/gallery/personas/"; gallery += aName + "/"; osl::Directory::createPath( gallery ); OUString aPreviewFile( INetURLObject( aPreviewURL ).getName() ); try { xFileAccess->copy( aPreviewURL, gallery + aPreviewFile ); } catch ( const uno::Exception & ) { return; } *pPreviewFile = gallery + aPreviewFile; *pPersonaSetting = aName + ";" + aHeaderURL + ";" + aFooterURL + ";" + aTextColor + ";" + aAccentColor; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */