diff --git a/extensions/source/update/check/download.cxx b/extensions/source/update/check/download.cxx old mode 100644 new mode 100755 index dd7da492ff57..09d90f1eaa83 --- a/extensions/source/update/check/download.cxx +++ b/extensions/source/update/check/download.cxx @@ -169,7 +169,9 @@ progress_callback( void *clientp, double dltotal, double dlnow, double ultotal, if( ! out->StopCondition.check() ) { - double fPercent = (dlnow + out->Offset) * 100 / (dltotal + out->Offset); + double fPercent = 0; + if ( dltotal + out->Offset ) + fPercent = (dlnow + out->Offset) * 100 / (dltotal + out->Offset); if( fPercent < 0 ) fPercent = 0; @@ -262,6 +264,9 @@ bool curl_run(const rtl::OUString& rURL, OutData& out, const rtl::OString& aProx rtl::OString aURL(rtl::OUStringToOString(rURL, RTL_TEXTENCODING_UTF8)); curl_easy_setopt(pCURL, CURLOPT_URL, aURL.getStr()); + // abort on http errors + curl_easy_setopt(pCURL, CURLOPT_FAILONERROR, 1); + // enable redirection curl_easy_setopt(pCURL, CURLOPT_FOLLOWLOCATION, 1); @@ -300,6 +305,19 @@ bool curl_run(const rtl::OUString& rURL, OutData& out, const rtl::OString& aProx ret = true; } + if ( CURLE_PARTIAL_FILE == cc ) + { + // this sometimes happens, when a user throws away his user data, but has already + // completed the download of an update. + double fDownloadSize; + curl_easy_getinfo( pCURL, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &fDownloadSize ); + if ( -1 == fDownloadSize ) + { + out.Handler->downloadFinished(out.File); + ret = true; + } + } + // Avoid target file being removed else if( (CURLE_ABORTED_BY_CALLBACK == cc) || out.StopCondition.check() ) ret = true; @@ -313,7 +331,30 @@ bool curl_run(const rtl::OUString& rURL, OutData& out, const rtl::OString& aProx if( NULL != error_message ) aMessage = error_message; - out.Handler->downloadStalled( rtl::OStringToOUString(aMessage, RTL_TEXTENCODING_UTF8) ); + if ( CURLE_HTTP_RETURNED_ERROR == cc ) + { + long nError; + curl_easy_getinfo( pCURL, CURLINFO_RESPONSE_CODE, &nError ); + + if ( 403 == nError ) + aMessage += rtl::OString( RTL_CONSTASCII_STRINGPARAM( " 403: Access denied!" ) ); + else if ( 404 == nError ) + aMessage += rtl::OString( RTL_CONSTASCII_STRINGPARAM( " 404: File not found!" ) ); + else if ( 416 == nError ) + { + // we got this error probably, because we already downloaded the file + out.Handler->downloadFinished(out.File); + ret = true; + } + else + { + aMessage += rtl::OString( RTL_CONSTASCII_STRINGPARAM( ":error code = " ) ); + aMessage += aMessage.valueOf( nError ); + aMessage += rtl::OString( RTL_CONSTASCII_STRINGPARAM( " !" ) ); + } + } + if ( !ret ) + out.Handler->downloadStalled( rtl::OStringToOUString(aMessage, RTL_TEXTENCODING_UTF8) ); } curl_easy_cleanup(pCURL); @@ -330,14 +371,52 @@ Download::start(const rtl::OUString& rURL, const rtl::OUString& rFile, const rtl OSL_ASSERT( m_aHandler.is() ); OutData out(m_aCondition); + rtl::OUString aFile( rFile ); - out.File = rFile; + // when rFile is empty, there is no remembered file name. If there is already a file with the + // same name ask the user if she wants to resume a download or restart the download + if ( !aFile.getLength() ) + { + // GetFileName() + rtl::OUString aURL( rURL ); + // ensure no trailing '/' + sal_Int32 nLen = aURL.getLength(); + while( (nLen > 0) && ('/' == aURL[ nLen-1 ]) ) + aURL = aURL.copy( 0, --nLen ); + + // extract file name last '/' + sal_Int32 nIndex = aURL.lastIndexOf('/'); + aFile = rDestinationDir + aURL.copy( nIndex ); + + // check for existing file + oslFileError rc = osl_openFile( aFile.pData, &out.FileHandle, osl_File_OpenFlag_Write | osl_File_OpenFlag_Create ); + osl_closeFile(out.FileHandle); + out.FileHandle = NULL; + + if( osl_File_E_EXIST == rc ) + { + if ( m_aHandler->checkDownloadDestination( aURL.copy( nIndex+1 ) ) ) + { + osl_removeFile( aFile.pData ); + aFile = rtl::OUString(); + } + else + m_aHandler->downloadStarted( aFile, 0 ); + } + else + { + osl_removeFile( aFile.pData ); + aFile = rtl::OUString(); + } + } + + out.File = aFile; out.DestinationDir = rDestinationDir; out.Handler = m_aHandler; - if( rFile.getLength() > 0 ) + if( aFile.getLength() > 0 ) { - oslFileError rc = osl_openFile(rFile.pData, &out.FileHandle, osl_File_OpenFlag_Write); + oslFileError rc = osl_openFile(aFile.pData, &out.FileHandle, osl_File_OpenFlag_Write); if( osl_File_E_None == rc ) { diff --git a/extensions/source/update/check/download.hxx b/extensions/source/update/check/download.hxx index 1b2fb678417b..ff16ef52f7fb 100644 --- a/extensions/source/update/check/download.hxx +++ b/extensions/source/update/check/download.hxx @@ -35,6 +35,8 @@ struct DownloadInteractionHandler : public rtl::IReference { + virtual bool checkDownloadDestination(const rtl::OUString& rFileName) = 0; + // called if the destination file already exists, but resume is false virtual bool downloadTargetExists(const rtl::OUString& rFileName) = 0; diff --git a/extensions/source/update/check/updatecheck.cxx b/extensions/source/update/check/updatecheck.cxx old mode 100644 new mode 100755 index 10632cd23fbd..d65a97e49dc6 --- a/extensions/source/update/check/updatecheck.cxx +++ b/extensions/source/update/check/updatecheck.cxx @@ -800,6 +800,8 @@ UpdateCheck::initialize(const uno::Sequence< beans::NamedValue >& rValues, aModel.getUpdateEntry(m_aUpdateInfo); bool obsoleteUpdateInfo = isObsoleteUpdateInfo(aUpdateEntryVersion); + bool bContinueDownload = false; + bool bDownloadAvailable = false; m_bHasExtensionUpdate = checkForPendingUpdates( xContext ); m_bShowExtUpdDlg = false; @@ -808,10 +810,7 @@ UpdateCheck::initialize(const uno::Sequence< beans::NamedValue >& rValues, if( aLocalFileName.getLength() > 0 ) { - bool downloadPaused = aModel.isDownloadPaused(); - - enableDownload(true, downloadPaused); - setUIState(downloadPaused ? UPDATESTATE_DOWNLOAD_PAUSED : UPDATESTATE_DOWNLOADING); + bContinueDownload = true; // Try to get the number of bytes already on disk osl::DirectoryItem aDirectoryItem; @@ -820,16 +819,36 @@ UpdateCheck::initialize(const uno::Sequence< beans::NamedValue >& rValues, osl::FileStatus aFileStatus(FileStatusMask_FileSize); if( osl::DirectoryItem::E_None == aDirectoryItem.getFileStatus(aFileStatus) ) { - // Calculate initial percent value. - if( aModel.getDownloadSize() > 0 ) + sal_Int64 nDownloadSize = aModel.getDownloadSize(); + sal_Int64 nFileSize = aFileStatus.getFileSize(); + + if( nDownloadSize > 0 ) { - sal_Int32 nPercent = (sal_Int32) (100 * aFileStatus.getFileSize() / aModel.getDownloadSize()); - getUpdateHandler()->setProgress(nPercent); + if ( nDownloadSize <= nFileSize ) // we have already downloaded everthing + { + bContinueDownload = false; + bDownloadAvailable = true; + m_aImageName = getImageFromFileName( aLocalFileName ); + } + else // Calculate initial percent value. + { + sal_Int32 nPercent = (sal_Int32) (100 * nFileSize / nDownloadSize); + getUpdateHandler()->setProgress( nPercent ); + } } } } + + if ( bContinueDownload ) + { + bool downloadPaused = aModel.isDownloadPaused(); + + enableDownload(true, downloadPaused); + setUIState(downloadPaused ? UPDATESTATE_DOWNLOAD_PAUSED : UPDATESTATE_DOWNLOADING); + } + } - else + if ( !bContinueDownload ) { // We do this intentionally only if no download is in progress .. if( obsoleteUpdateInfo ) @@ -842,13 +861,18 @@ UpdateCheck::initialize(const uno::Sequence< beans::NamedValue >& rValues, // Data is outdated, probably due to installed update rtl::Reference< UpdateCheckConfig > aConfig = UpdateCheckConfig::get( xContext, *this ); aConfig->clearUpdateFound(); + aConfig->clearLocalFileName(); + m_aUpdateInfo = UpdateInfo(); } else { enableAutoCheck(aModel.isAutoCheckEnabled()); - setUIState(getUIState(m_aUpdateInfo)); + if ( bDownloadAvailable ) + setUIState( UPDATESTATE_DOWNLOAD_AVAIL ); + else + setUIState(getUIState(m_aUpdateInfo)); } } } @@ -937,6 +961,10 @@ UpdateCheck::install() aParameter += UNISTRING(" &"); #endif + + rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get( m_xContext ); + rModel->clearLocalFileName(); + xShellExecute->execute(aInstallImage, aParameter, nFlags); ShutdownThread *pShutdownThread = new ShutdownThread( m_xContext ); (void) pShutdownThread; @@ -1101,6 +1129,23 @@ UpdateCheck::downloadTargetExists(const rtl::OUString& rFileName) return cont; } +//------------------------------------------------------------------------------ +bool UpdateCheck::checkDownloadDestination( const rtl::OUString& rFileName ) +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + + rtl::Reference< UpdateHandler > aUpdateHandler( getUpdateHandler() ); + + bool bReload = false; + + if( aUpdateHandler->isVisible() ) + { + bReload = aUpdateHandler->showOverwriteWarning( rFileName ); + } + + return bReload; +} + //------------------------------------------------------------------------------ void @@ -1132,15 +1177,18 @@ UpdateCheck::downloadProgressAt(sal_Int8 nPercent) void UpdateCheck::downloadStarted(const rtl::OUString& rLocalFileName, sal_Int64 nFileSize) { - osl::MutexGuard aGuard(m_aMutex); + if ( nFileSize > 0 ) + { + osl::MutexGuard aGuard(m_aMutex); - rtl::Reference< UpdateCheckConfig > aModel(UpdateCheckConfig::get(m_xContext)); - aModel->storeLocalFileName(rLocalFileName, nFileSize); + rtl::Reference< UpdateCheckConfig > aModel(UpdateCheckConfig::get(m_xContext)); + aModel->storeLocalFileName(rLocalFileName, nFileSize); - // Bring-up release note for position 1 .. - const rtl::OUString aURL(getReleaseNote(m_aUpdateInfo, 1, aModel->isAutoDownloadEnabled())); - if( aURL.getLength() > 0 ) - showReleaseNote(aURL); + // Bring-up release note for position 1 .. + const rtl::OUString aURL(getReleaseNote(m_aUpdateInfo, 1, aModel->isAutoDownloadEnabled())); + if( aURL.getLength() > 0 ) + showReleaseNote(aURL); + } } //------------------------------------------------------------------------------ @@ -1153,9 +1201,6 @@ UpdateCheck::downloadFinished(const rtl::OUString& rLocalFileName) // no more retries m_pThread->terminate(); - rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext); - rModel->clearLocalFileName(); - m_aImageName = getImageFromFileName(rLocalFileName); UpdateInfo aUpdateInfo(m_aUpdateInfo); @@ -1163,6 +1208,7 @@ UpdateCheck::downloadFinished(const rtl::OUString& rLocalFileName) setUIState(UPDATESTATE_DOWNLOAD_AVAIL); // Bring-up release note for position 2 .. + rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get( m_xContext ); const rtl::OUString aURL(getReleaseNote(aUpdateInfo, 2, rModel->isAutoDownloadEnabled())); if( aURL.getLength() > 0 ) showReleaseNote(aURL); diff --git a/extensions/source/update/check/updatecheck.hxx b/extensions/source/update/check/updatecheck.hxx index 59a1727f4bd9..7283288769e0 100644 --- a/extensions/source/update/check/updatecheck.hxx +++ b/extensions/source/update/check/updatecheck.hxx @@ -111,6 +111,8 @@ public: virtual void downloadProgressAt(sal_Int8 nProcent); virtual void downloadStarted(const rtl::OUString& rLocalFileName, sal_Int64 nFileSize); virtual void downloadFinished(const rtl::OUString& rLocalFileName); + // checks if the download target already exists and asks user what to do next + virtual bool checkDownloadDestination( const rtl::OUString& rFile ); // Cancels the download action (and resumes checking if enabled) void cancelDownload(); diff --git a/extensions/source/update/check/updatecheckconfig.cxx b/extensions/source/update/check/updatecheckconfig.cxx old mode 100644 new mode 100755 index b3e559c5f136..9f78b33270c2 --- a/extensions/source/update/check/updatecheckconfig.cxx +++ b/extensions/source/update/check/updatecheckconfig.cxx @@ -398,7 +398,7 @@ UpdateCheckConfig::storeLocalFileName(const rtl::OUString& rLocalFileName, sal_I if( m_xContainer->hasByName(aNameList[i]) ) m_xContainer->replaceByName(aNameList[i], aValueList[i]); else - m_xContainer->insertByName(aNameList[i],aValueList[i]); + m_xContainer->insertByName(aNameList[i], aValueList[i]); } commitChanges(); diff --git a/extensions/source/update/check/updatehdl.cxx b/extensions/source/update/check/updatehdl.cxx index cd1c5f1f721a..bb38c34a0b4e 100644 --- a/extensions/source/update/check/updatehdl.cxx +++ b/extensions/source/update/check/updatehdl.cxx @@ -52,6 +52,7 @@ #include "com/sun/star/awt/XThrobber.hpp" #include "com/sun/star/awt/XTopWindow.hpp" #include "com/sun/star/awt/XVclWindowPeer.hpp" +#include "com/sun/star/awt/XVclContainer.hpp" #include "com/sun/star/awt/XWindow.hpp" #include "com/sun/star/awt/XWindow2.hpp" @@ -101,7 +102,8 @@ UpdateHandler::UpdateHandler( const uno::Reference< uno::XComponentContext > & r mbVisible( false ), mbStringsLoaded( false ), mbMinimized( false ), - mbListenerAdded(false) + mbListenerAdded(false), + mbShowsMessageBox(false) { } @@ -232,6 +234,11 @@ void UpdateHandler::setVisible( bool bVisible ) //-------------------------------------------------------------------- void UpdateHandler::setProgress( sal_Int32 nPercent ) { + if ( nPercent > 100 ) + nPercent = 100; + else if ( nPercent < 0 ) + nPercent = 0; + if ( nPercent != mnPercent ) { osl::MutexGuard aGuard( maMutex ); @@ -478,7 +485,18 @@ void SAL_CALL UpdateHandler::handle( uno::Reference< task::XInteractionRequest > void SAL_CALL UpdateHandler::queryTermination( const lang::EventObject& ) throw ( frame::TerminationVetoException, uno::RuntimeException ) { - setVisible( false ); + if ( mbShowsMessageBox ) + { + uno::Reference< awt::XTopWindow > xTopWindow( mxUpdDlg, uno::UNO_QUERY ); + if ( xTopWindow.is() ) + xTopWindow->toFront(); + + throw frame::TerminationVetoException( + UNISTRING("The office cannot be closed while displaying a warning!"), + uno::Reference(static_cast(this), uno::UNO_QUERY)); + } + else + setVisible( false ); } //------------------------------------------------------------------------------ @@ -707,6 +725,9 @@ void UpdateHandler::loadStrings() msInstallError = loadString( xBundle, RID_UPDATE_STR_INSTALL_ERROR ); msOverwriteWarning = loadString( xBundle, RID_UPDATE_STR_OVERWRITE_WARNING ); msPercent = loadString( xBundle, RID_UPDATE_STR_PERCENT ); + msReloadWarning = loadString( xBundle, RID_UPDATE_STR_RELOAD_WARNING ); + msReloadReload = loadString( xBundle, RID_UPDATE_STR_RELOAD_RELOAD ); + msReloadContinue = loadString( xBundle, RID_UPDATE_STR_RELOAD_CONTINUE ); msStatusFL = loadString( xBundle, RID_UPDATE_FT_STATUS ); msDescription = loadString( xBundle, RID_UPDATE_FT_DESCRIPTION ); @@ -943,12 +964,14 @@ bool UpdateHandler::showWarning( const rtl::OUString &rWarningText ) const uno::Reference< awt::XMessageBox > xMsgBox( xToolkit->createWindow( aDescriptor ), uno::UNO_QUERY ); if ( xMsgBox.is() ) { + mbShowsMessageBox = true; sal_Int16 nRet; // xMsgBox->setCaptionText( msCancelTitle ); xMsgBox->setMessageText( rWarningText ); nRet = xMsgBox->execute(); if ( nRet == 2 ) // RET_YES == 2 bRet = true; + mbShowsMessageBox = false; } uno::Reference< lang::XComponent > xComponent( xMsgBox, uno::UNO_QUERY ); @@ -958,6 +981,86 @@ bool UpdateHandler::showWarning( const rtl::OUString &rWarningText ) const return bRet; } +//-------------------------------------------------------------------- +bool UpdateHandler::showWarning( const rtl::OUString &rWarningText, + const rtl::OUString &rBtnText_1, + const rtl::OUString &rBtnText_2 ) const +{ + bool bRet = false; + + uno::Reference< awt::XControl > xControl( mxUpdDlg, uno::UNO_QUERY ); + if ( !xControl.is() ) return bRet; + + uno::Reference< awt::XWindowPeer > xPeer = xControl->getPeer(); + if ( !xPeer.is() ) return bRet; + + uno::Reference< awt::XToolkit > xToolkit = xPeer->getToolkit(); + if ( !xToolkit.is() ) return bRet; + + awt::WindowDescriptor aDescriptor; + + sal_Int32 nWindowAttributes = awt::WindowAttribute::BORDER | awt::WindowAttribute::MOVEABLE | awt::WindowAttribute::CLOSEABLE; + nWindowAttributes |= awt::VclWindowPeerAttribute::YES_NO; + nWindowAttributes |= awt::VclWindowPeerAttribute::DEF_NO; + + aDescriptor.Type = awt::WindowClass_MODALTOP; + aDescriptor.WindowServiceName = UNISTRING( "warningbox" ); + aDescriptor.ParentIndex = -1; + aDescriptor.Parent = xPeer; + aDescriptor.Bounds = awt::Rectangle( 10, 10, 250, 150 ); + aDescriptor.WindowAttributes = nWindowAttributes; + + uno::Reference< awt::XMessageBox > xMsgBox( xToolkit->createWindow( aDescriptor ), uno::UNO_QUERY ); + if ( xMsgBox.is() ) + { + uno::Reference< awt::XVclContainer > xMsgBoxCtrls( xMsgBox, uno::UNO_QUERY ); + if ( xMsgBoxCtrls.is() ) + { + uno::Sequence< uno::Reference< awt::XWindow > > xChildren = xMsgBoxCtrls->getWindows(); + + for ( long i=0; i < xChildren.getLength(); i++ ) + { + uno::Reference< awt::XVclWindowPeer > xMsgBoxCtrl( xChildren[i], uno::UNO_QUERY ); + if ( xMsgBoxCtrl.is() ) + { + bool bIsDefault = true; + uno::Any aValue = xMsgBoxCtrl->getProperty( UNISTRING("DefaultButton") ); + aValue >>= bIsDefault; + if ( bIsDefault ) + xMsgBoxCtrl->setProperty( UNISTRING("Text"), uno::Any( rBtnText_1 ) ); + else + xMsgBoxCtrl->setProperty( UNISTRING("Text"), uno::Any( rBtnText_2 ) ); + } + } + } + + sal_Int16 nRet; + // xMsgBox->setCaptionText( msCancelTitle ); + mbShowsMessageBox = true; + xMsgBox->setMessageText( rWarningText ); + nRet = xMsgBox->execute(); + if ( nRet == 2 ) // RET_YES == 2 + bRet = true; + + mbShowsMessageBox = false; + } + + uno::Reference< lang::XComponent > xComponent( xMsgBox, uno::UNO_QUERY ); + if ( xComponent.is() ) + xComponent->dispose(); + + return bRet; +} + +//-------------------------------------------------------------------- +bool UpdateHandler::showOverwriteWarning( const rtl::OUString& rFileName ) const +{ + rtl::OUString aMsg( msReloadWarning ); + searchAndReplaceAll( aMsg, UNISTRING( "%FILENAME" ), rFileName ); + searchAndReplaceAll( aMsg, UNISTRING( "%DOWNLOAD_PATH" ), msDownloadPath ); + return showWarning( aMsg, msReloadContinue, msReloadReload ); +} + //-------------------------------------------------------------------- bool UpdateHandler::showOverwriteWarning() const { diff --git a/extensions/source/update/check/updatehdl.hrc b/extensions/source/update/check/updatehdl.hrc index 6389a661bf6c..ad3d472eaf68 100644 --- a/extensions/source/update/check/updatehdl.hrc +++ b/extensions/source/update/check/updatehdl.hrc @@ -47,6 +47,9 @@ #define RID_UPDATE_STR_PERCENT RID_UPDATE_HDL_START + 18 #define RID_UPDATE_STR_DOWNLOAD_DESCR RID_UPDATE_HDL_START + 19 #define RID_UPDATE_STR_INSTALL_ERROR RID_UPDATE_HDL_START + 20 + #define RID_UPDATE_STR_RELOAD_WARNING RID_UPDATE_HDL_START + 21 + #define RID_UPDATE_STR_RELOAD_RELOAD RID_UPDATE_HDL_START + 22 + #define RID_UPDATE_STR_RELOAD_CONTINUE RID_UPDATE_HDL_START + 23 #define RID_UPDATE_FT_DESCRIPTION RID_UPDATE_HDL_START + 25 #define RID_UPDATE_FT_STATUS RID_UPDATE_HDL_START + 26 diff --git a/extensions/source/update/check/updatehdl.hxx b/extensions/source/update/check/updatehdl.hxx index 696e2cdda0cf..bd525853dda1 100644 --- a/extensions/source/update/check/updatehdl.hxx +++ b/extensions/source/update/check/updatehdl.hxx @@ -98,6 +98,7 @@ private: bool mbStringsLoaded; bool mbMinimized; bool mbListenerAdded; + mutable bool mbShowsMessageBox; osl::Mutex maMutex; @@ -125,6 +126,9 @@ private: rtl::OUString msInstallError; // RID_UPDATE_STR_INSTALL_ERROR rtl::OUString msOverwriteWarning; // RID_UPDATE_STR_OVERWRITE_WARNING rtl::OUString msPercent; // RID_UPDATE_STR_PERCENT + rtl::OUString msReloadWarning; // RID_UPDATE_STR_OVERWRITE_WARNING + rtl::OUString msReloadReload; // RID_UPDATE_STR_OVERWRITE_WARNING + rtl::OUString msReloadContinue; // RID_UPDATE_STR_OVERWRITE_WARNING rtl::OUString msStatusFL; // RID_UPDATE_FT_STATUS rtl::OUString msDescription; // RID_UPDATE_FT_DESCRIPTION rtl::OUString msClose; // RID_UPDATE_BTN_CLOSE @@ -184,6 +188,8 @@ public: rtl::OUString getBubbleTitle( UpdateState eState ); rtl::OUString getDefaultInstErrMsg(); bool showWarning( const rtl::OUString &rWarning ) const; + bool showWarning( const rtl::OUString &rWarning, const rtl::OUString& rBtnText_1, const rtl::OUString& rBtnText_2 ) const; + bool showOverwriteWarning( const rtl::OUString &rFileName ) const; bool showOverwriteWarning() const; // Allows runtime exceptions to be thrown by const methods diff --git a/extensions/source/update/check/updatehdl.src b/extensions/source/update/check/updatehdl.src index d371a80b33cb..58f88b7e4852 100644 --- a/extensions/source/update/check/updatehdl.src +++ b/extensions/source/update/check/updatehdl.src @@ -122,6 +122,21 @@ String RID_UPDATE_STR_OVERWRITE_WARNING Text [ en-US ] = "A file with that name already exists! Do you want to overwrite the existing file?"; }; +String RID_UPDATE_STR_RELOAD_WARNING +{ + Text [ en-US ] = "A file with the name '%FILENAME' already exists in '%DOWNLOAD_PATH'! Do you want to continue with the download or delete and reload the file?"; +}; + +String RID_UPDATE_STR_RELOAD_RELOAD +{ + Text [ en-US ] = "Reload File"; +}; + +String RID_UPDATE_STR_RELOAD_CONTINUE +{ + Text [ en-US ] = "Continue"; +}; + String RID_UPDATE_STR_PERCENT { Text [ en-US ] = "%PERCENT%";