2023-07-01 17:54:53 +01:00
# include "stdafx.h"
# include "AddonManager.h"
# include "SandMan.h"
# include "OnlineUpdater.h"
# include "../MiscHelpers/Common/Common.h"
# include "../MiscHelpers/Common/OtherFunctions.h"
# include <QUrlQuery>
# include <QJsonDocument>
# include <QJsonObject>
2023-07-01 18:24:48 +01:00
# include "../QSbieAPI/Sandboxie/SbieTemplates.h"
2023-07-01 17:54:53 +01:00
# include <QtConcurrent>
2023-07-30 13:28:35 +01:00
# include "../../SandboxieTools/UpdUtil/UpdUtil.h"
2023-07-01 17:54:53 +01:00
# include <Windows.h>
CAddonManager : : CAddonManager ( QObject * parent )
: QObject ( parent )
{
}
2023-07-01 20:24:12 +01:00
void CAddonManager : : UpdateAddonsWhenNotCached ( )
{
QVariantMap Data = theGUI - > m_pUpdater - > GetUpdateData ( ) ;
if ( ! Data . isEmpty ( ) & & Data . contains ( " addons " ) & & theGUI - > m_pUpdater - > GetLastUpdateTime ( ) > QDateTime : : currentDateTime ( ) . addDays ( - 1 ) ) {
OnUpdateData ( Data , QVariantMap ( ) ) ;
return ;
}
2023-07-30 13:28:35 +01:00
else if ( ! m_KnownAddons . isEmpty ( ) ) {
QFileInfo info ( theConf - > GetConfigDir ( ) + " / " ADDONS_FILE ) ;
2023-07-01 20:24:12 +01:00
if ( info . birthTime ( ) > QDateTime : : currentDateTime ( ) . addDays ( - 1 ) )
return ;
}
UpdateAddons ( ) ;
}
2023-07-01 17:54:53 +01:00
void CAddonManager : : UpdateAddons ( )
{
theGUI - > m_pUpdater - > GetUpdates ( this , SLOT ( OnUpdateData ( const QVariantMap & , const QVariantMap & ) ) ) ;
}
void CAddonManager : : OnUpdateData ( const QVariantMap & Data , const QVariantMap & Params )
{
if ( Data . isEmpty ( ) | | Data [ " error " ] . toBool ( ) )
return ;
QVariantMap Addons = Data [ " addons " ] . toMap ( ) ;
QJsonDocument doc ( QJsonValue : : fromVariant ( Addons ) . toObject ( ) ) ;
2023-07-30 13:28:35 +01:00
QFile : : remove ( theConf - > GetConfigDir ( ) + " / " ADDONS_FILE ) ;
WriteStringToFile ( theConf - > GetConfigDir ( ) + " / " ADDONS_FILE , doc . toJson ( ) ) ;
2023-07-01 17:54:53 +01:00
LoadAddons ( ) ;
emit DataUpdated ( ) ;
}
2023-07-30 13:28:35 +01:00
QList < CAddonInfoPtr > CAddonManager : : GetAddons ( )
2023-07-01 17:54:53 +01:00
{
2023-07-30 13:28:35 +01:00
if ( m_KnownAddons . isEmpty ( ) ) {
2023-07-01 17:54:53 +01:00
if ( ! LoadAddons ( ) )
UpdateAddons ( ) ;
}
2023-07-30 13:28:35 +01:00
QMap < QString , CAddonInfoPtr > Addons ;
m_Installed . clear ( ) ;
QDir Dir ( theAPI - > GetSbiePath ( ) + ADDONS_PATH ) ;
foreach ( const QFileInfo & Info , Dir . entryInfoList ( QStringList ( ) < < " *.json " , QDir : : Files | QDir : : Hidden | QDir : : System ) ) {
QString AddonPath = theAPI - > GetSbiePath ( ) + ADDONS_PATH + Info . fileName ( ) ;
QString AddonStr = ReadFileAsString ( AddonPath ) ;
QVariantMap Data = QJsonDocument : : fromJson ( AddonStr . toUtf8 ( ) ) . toVariant ( ) . toMap ( ) ;
m_Installed . append ( CAddonPtr ( new CAddon ( Data ) ) ) ;
Addons . insert ( Data [ " id " ] . toString ( ) . toLower ( ) , CAddonInfoPtr ( new CAddonInfo ( Data , true ) ) ) ;
}
foreach ( const CAddonPtr & pAddon , m_KnownAddons ) {
CAddonInfoPtr & pInfo = Addons [ pAddon - > Id . toLower ( ) ] ;
if ( pInfo . isNull ( ) ) {
bool Installed = false ;
QString Key = pAddon - > GetSpecificEntry ( " uninstallKey " ) . toString ( ) ;
if ( ! Key . isEmpty ( ) ) {
QSettings settings ( Key , QSettings : : NativeFormat ) ;
QString Uninstall = settings . value ( " UninstallString " ) . toString ( ) ;
if ( ! Uninstall . isEmpty ( ) ) {
Installed = true ;
m_Installed . append ( CAddonPtr ( new CAddon ( pAddon - > Data ) ) ) ;
}
}
pInfo = CAddonInfoPtr ( new CAddonInfo ( pAddon - > Data , Installed ) ) ;
}
else if ( pInfo - > Data [ " version " ] ! = pAddon - > Data [ " version " ] )
pInfo - > UpdateVersion = pAddon - > Data [ " version " ] . toString ( ) ;
2023-07-01 17:54:53 +01:00
}
2023-07-30 13:28:35 +01:00
return Addons . values ( ) ;
2023-07-01 17:54:53 +01:00
}
bool CAddonManager : : LoadAddons ( )
{
2023-07-30 13:28:35 +01:00
m_KnownAddons . clear ( ) ;
2023-07-01 17:54:53 +01:00
2023-07-30 13:28:35 +01:00
QString AddonPath = theConf - > GetConfigDir ( ) + " / " ADDONS_FILE ;
QString AddonStr = ReadFileAsString ( AddonPath ) ;
QVariantMap Data = QJsonDocument : : fromJson ( AddonStr . toUtf8 ( ) ) . toVariant ( ) . toMap ( ) ;
foreach ( const QVariant vAddon , Data [ " list " ] . toList ( ) )
m_KnownAddons . append ( CAddonPtr ( new CAddon ( vAddon . toMap ( ) ) ) ) ;
return ! m_KnownAddons . isEmpty ( ) ;
2023-07-01 17:54:53 +01:00
}
2023-07-30 13:28:35 +01:00
CAddonPtr CAddonManager : : GetAddon ( const QString & Id , EState State )
2023-07-01 17:54:53 +01:00
{
2023-07-30 13:28:35 +01:00
if ( State ! = eNotINstalled )
{
foreach ( const CAddonPtr & pAddon , m_Installed ) {
if ( pAddon - > Id . compare ( Id , Qt : : CaseInsensitive ) = = 0 )
return pAddon ;
}
}
2023-07-01 17:54:53 +01:00
2023-07-30 13:28:35 +01:00
if ( State ! = eInstalled )
{
if ( m_KnownAddons . isEmpty ( ) )
LoadAddons ( ) ;
foreach ( const CAddonPtr & pAddon , m_KnownAddons ) {
if ( pAddon - > Id . compare ( Id , Qt : : CaseInsensitive ) = = 0 )
return pAddon ;
2023-07-01 17:54:53 +01:00
}
}
return CAddonPtr ( ) ;
}
2023-07-30 13:28:35 +01:00
/*bool CAddonManager::CheckAddon(const CAddonPtr& pAddon)
2023-07-01 17:54:53 +01:00
{
2023-07-30 13:28:35 +01:00
QString Key = pAddon - > GetSpecificEntry ( " uninstallKey " ) . toString ( ) ;
2023-07-01 17:54:53 +01:00
if ( ! Key . isEmpty ( ) ) {
QSettings settings ( Key , QSettings : : NativeFormat ) ;
QString Uninstall = settings . value ( " UninstallString " ) . toString ( ) ;
return ! Uninstall . isEmpty ( ) ;
}
2023-07-30 13:28:35 +01:00
/ * QStringList Files = pAddon - > GetSpecificEntry ( " files " ) . toStringList ( ) ;
2023-07-01 17:54:53 +01:00
foreach ( const QString & File , Files ) {
if ( theGUI - > GetCompat ( ) - > CheckFile ( ExpandPath ( File ) ) )
return true ;
}
2023-07-30 13:28:35 +01:00
return false ; * /
QString AddonFile = theAPI - > GetSbiePath ( ) + ADDONS_PATH + pAddon - > Id + " .json " ;
return QFile : : exists ( AddonFile ) ;
} */
2023-07-01 17:54:53 +01:00
SB_PROGRESS CAddonManager : : TryInstallAddon ( const QString & Id , QWidget * pParent , const QString & Prompt )
{
if ( QMessageBox ( " Sandboxie-Plus " , Prompt . isEmpty ( ) ? tr ( " Do you want to download and install %1? " ) . arg ( Id ) : Prompt ,
QMessageBox : : Question , QMessageBox : : Yes | QMessageBox : : Default , QMessageBox : : No | QMessageBox : : Escape , QMessageBox : : NoButton , pParent ? pParent : theGUI ) . exec ( ) ! = QMessageBox : : Yes )
return SB_ERR ( SB_OtherError ) ;
SB_PROGRESS Status = InstallAddon ( Id ) ;
if ( Status . GetStatus ( ) = = OP_ASYNC )
theGUI - > AddAsyncOp ( Status . GetValue ( ) , false , tr ( " Installing: %1 " ) . arg ( Id ) , pParent ) ;
else
theGUI - > CheckResults ( QList < SB_STATUS > ( ) < < Status , pParent ) ;
return Status ;
}
SB_PROGRESS CAddonManager : : TryRemoveAddon ( const QString & Id , QWidget * pParent )
{
if ( QMessageBox ( " Sandboxie-Plus " , tr ( " Do you want to remove %1? " ) . arg ( Id ) ,
QMessageBox : : Question , QMessageBox : : Yes | QMessageBox : : Default , QMessageBox : : No | QMessageBox : : Escape , QMessageBox : : NoButton , pParent ? pParent : theGUI ) . exec ( ) ! = QMessageBox : : Yes )
return SB_ERR ( SB_OtherError ) ;
SB_PROGRESS Status = RemoveAddon ( Id ) ;
if ( Status . GetStatus ( ) = = OP_ASYNC )
theGUI - > AddAsyncOp ( Status . GetValue ( ) , false , tr ( " Removing: %1 " ) . arg ( Id ) , pParent ) ;
else
theGUI - > CheckResults ( QList < SB_STATUS > ( ) < < Status , pParent ) ;
return Status ;
}
2023-07-30 13:28:35 +01:00
SB_PROGRESS CAddonManager : : InstallAddon ( const QString & Id )
{
CAddonPtr pAddon = GetAddon ( Id , eNotINstalled ) ;
if ( ! pAddon )
return SB_ERR ( SB_OtherError , QVariantList ( ) < < tr ( " Addon not found, please try updating the addon list in the global settings! " ) ) ;
QFile : : remove ( theGUI - > m_pUpdater - > GetUpdateDir ( true ) + " / " ADDONS_FILE ) ;
QFile : : copy ( theConf - > GetConfigDir ( ) + " / " ADDONS_FILE , theGUI - > m_pUpdater - > GetUpdateDir ( true ) + " / " ADDONS_FILE ) ;
QStringList Params ;
Params . append ( " modify " ) ;
Params . append ( " add: " + pAddon - > Id ) ;
Params . append ( " /agent_arch: " + GetAppArch ( ) ) ;
Params . append ( " /framework: " + GetFramework ( ) ) ;
Params . append ( " /step:apply " ) ;
Params . append ( " /embedded " ) ;
Params . append ( " /temp: " + theGUI - > m_pUpdater - > GetUpdateDir ( ) . replace ( " / " , " \\ " ) ) ;
pAddon - > pProgress = CSbieProgressPtr ( new CSbieProgress ( ) ) ;
QtConcurrent : : run ( CAddonManager : : RunUpdaterAsync , pAddon , Params ) ;
//QTimer::singleShot(10, this, [=]() { CAddonManager::RunUpdaterAsync(pAddon, Params); });
return SB_PROGRESS ( OP_ASYNC , pAddon - > pProgress ) ;
}
2023-07-01 17:54:53 +01:00
SB_PROGRESS CAddonManager : : RemoveAddon ( const QString & Id )
{
2023-07-30 13:28:35 +01:00
CAddonPtr pAddon = GetAddon ( Id , eInstalled ) ;
2023-07-01 17:54:53 +01:00
if ( ! pAddon )
return SB_ERR ( SB_OtherError , QVariantList ( ) < < tr ( " Addon not found! " ) ) ;
2023-07-30 13:28:35 +01:00
QStringList Params ;
Params . append ( " modify " ) ;
Params . append ( " remove: " + pAddon - > Id ) ;
Params . append ( " /step:apply " ) ;
Params . append ( " /embedded " ) ;
2023-07-01 17:54:53 +01:00
pAddon - > pProgress = CSbieProgressPtr ( new CSbieProgress ( ) ) ;
2023-07-30 13:28:35 +01:00
QtConcurrent : : run ( CAddonManager : : RunUpdaterAsync , pAddon , Params ) ;
//QTimer::singleShot(10, this, [=]() { CAddonManager::RunUpdaterAsync(pAddon, Params); });
2023-07-01 17:54:53 +01:00
return SB_PROGRESS ( OP_ASYNC , pAddon - > pProgress ) ;
}
2023-07-30 13:28:35 +01:00
QString GetUpdErrorStr ( int exitCode ) ;
QString GetUpdErrorStr2 ( int exitCode )
2023-07-01 17:54:53 +01:00
{
2023-07-30 13:28:35 +01:00
switch ( exitCode )
2023-07-01 17:54:53 +01:00
{
2023-07-30 13:28:35 +01:00
case ERROR_NO_ADDON : return CAddonManager : : tr ( " Addon Not Found " ) ;
case ERROR_NO_ADDON2 : return CAddonManager : : tr ( " Addon is not available for this paltform " ) ;
case ERROR_BAD_ADDON : return CAddonManager : : tr ( " Missing instalation instructions " ) ;
case ERROR_BAD_ADDON2 : return CAddonManager : : tr ( " Executing addon setup failed " ) ;
case ERROR_DELETE : return CAddonManager : : tr ( " Failed to delete a file during addon removal " ) ;
default : return GetUpdErrorStr ( exitCode ) ;
2023-07-01 17:54:53 +01:00
}
}
2023-07-30 13:28:35 +01:00
void CAddonManager : : RunUpdaterAsync ( CAddonPtr pAddon , const QStringList & Params )
2023-07-01 17:54:53 +01:00
{
2023-07-30 13:28:35 +01:00
# ifdef _DEBUG
CSbieResult < int > Status = COnlineUpdater : : RunUpdater ( Params , false , true ) ;
# else
CSbieResult < int > Status = COnlineUpdater : : RunUpdater ( Params , true , true ) ;
# endif
2023-07-01 17:54:53 +01:00
2023-07-30 13:28:35 +01:00
if ( Status . IsError ( ) )
pAddon - > pProgress - > Finish ( SB_ERR ( SB_OtherError , QVariantList ( ) < < tr ( " Updater failed to to perform plugin operation " ) ) ) ;
else if ( Status . GetValue ( ) < 0 )
pAddon - > pProgress - > Finish ( SB_ERR ( SB_OtherError , QVariantList ( ) < < tr ( " Updater failed to to perform plugin operation, error: %1 " ) . arg ( GetUpdErrorStr2 ( Status . GetValue ( ) ) ) ) ) ;
2023-07-01 17:54:53 +01:00
else
2023-07-30 13:28:35 +01:00
pAddon - > pProgress - > Finish ( SB_OK ) ;
pAddon - > pProgress . clear ( ) ;
2023-07-01 17:54:53 +01:00
}
2023-07-30 13:28:35 +01:00
QString CAddonManager : : GetAppArch ( )
2023-07-01 17:54:53 +01:00
{
2023-07-30 13:28:35 +01:00
# ifdef _M_ARM64
return " a64 " ;
# elif _WIN64
return " x64 " ;
# else
return " x86 " ;
# endif
2023-07-01 17:54:53 +01:00
}
2023-07-30 13:28:35 +01:00
QString CAddonManager : : GetSysArch ( )
2023-07-01 17:54:53 +01:00
{
SYSTEM_INFO systemInfo ;
GetSystemInfo ( & systemInfo ) ;
switch ( systemInfo . wProcessorArchitecture )
{
case PROCESSOR_ARCHITECTURE_INTEL : return " x86 " ;
case PROCESSOR_ARCHITECTURE_AMD64 : return " x64 " ;
case PROCESSOR_ARCHITECTURE_ARM64 : return " a64 " ;
}
2023-07-30 13:28:35 +01:00
return GetAppArch ( ) ; // fallback
2023-07-01 17:54:53 +01:00
}
2023-07-30 13:28:35 +01:00
QString CAddonManager : : GetFramework ( )
2023-07-01 17:54:53 +01:00
{
2023-07-30 13:28:35 +01:00
QString qt = QString ( " qt%1.%2.%3 " ) . arg ( QT_VERSION_MAJOR ) . arg ( QT_VERSION_MINOR ) . arg ( QT_VERSION_PATCH ) ;
# ifdef _DEBUG
qt . append ( " d " ) ;
# endif // _DEBUG
qt . append ( " _ " + GetAppArch ( ) ) ;
return qt ;
}
2023-07-01 17:54:53 +01:00
2023-07-30 13:28:35 +01:00
QVariant CAddon : : GetSpecificEntry ( const QString & Name , QString * pName )
{
2023-07-01 17:54:53 +01:00
//
// First we check the qt cpecific entry for our version of qt and platform
//
2023-07-30 13:28:35 +01:00
QString qt = CAddonManager : : GetFramework ( ) ;
2023-07-01 17:54:53 +01:00
# ifdef _DEBUG
qt . append ( " d " ) ;
# endif // _DEBUG
2023-07-30 13:28:35 +01:00
if ( Data . contains ( Name + " - " + qt ) ) {
if ( pName ) * pName = Name + " - " + qt ;
return Data [ Name + " - " + qt ] ;
2023-07-01 17:54:53 +01:00
}
//
// Second we check the actual architecture
//
2023-07-30 13:28:35 +01:00
QString match = Data [ " matchArch " ] . toString ( ) ;
QString arch = match ! = " agent " ? CAddonManager : : GetSysArch ( ) : CAddonManager : : GetAppArch ( ) ;
if ( Data . contains ( Name + " - " + arch ) ) {
if ( pName ) * pName = Name + " - " + arch ;
return Data [ Name + " - " + arch ] ;
2023-07-01 17:54:53 +01:00
}
//
// last we try the unsoecific entry
//
if ( Data . contains ( Name ) ) {
if ( pName ) * pName = Name ;
return Data [ Name ] ;
}
return QString ( ) ;
}
2023-07-30 13:28:35 +01:00
QString CAddonInfo : : GetLocalizedEntry ( const QString & Name )
2023-07-01 17:54:53 +01:00
{
if ( Data . contains ( Name + " _ " + theGUI - > m_Language ) )
return Data [ Name + " _ " + theGUI - > m_Language ] . toString ( ) ;
QString LangAux = theGUI - > m_Language ; // Short version as fallback
LangAux . truncate ( LangAux . lastIndexOf ( ' _ ' ) ) ;
if ( Data . contains ( Name + " _ " + LangAux ) )
return Data [ Name + " _ " + LangAux ] . toString ( ) ;
return Data [ Name ] . toString ( ) ;
2023-07-30 13:28:35 +01:00
}